[
  {
    "path": ".github/workflows/update-externals.yml",
    "content": "name: Update external pages\non:\n  schedule:\n    - cron: '30 1 * * 4'\n  workflow_dispatch:\njobs:\n  update:\n    runs-on: ubuntu-latest\n    timeout-minutes: 15\n    steps:\n      - name: Clone repository\n        uses: actions/checkout@v2\n\n      - name: Install dependencies\n        run: |\n          sudo apt-get update\n          sudo apt-get install -y ruby-bundler\n\n      - name: Run update script\n        run: _scripts/update-external-docs.rb\n\n      - name: Create pull request\n        uses: peter-evans/create-pull-request@v3\n        with:\n          title: Update external docs\n          body: ''\n          commit-message: Update external docs\n          # do *not* use any suffix here -- if there is an open unreviewed PR,\n          # we want to force-push to that, not create a new one\n          branch: update-externals\n"
  },
  {
    "path": ".gitignore",
    "content": "_site\n.gem\n.sass-cache\n.jekyll-metadata\n*.pyc\n*.sw?\n*~\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: ruby\nrvm:\n- 2.1\nscript: \"bundle exec jekyll build\"\n"
  },
  {
    "path": ".well-known/org.flathub.VerifiedApps.txt",
    "content": "d57c9cbd-223d-40cf-91f0-eda43b53cb8b\n"
  },
  {
    "path": "404.md",
    "content": "---\ntitle: Document Not Found\nindex: false\npermalink: /404.html\n---\n\n{% include search.html %}\n\n<script>$(function(){ trigger404(\"{{ site.baseurl }}\"); });</script>\n"
  },
  {
    "path": "CNAME",
    "content": "cockpit-project.org"
  },
  {
    "path": "Gemfile",
    "content": "source \"https://rubygems.org\"\nruby RUBY_VERSION\n\n# Hello! This is where you manage which Jekyll version is used to run.\n# When you want to use a different version, change it below, save the\n# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:\n#\n#     bundle exec jekyll serve\n#\n# This will help ensure the proper Jekyll version is running.\n# Happy Jekylling!\n\n# To upgrade, run `bundle update github-pages`.\ngem \"github-pages\", group: :jekyll_plugins\n\n# This is the default theme for new Jekyll sites. You may change this to anything you like.\ngem \"minima\"\n\n# Ruby 3.x doesn't have webrick; so it needs to be manually added\n# https://github.com/github/pages-gem/issues/752#issuecomment-764647862\ngem \"webrick\"\n\n# Squelch Jekyll run's faraday message by installing the gem it recommends\ngem \"faraday-retry\"\n\n# CSV is no longer part of Ruby; it needs to explicitly be included\ngem \"csv\"\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\nCopyright (c) 2015, 2016 Garrett LeSage & Red Hat, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Cockpit Project Website\n\n[The Cockpit project website](https://cockpit-project.org/) is based on Springboard, which is a MIT-licensed preconfigured build of Jekyll, used for starting up a site quickly.\n\nThis repository manages the content and presentation of the Cockpit project's website, including blog articles, release notes, the Cockpit guide, and screenshots.\n\nFor more details on Springboard, see [jekyll-springboard](https://github.com/garrett/jekyll-springboard).\n\n## Get Started\n\n### Using a Podman container\n\n#### Setting up the container for the first time\n\n0. Install Podman (if you haven't already; it's preinstalled with Silverblue and available elsewhere). Depending on your distribution, use `sudo dnf install podman` or `sudo apt install podman`\n1. Create the container and install the dependencies with:\n   `_scripts/container-create`\n\n#### Initial setup on Windows\n\nRunning the container is possible on Windows by running a podman container in [Windows Subsystem for Linux](https://learn.microsoft.com/en-us/windows/wsl/install):\n\n0. Install some Linux distribution (Ubuntu is the default): `wsl --install`\n1. Clone the repository to your Linux filesystem `/home/<username>`\n2. You can now follow the instructions for Linux, inside your WSL2 Linux environment\n\n#### Running the Jekyll server locally\n\nRun the website locally using Jekyll with:\n\n1. `_scripts/container-jekyll`\n2. Visit <http://127.0.0.1:4000/>\n\nYou can pass arguments to the `container-jekyll` command. To see everything available, pass `--help`.\nThe most useful arguments are:\n- `-I` for incremental, which speeds up page compilation by recompiling only parts that have changed\n- `-l` for livereload, which updates the browser when parts of the page change\n\nSo, for instant rendering of local changes, you'd run:\n\n- `_scripts/container-jekyll -Il`\n\n#### Updating when Gemfile / Gemfile.lock changes\n\n1. `_scripts/container-update-gems`\n\n#### Deleting the container\n\n1. `_scripts/container-delete`\n\nThis removes the container and the local `.gem` directory.\n\n### Installing locally without a container\n\nIn order to convert content into web pages, you will need to have Ruby, Bundler, and Jekyll installed.\n\n1. Install Ruby & Bundler (as root):\n\n   _Note: To become root, you must either run `su` or `sudo -s`_\n\n   * **Fedora** / **RHEL** / **CentOS**:\n     ```\n     dnf install -y rubygem-bundler ruby-devel libffi-devel make gcc gcc-c++ \\\n     redhat-rpm-config zlib-devel libxml2-devel libxslt-devel tar nodejs\n     ```\n\n   * **openSUSE**:\n     ```\n     zypper install ruby2.1-rubygem-bundler ruby2.1-devel make gcc-c++ \\\n     libxml2-devel libxslt-devel tar\n     ```\n     \n   * **Debian** / **Ubuntu**:\n     ```\n     apt update && apt install bundler zlib1g-dev\n     ```\n\n   * **macOS** / **OS X**:\n   \n     _Note: First, you must install Mac developer tools. Then, run the following:_\n     \n     ```\n     gem update --system\n     gem install bundler\n     ```\n\n2. Configure bundler to work as a user:\n   ```\n   bundle config path ~/.gem\n   ```\n\n3. Install gems (as user):\n   ```\n   bundle install\n   ```\n\n4. Run Jekyll:\n   ```\n   bundle exec jekyll server\n   ```\n\n## Work with the Site\n\nAs this site scaffolding is built on Jekyll, most all Jekyll documentation applies.\n\nUseful references:\n- [the official Jekyll documentation](http://jekyllrb.com/docs/home/)\n- [CloudCannon Jekyll tutorials](https://learn.cloudcannon.com/)\n\n### Release Notes\n\nRelease notes are in the form of a Markdown-formatted blog post, and are located in `_posts` with the date and URL slug as parts of the filename.\n\nFor more details, read [the section on blog posts](#blog-posts).\n\n### Frontmatter\n\nFrontmatter is embedded YAML, included in every document Jekyll processes. If the Frontmatter YAML is left out, Jekyll will not process the file, and will merely copy it out, unprocessed, to the output `_site` sub-directory.\n\nExample Markdown file with Frontmatter (at the top):\n\n```markdown\n---\ntitle: This is a blog post!\ndate: 2017-04-01\nauthor: reedrichards\ntags: foo bar baz\ncategory: selfpost\n---\n\nHi everyone! Welcome to my first blog post!\n```\n\nThe author should be a nickname (ideally) and you should fill out information in the `_data/authors.yml` file.\n\nBlog posts _need_ Frontmatter with most of the above fields. The fields for `tags` and `category` are optional. All other files that are to be processed by Jekyll should have at least the opening and closing Frontmatter lines (the two triple dashes `---`), and should _probably_ at least include the `title` as well.\n\n### Markdown\n\nJekyll uses Markdown... specifically, GitHub-flavored Markdown via Kramdown.\n\nYou're able to use all Markdown conventions that GitHub adds on top (including tables, etc.) and also able to add in classes and IDs (among other things) thanks to Kramdown.\n\nIn addition, Jekyll uses what's called \"Liquid\" tags for simple logic and flow control. (Variables, if/then/else, loops, etc.) Liquid is supported not just in HTML and what Jekyll considers plaintext (JSON, XML, etc.), but also in Markdown.\n\nIf you would like to mix Markdown with a bit more advanced layout, you may want to consider capture blocks with Markdown rendering in Liquid tags. It looks like this (using a simple [Grlidlex](http://gridlex.devlint.fr/) grid):\n\n```markdown\n{% capture intro %}\n## Intro title here\n\nA list:\n\n1. Item 1\n2. Item 2\n{% endcapture %}\n\n{% capture details %}\nSome other information to the side...\n{% endcapture %}\n\n<section class=\"grid\">\n  <div class=\"col\">{{ intro | markdownify }}</div>\n  <div class=\"col\">{{ details | markdownify }}</div>\n</section>\n```\n\nThis allows you to mix-and-match content in pure Markdown with a bit of HTML for more advanced layout. Generally, you'll want to just keep eveything in pure Markdown and keep this technique for special pages (such as landing pages or anything that needs to be a little more complex).\n\n### Liquid\n\n[Liquid is a templating language](https://shopify.github.io/liquid/) originally made by Shopify and included in Jekyll by default.\n\nThere are basically two types of Liquid tags:\n1. Objects, which look like `{{ objectname }}`\n2. Tags look similar to objects, but instead of using double brackets, tags use percent signs. `{% tagname %}`\n\nBoth objects and tags take filters, which is written as a pipe followed by a directive. Filters can (sometimes optionally) take arguments as well, and can also be chained.\n\nSimple example (the assignment is a bit silly here, but important to point out):\n\n```liquid\n{% if person %}\n  {% assign role = person.job_title | capitalize %}\n\n  Hello, {{ person.name }}!\n\n  How long have you worked at {{ role }}?\n{% endif %}\n```\n\nPlease note that whitespace shows up in files. This usually doesn't matter much for HTML, but can matter a lot for XML or JSON (especially if the generated file loops and becomes large). Workarounds include breaking up Liquid tags over multiple lines and using throw-away capture groups for assignments.\n\nSpace-reducing example (mainly useful for loops):\n\n```liquid\n{%\n  if foo\n    %}{{\n      foo.bar\n      | split: \"::\"\n      | join: \", \"\n      | strip\n    }}{%\n  endif\n%}\n```\n\n- [Official Liquid documentation](https://shopify.github.io/liquid/basics/introduction/)\n- [Jekyll Cheat Sheet](https://learn.cloudcannon.com/jekyll-cheat-sheet/) — Jekyll-specific liquid tags\n- [Liquid for Designers](https://github.com/Shopify/liquid/wiki/Liquid-for-Designers) — an excellent overview on how to use Liquid tags in documents (both Markdown and HTML)\n\n### Blog Posts\n\nAll blog posts belong in the `_posts` directory and must be formatted with the year, slug (usually a shortened title, used as part of the URL), and extension. This look like `2017-04-01-welcome-to-the-blog.md`\n\nIn addition, every blog post needs to have Frontmatter including the fields `title` and `date` (which should be the same as the filename's date) and should also include `author` to give the person credit (as well as to show up under the author on the authors page). In addition, a blog post may have `tags` and a `category`, but they're not necessary (only suggested).\n\nTo make this process easier we have `_scripts/generate-release-notes` which will take release notes from all our Cockpit repos and generate a blog post for you.\n\n```bash\n_scripts/generate-release-notes --user YourAuthorName\n```\n\nFor all arguments check `--help` section\n\n```bash\n_scripts/generate-release-notes --help\n```\n\n\n#### Blog Authors\n\nWhile not necessary, it is suggested to use nicknames for authors in the Frontmatter of blog posts.\n\nThere's a bit of logic in the blog post code that uses information from a `_data/authors.yml` file if it exists.\n\nThe format for an authors file looks like this:\n\n```yaml\ndefault:\n  name: Site Admin\n\nexample:\n  name: Ann Example\n  twitter: example\n  googleplus: somegoogleaccount\n  facebook: somefacebookaccount\n  gravatar: 5658ffccee7f0ebfda2b226238b1eb6e\n  description: |\n    This is an example author. To get a gravatar, do something like:\n    echo -n email@example.com | md5sum\n\nreedrichards:\n  name: 'Reed \"Fantastic\" Richards'\n  twitter: MrFantastic__\n  description: |\n    Along with a few of my friends, I was blasted by cosmic radiation,\n    and now I'm super bendy and stretchy.\n\n    We fight crime.\n```\n\nIn the above snippet, `default`, `example`, and `reedrichards` are nicknames that are used in the blog posts. All fields are optional, but you'll probably at least want a `name`.\n\nNote that some characters need to be escaped in quote marks. In the above snipped, the word __\"Fantastic\"__ has quotes around it, so it has single quotes around the string. In most cases, you can leave out the quote strings, but if in doubt, go ahead and wrap the string in quotes.\n\n### Navigation\n\nNavigation is controlled by a `_data/navigation.yml` file, if it exists.\n\nSimply add navigation info in the correct format and your site will take care of all the navigation needs for you, including highlighting the current page.\n\n```yaml\n- title: Home\n  url: \"/\"\n\n- title: Software\n  url: /software/\n\n- title: Standards\n  url: /standards/\n\n- title: Search\n  url: /search/\n```\n\nNote that the URL to \"/\" is in quotes. This is necessary, due to YAML. The other `title`s and `url`s skip quoting and still work, however.\n\nYou can even get fancy and add sub-navigation if you want to (although you probably shouldn't, for usability reasons):\n\n```yaml\n- title: About\n  url: /about/\n  nav:\n    - title: Things\n      url: /about/things/\n    - title: FAQ\n      url: /about/faq/\n      nav:\n        - title: Test1\n          url: /test1\n        - title: Test2\n          url: /test2\n```\n\n### Customization\n\nSite customization happens mainly in two places: `_config.yml` and `assets/site.scss` (or `assets/site.sass`). By default, the site CSS file doesn't exist, so you'll need to create it.\n\n#### Config YAML\n\nThe `_config.yaml` file is pretty straightforward. It has a configuration by default that makes things work locally in a similar manner to how GitHub Pages works.\n\nFor more details on the `_config.yaml` file, [read Jekyll's documentation](https://jekyllrb.com/docs/configuration/).\n\n#### Custom CSS\n\nCreating the custom site CSS is easy. Run one of the following commands:\n\n- If you're using **SCSS**: `cp assets/default.scss assets/site.scss`\n- If you'd rather use **SASS**: `sass-convert assets/default.scss assets/site.sass`\n\n_**Note**: If you convert the default file to SASS, the comments about turning on and off imports will be in the wrong place. Thankfully, editing the comments is an easy one-time fix._\n\nNext step is to edit the site scss/sass file.\n\nInside the file, you'll see a bunch of variables at the top and a whole lot of imports underneith. The variables are pretty self explanitory, and let you quickly tweak the look of your site without having to actually edit CSS. Imports are there to include special styling for your site. A good set of defaults are turned on, but you can turn on and off several by uncommenting to turn on or commenting (or deleting) to turn off various styles.\n\nAdd any custom style specific to your site below all the imports.\n\n#### Custom Logo\n\nDrop your logo, preferably in SVG format, in the images directory. Call it `logo.svg` (or `logo.png` if you don't have it available in SVG). That's it! Done!\n\n### Directory structure\n\nExporting rule of thumb: Directories and files starting with an underscore are seen by Jekyll (and some are vital in most Jekyll codebases, such as `_layouts`), but are not included in the output.\n\n- **`_data`** — [Data files](http://jekyllrb.com/docs/datafiles/), in YAML (`yml`) or JSON format. Referenced in Liquid tags as `site.data.`_`FILENAME`_`.`_`DATA…`_.\n  - `navigation.yml` _(optional, but strongly recommended)_ — Navigation used across the site\n  - `authors.yml` _(optional, but recommended)_ — Information about blog authors\n\n- **`_includes`** — Partials used for inclusion in documents and layouts, useful for abstracting complex HTML & Liquid logic, especially when it may be reused across the site. Includes are invoked as `{% include FILENAME.html key=value %}` (key and value are optional, and can be anything — value itself can be a variable or a string enclosed in quotes).\n\n- **`_layouts`** — Templates for pages, especially HTML — most noteworthy layouts are `essential`, which is \"bare-bones\" HTML, and leaving `layout:` in Frontmatter blank for no layout at all (which is useful for JSON, XML, plain text, etc.).\n\n- **`_posts`** — Blog posts go here, in Markdown format. Posts should contain basic Frontmatter (YAML at the top of the file). The filename matters, too: `YYYY-MM-DD-your-post-short-title-in-lowercase.md`. For more information, please consult [the official Jekyll documentation on blog posts](http://jekyllrb.com/docs/posts/).\n\n- **`_site`** — Output of the Jekyll compilation process. This should not be checked into git (and is already in the `.gitignore`). On a clean git checkout, this directory does not exist.\n\n- **`assets`** — This is the place for CSS, JavaScript, and fonts. CoffeScript (`.coffee`) and SASS (`.sass`, `.scss`) are supported as Jekyll will process them to CSS and JavaScript, provided they have a Frontmatter directive (which can be empty, as in two immediate lines of three dashes `---`) for top-level processed files (files which are included via SASS includes need not — and even should not — have Frontmatter).\n  - **`fonts`** — Any fonts served locally should go here.\n  - **`lib`** — Custom CSS & JavaScript.\n  - **`vendor`** — Included CSS & JavaScript from other projects (such as jQuery, etc.)\n\n- **`blog`** — This is not the place for blog posts. It is, however, the place for files that make blogs work (the index file, author file, category files, feeds, etc.). In most cases, you don't need to touch what's here.\n\n- **`guide`** — Cockpit-specific guides, dumped as HTML and included in the website.\n  - **`latest`** — The latest guide. This is what the other pages should link. Other guides are included for posterity under their version number.\n\n- **`images`** — Images live here. These are the images blog posts and other pages usually link to.\n  - **`site`** — Site-specific images (various icons, logos, etc.) should be placed here.\n  - **`logo.svg`** — Logo file, in SVG. Using `logo.png` is also supported, but using an SVG is recommended.\n  - **`favicon.png`** — Large 512px square version of the site icon.\n  - **`favicon-small.png`** — Small 16px square version of the site icon.\n\n## Deployment\n\n### GitHub Pages\n\nIf you're deploying on GitHub using GitHub pages, all you need to do is:\n\n1. Click the \"Settings\" tables\n2. Scroll down to \"GitHub Pages\"\n3. Select \"Master branch\" (if it's not already selected)\n4. Click \"Save\"\n\nThe first time it sets up your pages may take several minutes. Please be patient.\n\n_**Tip**: If your development model has others fork this repo into their own personal namespace, they can follow these same directions to have their very own staging version of the site to demonstrate their changes._\n\n_**Note**: GitHub may complain about the CNAME _\"The CNAME cockpit-project.org is already taken\"_. This is just a warningverything is fine and it should still work._\n\n### Custom Deployment\n\nThe detailed process of deploying is outside of the scope of this document.\n\nA quick overview, however, would be to do something such as:\n\n1. Run `bundle exec jekyll build`\n2. Sync the results of the `_site` directory to your webhost via some means (rsync, sftp, etc.)\n"
  },
  {
    "path": "_config.yml",
    "content": "# Welcome to Jekyll!\n#\n# This config file is meant for settings that affect your whole blog, values\n# which you are expected to set up once and rarely edit after that. If you find\n# yourself editing these this file very often, consider using Jekyll's data files\n# feature for the data you need to update frequently.\n#\n# For technical reasons, this file is *NOT* reloaded automatically when you use\n# 'jekyll serve'. If you change this file, please restart the server process.\n\n# Site settings\n# These are used to personalize your new site. If you look in the HTML files,\n# you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.\n# You can create any custom variable you would like, and they will be accessible\n# in the templates via {{ site.myvariable }}.\ntitle: Cockpit Project\n#email: your-email@domain.com\ndescription: > # this means to ignore newlines until \"baseurl:\"\n  Cockpit makes it easy to administer your Linux servers via a web browser.\n#baseurl: \"/cockpit\" # the subpath of your site, e.g. /blog\n#url: \"http://example.com\" # the base hostname & protocol for your site\n#twitter_username: jekyllrb\n#github_username:  jekyll\n#repository: cockpit/cockpit-website\n\n#permalink: blog/:year/:month/:slug/\npermalink: blog/:slug.html\npaginate: 12\npaginate_path: \"/blog/page=:num\"\n\n# Publish articles with a date/time set in the future\nfuture: true\n\n# Ignore certain phrases from the blog listing (comma-separated)\nblog_ignore: \"We release regularly,Here are the release notes,Try it out,From the future,Note:,Cockpit is a user interface for servers\"\n\n# Summarize to blog content to headings?\nblog_summary_headings: true\n\n# Truncate blog summaries to this length\nblog_summary_length: 50\n\nlang: en\n\nlogo: /images/site/cockpit-logo.svg\ncolor: \"#3e5375\"\n\n# Build settings\nmarkdown: kramdown\ntheme: minima\n\n# YAML defaults for pages\ndefaults:\n  -\n    scope:\n      path: \"\"\n    values:\n      layout: \"page\"\n  -\n    scope:\n      path: _posts\n    values:\n      layout: \"post\"\n\n# GitHub builds with safe mode, so enable it for previewing locally too\nsafe: true\n\nexcerpt_separator: <!--BREAK-->\n\n# Don't compile these files/dirs into the website\nexclude:\n  - Gemfile\n  - Gemfile.lock\n  - README.md\n  - bin\n  - LICENSE\n\ninclude:\n  - _stylesheets\n  - _javascript\n  - assets/site.js\n  - .well-known\n\nsass:\n  sass_dir: assets/\n  style: compressed\n\n# Let the following Jekyll plugins work in safemode\n# (mimicking GitHub's config)\nplugins:\n  - jekyll-redirect-from\n  - jekyll-sass-converter\n  - jemoji\n  - jekyll-mentions\n  - jekyll-sitemap\n  - jekyll-feed\n  - jekyll-gist\n  - jekyll-paginate\n  - jekyll-coffeescript\n  - jekyll-seo-tag\n  - jekyll-github-metadata\n\nwhitelist:\n  - jekyll-redirect-from\n  - jekyll-sass-converter\n  - jemoji\n  - jekyll-mentions\n  - jekyll-sitemap\n  - jekyll-feed\n  - jekyll-gist\n  - jekyll-paginate\n  - jekyll-coffeescript\n  - jekyll-seo-tag\n  - jekyll-github-metadata\n"
  },
  {
    "path": "_data/applications.yml",
    "content": "# Entries here are displayed under their respective maintainer field.\n# If let unset it will be seen as third-party.\n# Available options are seen in maintainers.yml and for example be\n# - cockpit\n# - redhat\n# - suse\n\n# The Cockpit group is special, it inherits source, issues, license for the `source: cockpit` entries\ncockpit:\n  source: https://github.com/cockpit-project/cockpit/\n  issues: https://github.com/cockpit-project/cockpit/issues\n  license: LGPL 2.1\n  comment: |\n    This is the default template that \"source: cockpit\" pulls from, so source, issues, and license don't need to be filled out everywhere.\n\nstoraged:\n  title: Storage\n  package: cockpit-storaged\n  source: cockpit\n  maintainer: cockpit\n  description: |\n    Manage your system's storage. Supports local partitions, encryption, NFS, RAID, iSCSI, and more.\n\nnetworkmanager:\n  title: Network\n  package: cockpit-networkmanager\n  source: cockpit\n  maintainer: cockpit\n  description: |\n    Manage your network interfaces and edit your firewall with ease.\n\npackagekit:\n  title: Software Updates (PackageKit)\n  package: cockpit-packagekit\n  source: cockpit\n  maintainer: cockpit\n  description: |\n    See and apply updates to your system. Supports RPM and DEB based systems through PackageKit.\n\nostree:\n  title: Software Updates (OSTree)\n  package: cockpit-ostree\n  maintainer: cockpit\n  source: https://github.com/cockpit-project/cockpit-ostree\n  issues: https://github.com/cockpit-project/cockpit-ostree/issues\n  license: LGPL 2.1\n  description: |\n    Upgrade OSTree-based systems.\n\nmachines:\n  title: Virtual Machines\n  package: cockpit-machines\n  source: https://github.com/cockpit-project/cockpit-machines\n  issues: https://github.com/cockpit-project/cockpit-machines/issues\n  license: LGPL 2.1\n  maintainer: cockpit\n  description: |\n    Create, run, and manage virtual machines.\n\npodman:\n  title: Podman Containers\n  package: cockpit-podman\n  source: https://github.com/cockpit-project/cockpit-podman\n  issues: https://github.com/cockpit-project/cockpit-podman/issues\n  license: LGPL 2.1\n  maintainer: cockpit\n  description: |\n    Download, use, and manage containers. (Podman replaces Docker.)\n\nselinux:\n  title: SELinux\n  package: cockpit-selinux\n  source: cockpit\n  maintainer: cockpit\n  description: |\n    View and manage SELinux exceptions. Instantly apply overrides and export your rules to apply to other systems.\n\nkdump:\n  title: Kernel Dump\n  package: cockpit-kdump\n  source: cockpit\n  maintainer: cockpit\n  description: |\n    Debugging the Linux kernel? This `kdump` add-on helps with catching stack traces.\n\nimage-builder:\n  title: Cockpit Image Builder\n  package: cockpit-image-builder\n  source: https://github.com/osbuild/image-builder-frontend\n  issues: https://github.com/osbuild/image-builder-frontend/issues\n  maintainer: redhat\n  description: |\n    On-premise frontend for image building. It allows users to create, manage, and compose custom operating system images, with images stored locally.\n\nsosreport:\n  title: Diagnostic Reports\n  package: cockpit-sosreport\n  source: cockpit\n  maintainer: cockpit\n  description: |\n    Collect system configuration and diagnostic information from systems, to help with diagnosing problems.\n\nfiles:\n  title: Cockpit Files\n  package: cockpit-files\n  source: https://github.com/cockpit-project/cockpit-files\n  issues: https://github.com/cockpit-project/cockpit-files/issues\n  maintainer: cockpit\n  description: |\n    A featureful file browser.\n\n389-ds:\n  title: 389 Directory Server\n  package: cockpit-389-ds\n  homepage: https://directory.fedoraproject.org/docs/389ds/download.html\n  source:\n  maintainer: redhat\n  description: |\n    A web-based interface to the enterprise-class Open Source LDAP server for Linux.\n\nsession-recording:\n  title: Session Recording\n  package: cockpit-session-recording\n  source: https://github.com/Scribery/cockpit-session-recording\n  issues: https://github.com/Scribery/cockpit-session-recording/issues\n  maintainer: redhat\n  description: |\n    Session recording configuration and playback based on [Scribery](https://scribery.github.io/), to record a user's actions for watching later.\n\nsubscriptions:\n  title: Subscription Manager\n  package: subscription-manager-cockpit\n  source: https://github.com/cockpit-project/subscription-manager-cockpit\n  issues: https://github.com/cockpit-project/subscription-manager-cockpit/issues\n  maintainer: redhat\n  description: |\n    Manage subscriptions to Red Hat Enterprise Linux.\n\nha-cluster:\n  title: High Availability Cluster Management\n  package: cockpit-ha-cluster\n  source: https://github.com/ClusterLabs/pcs-web-ui\n  maintainer: redhat\n  description: |\n    Manage Pacemaker based clusters with [PCS](https://github.com/ClusterLabs/pcs).\n\n# leapp:\n#   package: cockpit-leap\n#   title: Leapp\n#   homepage: https://leapp.readthedocs.io/en/latest/\n#   source: https://github.com/oamg/leapp\n#   license: Apache 2\n#   issues: https://github.com/oamg/leapp/issues\n#   description: |\n#     Leapp is an OS and application modernization framework. It is used to upgrade Red Hat Enterprise Linux. (For example: Upgrading RHEL 7 to 8.)\n\nzfs:\n  title: ZFS Manager\n  package: cockpit-zfs\n  source: https://github.com/45Drives/cockpit-zfs\n  issues: https://github.com/45Drives/cockpit-zfs/issues\n  prerelease: false\n  description: |\n    Interactive ZFS on Linux administration.\n\nfile-sharing:\n  title: File Sharing\n  source: https://github.com/45Drives/cockpit-file-sharing\n  issues: https://github.com/45Drives/cockpit-file-sharing/issues\n  prerelease: false\n  description: |\n    Easily manage Samba and NFS file sharing.\n\nnavigator:\n  title: Navigator\n  source: https://github.com/45Drives/cockpit-navigator\n  issues: https://github.com/45Drives/cockpit-navigator/issues\n  prerelease: false\n  description: |\n    A featureful file browser.\n\nbenchmark:\n  title: Benchmark\n  source: https://github.com/45Drives/cockpit-benchmark\n  issues: https://github.com/45Drives/cockpit-benchmark/issues\n  prerelease: false\n  description: |\n    A storage benchmark utility.\n\ntukit:\n  title: Software Updates (transactional-update from OpenSUSE with tukit)\n  package: cockpit-tukit\n  maintainer: suse\n  source: https://github.com/openSUSE/cockpit-tukit\n  issues: https://github.com/openSUSE/cockpit-tukit/issues\n  license: LGPL 2.1\n  description: |\n    Upgrade systems based on transactional-update from OpenSUSE with tukit.\n\nsensors:\n  title: Sensors\n  package: cockpit-sensors\n  source: https://github.com/ocristopfer/cockpit-sensors\n  issues: https://github.com/ocristopfer/cockpit-sensors/issues\n  license: LGPL 2.1\n  description: |\n    List all available sensors on the machine provided by `lm-sensors`.\n\ntailscale:\n  title: Tailscale\n  package: cockpit-tailscale\n  prerelease: true\n  source: https://github.com/spotsnel/cockpit-tailscale\n  issues: https://github.com/spotsnel/cockpit-tailscale/issues\n  license: LGPL 2.1\n  description: |\n    Manage Tailscale.\n\nheadscale:\n  title: Headscale\n  package: cockpit-headscale\n  prerelease: true\n  source: https://github.com/spotsnel/cockpit-headscale\n  issues: https://github.com/spotsnel/cockpit-headscale/issues\n  license: LGPL 2.1\n  description: |\n    Manage Headscale coordination server.\n\ncloudflared:\n  title: Cloudflare tunnels\n  package: cockpit-cloudflared\n  prerelease: true\n  source: https://github.com/spotsnel/cockpit-cloudflared\n  issues: https://github.com/spotsnel/cockpit-cloudflared/issues\n  license: LGPL 2.1\n  description: |\n    Show Cloudflare tunnel state.\n\nrepos:\n  title: Manage Repositories\n  package: cockpit-repos\n  maintainer: suse\n  source: https://github.com/openSUSE/cockpit-repos\n  issues: https://github.com/openSUSE/cockpit-repos/issues\n  license: LGPL 2.1\n  description: |\n    Manage package manager repositories on SUSE/openSUSE systems\n\nsubscriptions-suse:\n  title: Subscription Manager\n  package: cockpit-subscriptions\n  maintainer: suse\n  source: https://github.com/openSUSE/cockpit-subscriptions\n  issues: https://github.com/openSUSE/cockpit-subscriptions/issues\n  license: LGPL 2.1\n  description: |\n    Manage your SUSE Linux Enterprise subscriptions.\n\npackages:\n  title: Packages\n  package: cockpit-packages\n  maintainer: suse\n  source: https://github.com/openSUSE/cockpit-packages\n  issues: https://github.com/openSUSE/cockpit-packages/issues\n  license: LGPL 2.1\n  description: |\n    Install/Uninstall packages.\n\nbootloader:\n  title: Bootloader\n  prerelease: true\n  package: cockpit-bootloader\n  maintainer: suse\n  source: https://github.com/openSUSE/cockpit-bootloader\n  issues: https://github.com/openSUSE/cockpit-bootloader/issues\n  license: LGPL 2.1\n  description: |\n    Manage bootloader configurations.\n\ndockermanager:\n  title: Docker Manager\n  prerelease: true\n  source: https://github.com/chrisjbawden/cockpit-dockermanager\n  issues: https://github.com/chrisjbawden/cockpit-dockermanager/issues\n  description: |\n    A lightweight interface for simple management of docker containers.\n\nbackblaze-b2:\n  title: Backblaze B2 backup\n  prerelease: false\n  source: https://github.com/rabol/backblaze-b2\n  issues: https://github.com/rabol/backblaze-b2/issues\n  description: |\n    A lightweight interface for simple back up to Backblaze B2.\n\nros2-diagnostics:\n  title: ROS 2 Diagnostics\n  package: cockpit-ros2-diagnostics\n  source: https://github.com/clearpathrobotics/cockpit-ros2-diagnostics\n  issues: https://github.com/clearpathrobotics/cockpit-ros2-diagnostics/issues\n  license: LGPL 2.1\n  description: |\n    View ROS 2 diagnostics.\n\npackage-manager:\n  title: Package Manager\n  source: https://github.com/hatlabs/cockpit-package-manager\n  issues: https://github.com/hatlabs/cockpit-package-manager/issues\n  license: LGPL 2.1\n  description: |\n    DEB (APT) / RPM browsing and installation tool using PackageKit.\n\nport-forward:\n  title: Port Forward Manager\n  source: https://github.com/kuznetz/cockpit-port-forward\n  issues: https://github.com/kuznetz/cockpit-port-forward/issues\n  license: MIT\n  description: |\n    Manage firewalld port forwarding rules and masquerading.\n\nsudo-manager:\n  title: Sudo Manager\n  source: https://github.com/josephoaks/Cockpit-SUDO-Manager\n  issues: https://github.com/josephoaks/Cockpit-SUDO-Manager/issues\n  license: Apache-2.0\n  description: |\n    Manage sudo policy on Linux systems in a structured, auditable, and\n    policy-driven way. Developed for SUSE Linux.\n\npacman:\n  title: Pacman Package Manager\n  package: cockpit-pacman\n  source: https://github.com/pfeifferj/cockpit-pacman\n  issues: https://github.com/pfeifferj/cockpit-pacman/issues\n  license: GPL-3.0\n  description: |\n    Arch Linux package management using direct alpm.rs integration.\n\ndownload-superstation:\n  title: Download Superstation\n  package: cockpit-download-superstation\n  source: https://github.com/dl-romero/cockpit-download-superstation\n  issues: https://github.com/dl-romero/cockpit-download-superstation/issues\n  license: MIT\n  prerelease: false\n  description: |\n    Torrent management backed by libtorrent. Add torrents via .torrent file or\n    magnet link, set per-torrent and per-file download priorities, and monitor\n    speeds, peers, and trackers in real time. Includes one-click Start/Stop for\n    the Download Superstation systemd service.\n"
  },
  {
    "path": "_data/authors.yml",
    "content": "default:\n  name: Cockpit Team\n\nexample:\n  name: Ann Example\n  twitter: example\n  googleplus: somegoogleaccount\n  facebook: somefacebookaccount\n  # gravatar:\n  description: |\n    This is an example author. To get a gravatar, do something like:\n    echo -n email@example.com | md5sum\n\ndperpeet:\n  name: Dominik Perpeet\n\njelle:\n  name: Jelle van der Waa\n\nlars:\n  name: Lars Karlitski\n\npitti:\n  name: Martin Pitt\n\nstef:\n  name: Stef Walter\n\ngarrett:\n  name: Garrett LeSage\n  gravatar: ee31aa48c51297eb062133b15eaff702\n  description: |\n    Garrett has been a designer in the FOSS (free and open source software)\n    world since the late 90s and works at Red Hat in the Cockpit team.\n\nmvo:\n  name: Marius Vollmer\n\nlis:\n  name: Allison Karlitskaya\n\nmarusak:\n  name: Matej Marušák\n\nkkoukiou:\n  name: Katerina Koukiou\n\ntmatus:\n  name: Tomáš Matuš\n\nVenefilyn:\n  name: Freya Gustavsson\n  description: |\n    The one who touches codebases everywhere and lead with smiles.\n"
  },
  {
    "path": "_data/browser_support.yml",
    "content": "---\ncomment: Generated by _scripts/update-browser-data.rb\nbrowsers:\n  edge: '18'\n  firefox: '58'\n  chrome: '63'\n  safari: '11.1'\n  opera: '50'\n  ios_saf: '11.3'\nrules:\n  websockets:\n    req:\n    - WebSocket\n    - window\n  xhr2:\n    req:\n    - XMLHttpRequest\n    - window\n  namevalue-storage:\n    req:\n    - sessionStorage\n    - window\n  json:\n    req:\n    - JSON\n    - window\n  es5:\n    req:\n    - defineProperty\n    - Object\n  console-basic:\n    req:\n    - console\n    - window\n  history:\n    req:\n    - pushState\n    - window.history\n  textcontent:\n    req:\n    - textContent\n    - document\n  css-variables:\n    req:\n    - CSS\n    - window\n  css-supports-api:\n    css: selector(test)\n  promise-finally:\n    req:\n    - finally\n    - Promise.prototype\n  mdn-javascript_builtins_string_replaceall:\n    req:\n    - replaceAll\n    - String.prototype\n  flexbox:\n    css:\n    - display\n    - flex\n  css-grid:\n    css:\n    - display\n    - grid\n  mdn-css_selectors_where:\n    css: selector(:is(*):where(*))\n"
  },
  {
    "path": "_data/browsers.yml",
    "content": "- firefox:\n  vendor: Mozilla\n  name: Firefox\n  version: 82\n\n- chrome:\n  vendor: Google\n  name: Chrome\n  version: 88\n\n- edge:\n  vendor: Microsoft\n  name: Edge\n  version: 88\n\n- safari:\n  vendor: Apple\n  os: iOS\n  name: Safari\n  version: 14.5\n"
  },
  {
    "path": "_data/distros.yml",
    "content": "- fedora:\n  name: Fedora\n  tested: true\n  included: true\n\n- rhel:\n  name: Red Hat Enterprise Linux\n  tested: true\n  included: true\n\n- coreos:\n  name: Fedora CoreOS\n  tested: true\n  included: true\n\n- centos:\n  name: CentOS\n  tested: true\n  included: true\n\n- debian:\n  name: Debian GNU/Linux\n  tested: true\n  included: true\n\n- archlinux:\n  name: Arch Linux\n  tested: true\n  included: true\n\n- ubuntu:\n  name: Ubuntu\n  tested: true\n  included: true\n\n- tumbleweed:\n  name: openSUSE Tumbleweed\n  included: true\n\n- slemicro:\n  name: SUSE Linux Enterprise Micro\n  included: true\n"
  },
  {
    "path": "_data/maintainers.yml",
    "content": "# Entries on the page show up in the order listed here\n# - cockpit (official) first\n# - redhat  (unofficial; non-team RH developed) second\n# - suse (unofficial; developed and maintained by suse)\n# - nil/not set (third party) last\n\ncockpit:\n  title: Cockpit\n\nredhat:\n  title: Red Hat\n\nsuse:\n  title: SUSE\n"
  },
  {
    "path": "_data/navigation.yml",
    "content": "- title: Home\n  url: \"/\"\n\n- title: Install\n  url: /running.html\n\n- title: Documentation\n  url: /documentation.html\n\n- title: Contribute\n  url: /external/wiki/Contributing.html\n\n- title: Blog\n  url: /blog/\n\n- title: Search\n  url: /search.html\n"
  },
  {
    "path": "_includes/apps.html",
    "content": "{% capture apps_html %}\n{% assign default = site.data.applications.cockpit %}\n{% assign href = '<a href=\"#\">#</a>' %}\n{% assign https = '>https://' %}\n{% assign gt = '>' %}\n\n{% for app in include.apps %}\n  {% assign slug = app.package %}\n\n  {% comment %} Title is mandatory for output {% endcomment %}\n  {% unless app.title %}{% continue %}{% endunless %}\n\n  {% if app.source == 'cockpit'\n    %}{% comment %}\n    Graft in Cockpit's defaults\n    {% endcomment %}{%\n    assign app_source = default.source\n    %}{%\n    assign app_issues = default.issues\n    %}{%\n    assign app_license = default.license\n  %}{% else %}{%\n    assign app_source = app.source\n    %}{%\n    assign app_issues = app.issues\n    %}{%\n    assign app_license = app.license\n  %}{% endif %}\n\n{% assign link_url = app.homepage | default: app_source %}\n\n<article id=\"{{slug}}\" class=\"app\">\n  <h4 class=\"app-title\">{{ app.title }}</h4>\n\n  <header class=\"app-tags\">\n    {% if app.official %}\n      <span class=\"app-tag app-official\">official</span>\n    {% endif %}\n    {% if app.prerelease %}\n      <span class=\"app-tag app-prerelease\">pre-release</span>\n    {% endif %}\n  </header>\n\n  <section class=\"app-description\">\n  {{ app.description | markdownify }}\n  </section>\n\n  <dl class=\"app-details\">\n    {% if app.package %}\n      <dt>Package</dt>\n      <dd class=\"app-package\"><kbd>{{ app.package }}</kbd></dd>\n    {% endif %}\n\n    {% if app.homepage %}\n      <dt>Homepage</dt>\n      {% assign link_html = href | replace: '#', app.homepage | replace: https, gt %}\n      <dd>{{ link_html }}</dd>\n    {% endif %}\n\n    {% if app.source %}\n      <dt>Source</dt>\n      {% assign source = href | replace: '#', app_source | replace: https, gt %}\n      <dd class=\"app-source\">{{ source }}</dd>\n    {% endif %}\n\n    {% if app.issues %}\n      <dt>Issue tracker</dt>\n      {% assign issues = href | replace: '#', app.issues | replace: https, gt %}\n      <dd class=\"app-issues\">{{ issues }}</dd>\n    {% endif %}\n  </dl>\n</article>\n{% endfor %}\n{% endcapture %}\n<section class=\"apps\">{{ apps_html }}</section>\n"
  },
  {
    "path": "_includes/email.html",
    "content": "{% capture output %}\n{% assign email = include.username\n| append: \" AT \"\n| append: include.domain\n| replace: \".\", \" DOT \"\n| prepend: \" RemoveThisText \"\n| append: \" RemoveThisText \"\n%}\n\n{% if include.script != true %}\n\n<a href=\"mailto:{{ email }}\" class=\"mailto-obfuscated\">{{\n  include.name\n}}</a>\n\n{% else %}\n\n<script>\n  document.addEventListener(\"DOMContentLoaded\", function(event) {\n    document.querySelectorAll('.mailto-obfuscated').forEach(function(el){\n      setTimeout(function(){\n        el['href'] = el['href']\n          .replace(/AT/, '@')\n          .replace(/DOT/g, '.')\n          .replace(/RemoveThisText/g, '')\n          .replace(/ /g, '');\n      }, 300);\n  });\n});\n</script>\n\n{% endif %}\n{% endcapture %}{{ output | strip_newlines | strip }}{{ include.after }}\n"
  },
  {
    "path": "_includes/feed.html",
    "content": "{%\nassign posts = include.posts | default: site.posts\n%}{%\nassign limit = include.limit | default: site.paginate | default: 10\n%}{%\nassign title = include.title | default: site.title\n%}{%\nassign url_prefix = site.url | append: site.baseurl | append: '/'\n%}<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n  <channel>\n    <title>{{ title | xml_escape }}</title>\n    <description>{{ site.description | xml_escape }}</description>\n    <link>{{ url_prefix }}</link>\n    <atom:link href=\"{{ page.url | remove_first: '/' | prepend: url_prefix }}\" rel=\"self\" type=\"application/rss+xml\"/>\n    <pubDate>{{ site.time | date_to_rfc822 }}</pubDate>\n    <lastBuildDate>{{ site.time | date_to_rfc822 }}</lastBuildDate>\n    <generator>Jekyll v{{ jekyll.version }}</generator>\n    {% for post in posts limit: limit %}\n      <item>\n        <title>{{ post.title | xml_escape }}</title>\n        <description>\n          {{ post.content\n            | markdownify\n            | replace: 'img src=\"/', 'img src=\"$SITE_GOES_HERE'\n            | replace: 'a href=\"/', 'a href=\"$SITE_GOES_HERE'\n            | replace: '$SITE_GOES_HERE', url_prefix\n            | xml_escape\n          }}\n        </description>\n        <pubDate>{{ post.date | date_to_rfc822 }}</pubDate>\n        <link>{{ post.url | prepend: url_prefix }}</link>\n        <guid isPermaLink=\"true\">{{ post.url | prepend: url_prefix }}</guid>\n        {% for tag in post.tags %}\n        <category>{{ tag | xml_escape }}</category>\n        {% endfor %}\n        {% for cat in post.categories %}\n        <category>{{ cat | xml_escape }}</category>\n        {% endfor %}\n      </item>\n    {% endfor %}\n  </channel>\n</rss>\n"
  },
  {
    "path": "_includes/feed_category.html",
    "content": "{%\nassign cat_default = page.url | split: '/' | last | split: '.' | first\n%}{%\nassign category = include.category | default: cat_default\n%}{%\nassign category_posts = site.posts | where: 'category', category\n%}{%\nassign title = category | capitalize | prepend: \" - \" | prepend: site.title\n%}{% include feed.html posts=category_posts title=title %}\n"
  },
  {
    "path": "_includes/github.html",
    "content": "{% if site.github %}{% capture github_link %}\n  {% assign github_edit_text = site.github_edit_text | default: \"Edit page on GitHub\" %}\n  {% if page.source %}\n    {% if page.source contains '/wiki/' %}\n      {% assign wiki = '/_edit'%}\n    {% endif %}\n    <a href=\"{{ page.source | replace_first: '/blob/', '/edit/' }}{{ wiki }}\">{{ github_edit_text }}</a>\n  {% else %}\n    <a\n      href=\"https://github.com/{{\n        site.github.owner_name\n      }}/{{\n        site.github.repository_name\n      }}/edit/main/{{\n        page.path\n      }}\">{{\n        github_edit_text\n      }}</a>\n  {% endif %}\n{% endcapture %}{{ github_link | strip_new_lines | lstrip | rstrip }}{% endif %}\n"
  },
  {
    "path": "_includes/nav.html",
    "content": "{% assign navs = include.nav | default: site.data.navigation %}\n\n{% unless include.wrap == false %}\n  <nav role=\"{{ include.role }}\" class=\"{{ include.class }}\">\n{% endunless %}\n\n  <ul class=\"nav-menu\" role=\"menubar\">\n    {% for nav in navs %}\n      {% capture vars %}\n        {% if nav.url == page.url | replace: \".html\", \"/\" %}\n          {% assign active = \" active\" %}\n        {% elsif nav.url == page.url | remove: \".html\" %}\n          {% assign active = \" active\" %}\n        {% else %}\n          {% assign active = \"\" %}\n        {% endif %}\n\n        {% assign protocol = nav.url | split: ':' | first | downcase %}\n        {% if protocol == 'https' %}\n          {% assign baseurl = '' %}\n        {% elsif protocol == 'http' %}\n          {% assign baseurl = '' %}\n        {% elsif protocol == 'ftps' %}\n          {% assign baseurl = '' %}\n        {% elsif protocol == 'ftp' %}\n          {% assign baseurl = '' %}\n        {% elsif protocol == 'mailto' %}\n          {% assign baseurl = '' %}\n        {% else %}\n          {% assign baseurl = site.baseurl %}\n        {% endif %}\n\n        {% if nav.nav %}\n          {% assign navgroup = \" nav-group\" %}\n        {% else %}\n          {% assign navgroup = \"\" %}\n        {% endif %}\n\n        {% if nav.icon-only == true %}\n          {% assign nav_label = '' %}\n          {% assign nav_title = nav.title | prepend: ' title=\"' | append: '\"' %}\n          {% assign nav_alt = nav.title %}\n        {% else%}\n          {% assign nav_label = nav.title | prepend: '<span class=\"label\">' | append: '</span>' %}\n          {% assign nav_title = '' %}\n          {% assign nav_alt = '' %}\n        {% endif %}\n\n        {% if nav.icon %}\n          {% assign nav_class = nav.class | append: \" nav-icon\" %}\n            {% capture nav_icon %}\n              <img src=\"{{ site.baseurl }}/images/{{ nav.icon }}.svg\" alt=\"{{ nav_alt }}\"{{ nav_title }}>\n            {% endcapture %}\n        {% else %}\n          {% assign nav_class = nav.class %}\n        {% endif %}\n      {% endcapture %}{% assign vars = nil %}\n\n      <li class=\"nav--{{ nav.title | slugify | default: \"home\" }}{{ nav_class }}{{ navgroup }}{{ active }}\" role=\"menuitem\">\n        {% if nav.url %}\n          <a href=\"{{ nav.url | prepend: baseurl }}\">{{\n            nav_icon | strip\n            }}{{\n            nav_label | strip\n            }}</a>\n        {% else %}\n          <span class=\"not-a-link\">{{ nav.title }}</span>\n        {% endif %}\n        {% if nav.nav %}\n          {% include nav.html nav=nav.nav wrap=false %}\n        {% endif %}\n      </li>\n    {% endfor %}\n\n  </ul>\n\n{% unless include.wrap == false %}\n  </nav>\n{% endunless %}\n"
  },
  {
    "path": "_includes/nav_dir.html",
    "content": "{% comment %}\nThis builds upon nav.html, but feeds it the current directory as the\nnavigation source. It's intended for use in special layouts that are\nassigned by directories, but also can be used in individual files.\n\nTODO: Add filtering and weighted sorting.\n{% endcomment %}\n\n{% assign current_dir = site.html_pages | where: \"dir\", page.dir %}\n{% include nav.html nav=current_dir %}\n"
  },
  {
    "path": "_includes/page_footer.html",
    "content": "<footer class=\"footer-cockpit\" role=\"contentinfo\">\n    <p class=\"copyright\">\n        {% comment %}\n        Copyright dates, mainly to indicate:\n            1. the project has been around for a while \n            2. currently maintained\n        {% endcomment %}\n\n        © 2013 - {{ site.time | date: \"%Y\" }}\n\n        &mdash;\n\n        Cockpit is a <a href=\"https://redhat.com/\">Red Hat</a> sponsored\n        free software project released under the\n        <a href=\"https://opensource.org/licenses/lgpl-2.1.php\">LGPL v2.1+</a>\n    </p>\n\n    <p class=\"policy\">\n        <a href=\"{{ site.baseurl }}/privacy.html\">\n            Privacy Policy\n        </a>\n        &mdash;\n        <a href=\"{{ site.baseurl }}/code-of-conduct.html\">\n            Code of Conduct\n        </a>\n    </p>\n\n    <p class=\"edit-page\">{% include github.html %}</p>\n</footer>\n"
  },
  {
    "path": "_includes/page_header.html",
    "content": "<header class=\"masthead hidden-print\" id=\"branding\" role=\"banner\">\n\n  <section class=\"hgroup\">\n    {% assign logo_path = site.logo | default: \"/images/logo.svg\" %}\n    {% assign has_logo = site.static_files | where: \"path\", logo_path %}\n\n    {% if has_logo[0] %}\n      <h1><a href=\"{{ \"/\" | prepend: site.baseurl }}\"><img id=\"logo\" class=\"logo is-svg\" alt=\"{{ site.title }}\" src=\"{{ logo_path | prepend: site.baseurl }}\"></a></h1>\n    {% else %}\n      <h1><a href=\"/\">{{ site.title }}</a></h1>\n    {% endif %}\n\n    {% if site.subtitle %}\n      <h2 id=\"site-title\">{{ site.subtitle }}</h2>\n    {% endif %}\n  </section>\n\n  {% if site.data.navigation %}\n\n    <div class=\"nav-wrap\">\n      {% include nav.html role=\"navigation\" %}\n    </div>\n\n  {% endif %}\n\n</header>\n"
  },
  {
    "path": "_includes/pagination.html",
    "content": "{% if paginator.total_pages > 1 %}\n  {% assign display_before = paginator.page | minus: 5 %}\n  {% assign display_after = paginator.page | plus: 5 %}\n\n  {% comment %}\n  Balance after pages based on lack of previous pages\n  {% endcomment %}\n  {% if display_before < 0 %}\n    {% assign display_after = display_after | minus: display_before %}\n  {% endif %}\n\n  <nav aria-label=\"Page navigation\">\n    <ul class=\"pagination\" aria-label=\"Page navigation\">\n\n      {% if paginator.previous_page %}\n        <li class=\"newest\">\n          <a href=\"{{ site.paginate_path | remove: \"page\" | remove: \"=\" | remove: \":num\" | prepend: site.baseurl }}\">Newest</a>\n        </li>\n        <li class=\"newer\">\n          <a href=\"{{ paginator.previous_page_path | prepend: site.baseurl }}\">Newer</a>\n        </li>\n      {% endif %}\n\n      {% for page in (1..paginator.total_pages) %}\n\n        {% if page > display_before and page < display_after %}\n\n          <li>\n            {% if page == paginator.page %}\n              <span class=\"current\">{{ page }}</span>\n            {% elsif page == 1 %}\n              <a href=\"{{ paginator.previous_page_path | prepend: site.baseurl }}\">{{ page }}</a>\n            {% else %}\n              <a href=\"{{ site.paginate_path | prepend: site.baseurl | replace: \":num\", page }}\">{{ page }}</a>\n            {% endif %}\n          </li>\n\n        {% endif %}\n\n      {% endfor %}\n\n      {% if paginator.next_page %}\n        <li class=\"older\">\n          <a href=\"{{ paginator.next_page_path | prepend: site.baseurl }}\" class=\"next\">Older</a>\n        </li>\n        <li class=\"oldest\">\n          <a href=\"{{ site.paginate_path | prepend: site.baseurl | replace: \":num\", paginator.total_pages }}\" class=\"next\">Oldest</a>\n        </li>\n      {% endif %}\n\n    </ul>\n  </nav>\n{% endif %}\n"
  },
  {
    "path": "_includes/post.html",
    "content": "{% assign post = include.post | default: page %}\n{% assign excerpt = include.excerpt | default: false %}\n{% assign link_title = include.link | default: false %}\n{% assign author_card = include.author_card | default: false %}\n{% assign author = site.data.authors[post.author] %}\n{% assign separator = site.excerpt_separator | prepend: \"<p>\" | append: \"</p>\" %}\n{% assign summary_length = site.blog_summary_length | default: 50 %}\n{% assign ignore = include.ignore | default: site.blog_ignore | split: ',' %}\n{% assign summary_headings = site.blog_summary_headings %}\n{% assign heading_summary = include.heading_summary %}\n{% assign newline = '\n' %}\n\n<article class=\"post hentry\" id=\"{{ post.url | replace: \"/\", \"-\" }}\">\n  <header class=\"post-header\">\n    <h2 class=\"post-title entry-title\">\n      {% if link_title %}\n        <a href=\"{{ post.url | prepend: site.baseurl }}\">{{ post.title | escape }}</a>\n      {% else %}\n        {{ post.title | escape }}\n      {% endif %}\n    </h2>\n    <header class=\"post-meta\">\n      {% if post.author %}\n        {% if author %}\n          <span class=\"byline\">\n            by\n            <span class=\"author vcard\">\n              <a href=\"{{ site.baseurl }}/blog/authors#{{ post.author }}\">{{ author.name }}</a>\n            </span>\n          </span>\n        {% else %}\n          <span class=\"byline\">\n            by\n            <span class=\"author vcard\">\n              {{ post.author }}\n            </span>\n          </span>\n        {% endif %}\n        –\n      {% endif %}\n      <time class=\"published\" datetime=\"{{ post.date | date: \"%u\" }}\">\n        {{ post.date | date: \"%b %-d, %Y\" }}\n      </time>\n\n      {% if post.category %}\n        {% assign cat_path = \"/blog/category/\" | append: post.category %}\n        {% assign cat_url = site.baseurl | append: cat_path | append: \".html\" %}\n        {% assign cat_page = site.html_pages | where: 'url', cat_path | first %}\n\n        <div class=\"category\">\n          {% if cat_page.path %}\n            category: <a href=\"{{ cat_url }}\">{{ post.category }}</a>\n          {% else %}\n            category: {{ post.category }}\n          {% endif %}\n        </div>\n      {% endif %}\n    </header>\n  </header>\n\n  {% assign content_stripped = '' %}\n  {% assign content_headings = '' %}\n  {% assign content_lines = post.excerpt | split: newline %}\n  {% for line in content_lines %}\n    {% assign skip = ignore\n    | where_exp: \"item\", \"line contains item\"\n    | join: ''\n    | strip\n    %}\n    {% if skip == '' %}\n      {% assign line_stripped = line | strip_html %}\n      {% if line contains '<h' %}\n        {% assign content_headings = line_stripped\n        | prepend: '- ' \n        | prepend: newline \n        | prepend: content_headings\n        %}\n        {% assign content_stripped = content_stripped\n        | append: ' <h3 class=\"post-content-subtitle\">'\n        | append: line_stripped\n        | append: '</h3> '\n        | append: newline \n        %}\n      {% else %}\n        {% assign content_stripped = line_stripped\n        | prepend: content_stripped\n        %}\n      {% endif %}\n    {% endif %}\n  {% endfor %}\n\n  <section class=\"post-content entry-content\">\n    {% if excerpt %}\n      {% if summary_headings and content_headings != '' and heading_summary %}\n        {{ content_headings | markdownify }}\n      {% else %}\n        {{ content_stripped | truncatewords: summary_length }}\n      {% endif %}\n    {% else %}\n      {{ post.content | remove_first: separator }}\n    {% endif %}\n  </section>\n\n  {% if excerpt %}\n    <footer class=\"post-meta\">\n      <a class=\"more-link read-more\" href=\"{{ post.url | prepend: site.baseurl}}\">Read More »</a>\n    </footer>\n  {% endif %}\n\n</article>\n\n{% if author_card %}\n  {% if author.name %}\n    {% assign author_title = \"About \" | append: author.name %}\n    {% assign author_blurb = \"View all posts by \" | append: author.name | append: \" »\" %}\n  {% else %}\n    {% assign author_title = \"Other posts\" %}\n    {% assign author_blurb = \"View all posts »\" %}\n  {% endif %}\n  <div class=\"author-info author-card\" id=\"author-info\">\n    <h2>{{ author_title }}</h2>\n    <div class=\"author-blurb\">\n      {{ author.description | markdownify }}\n\n      <div class=\"more-link\">\n        <a href=\"{{ site.baseurl }}/blog/authors#{{ post.author }}\">\n          {{ author_blurb }}\n        </a>\n      </div>\n\n      {% if author.twitter or author.facebook %}\n        <div class=\"follow-on\">\n          Follow {{ author.name | split: \" \" | first }} on:\n          {% if author.twitter %}\n            <a class=\"icon-twitter\" href=\"https://twitter.com/{{ author.twitter }}\">Twitter</a>\n          {% endif %}\n          {% if author.facebook %}\n            <a class=\"icon-facebook\" href=\"https://facebook.com/{{ author.facebook }}\">Facebook</a>\n          {% endif %}\n        </div>\n      {% endif %}\n    </div>\n  </div>\n{% endif %}\n"
  },
  {
    "path": "_includes/posts.html",
    "content": "{% assign post_set = include.posts | default: site.posts %}\n{% assign limiter = include.limit | default: site.paginate %}\n\n<div class=\"blog-posts-list\">\n  <section class=\"articles\">\n\n    {% for post in post_set limit: limiter %}\n\n      {% if post.category == \"release\" %}\n        {% assign heading_summary = true %}\n      {% else %}\n        {% assign heading_summary = false %}\n      {% endif %}\n\n      {% include post.html post=post excerpt=true link=true heading_summary=heading_summary %}\n\n    {% endfor %}\n  </section>\n</div>\n"
  },
  {
    "path": "_includes/posts_category.html",
    "content": "{% assign cat_default = page.url | split: '/' | last %}\n{% assign category = include.category | default: cat_default %}\n\n<h1>Category: {{ category | capitalize }}</h1>\n\n{% assign category_posts = site.posts | where: 'category', category %}\n{% include posts.html posts=category_posts %}\n"
  },
  {
    "path": "_includes/rss.html",
    "content": "<p class=\"rss-subscribe\">subscribe <a href=\"{{ \"/feed.xml\" | prepend: site.baseurl }}\">via RSS</a></p>\n"
  },
  {
    "path": "_includes/search.html",
    "content": "{% unless include.js == false %}\n<script src=\"{{ site.baseurl }}/assets/vendor/string_score.js\"></script>\n<script src=\"{{ site.baseurl }}/assets/lib/search.js\"></script>\n{% endunless %}\n\n{% unless include.template == false %}\n<div class=\"search-page\">\n\n  <!-- Search form -->\n  <form class=\"search-form\" id=\"search-form\" action=\"https://duckduckgo.com/\" role=\"search\">\n    <div class=\"search-input-wrapper\">\n      <input autocomplete=\"off\" id=\"search-input\" name=\"q\" class=\"search-input\" aria-labelledby=\"searchFormButton\">\n    </div>\n    <input type=\"hidden\" name=\"sites\" value=\"cockpit-project.org\">\n    <button class=\"search-button\" id=\"searchFormButton\">Search</button>\n  </form>\n\n  <!-- Spinner while the JSON DB is loading -->\n  <div class=\"progress-container\">\n    <i class=\"spinner fa fa-circle-o-notch fa-spin hidden\" id=\"progress\"></i>\n  </div>\n\n  <!-- Possibly related keywords -->\n  <div class=\"similar hidden\" id=\"similar\">\n    Possibly related:\n    <span id=\"similar-list\">...</span>\n  </div>\n\n  <!-- Display number of results -->\n  <div class=\"search-match-string hidden\" id=\"matches\">\n    <span class=\"number\">#</span>\n    result<span class=\"plural\">s</span> found.\n  </div>\n\n  <!-- Search results go here -->\n  <section class=\"articles\" id=\"results\"></section>\n\n  <!-- Show if no results are found -->\n  <section hidden id=\"results-none\">\n    <h2>No results found.</h2>\n    Sorry; try again.\n  </section>\n\n  <!-- Template used for the JavaScript-based search results -->\n  <template hidden id=\"template\">\n    <article class=\"post hentry\">\n      <h2 class=\"post-title entry-title\">\n        <a class=\"title\"></a>\n      </h2>\n      <section class=\"post-content entry-content summary\"></section>\n      <header class=\"post-meta\">\n        <time class=\"published date\">Unknown</time>\n        <a class=\"url\" role=\"presentation\"></a>\n      </header>\n    </article>\n  </template>\n</div>\n{% endunless %}\n"
  },
  {
    "path": "_includes/search_json.html",
    "content": "{%\n  assign _words = \"\"\n  %}{%\n  assign _wordlists = \"\" | split: \",\"\n%}{\"pages\": [\n  {%\n    capture _docs\n      %}{%\n      include search_json_items.html type=\"doc\"\n      %}{%\n    endcapture\n  %}{%\n    assign _docs = _docs | strip\n  %}{%\n    capture _pages\n      %}{%\n      include search_json_items.html pages=site.html_pages type=\"page\"\n      %}{%\n    endcapture\n  %}{%\n    assign _pages = _pages | strip\n  %}\n  {{ _docs }}{%\n    if _docs != \"\" and _pages != \"\"\n      %},{%\n    endif \n  %}{{ _pages }}\n]}\n"
  },
  {
    "path": "_includes/search_json_items.html",
    "content": "{% capture codeblock %}\n  {% assign docs = include.pages | default: site.documents %}\n  {% assign _type = include.type | default: 'doc' %}\n  {% assign _first = true %}\n{% endcapture %}\n{% for _page in docs %}{% capture codeblock %}\n  {% assign _content = _page.content\n    | strip_html\n    | markdownify\n    | strip_html\n    | remove: site.excerpt_separator\n    | strip\n  %}\n\n  {% if _page.summary %}\n    {% assign _blurb = _page.summary %}\n  {% else %}\n    {% if _content contains site.excerpt_separator %}\n      {% assign _blurb = _content | split: site.excerpt_separator | first %}\n    {% else %}\n      {% assign _blurb = _content %}\n    {% endif %}\n  {% endif %}\n\n  {% if _type == 'page' %}\n    {% assign fallback_title = _page.content\n      | split: \"</title>\"\n      | first\n      | strip_html\n      | truncatewords: 10\n      | strip\n    %}\n    {% assign _blurb = _blurb | replace_first: fallback_title, '' %}\n  {% endif %}\n\n  {% if _page.date %}\n    {% assign _date_parts = _page.date | date: '%Y %B %-d' %}\n  {% endif %}\n\n  {% assign _wordlist = _content\n    | append: \" \" | append: _page.title\n    | append: \" \" | append: _page.tags\n    | append: \" \" | append: _page.category\n    | append: \" \" | append: _page.url\n    | append: \" \" | append: _page.author\n    | append: \" \" | append: _page.summary\n    | append: \" \" | append: _date_parts\n    | downcase\n    | remove: '!'\n    | remove: '\"'\n    | remove: '#'\n    | remove: '$'\n    | remove: '%'\n    | remove: '&'\n    | remove: '('\n    | remove: ')'\n    | remove: '['\n    | remove: ']'\n    | remove: '*'\n    | remove: '+'\n    | remove: ','\n    | remove: ';'\n    | remove: '='\n    | remove: '?'\n    | remove: '“'\n    | remove: '”'\n    | replace: \"‘\", \"'\"\n    | replace: \"’\", \"'\"\n    | replace: \"'s \", \" \"\n    | replace: \" '\", \" \"\n    | replace: \"' \", \" \"\n    | replace: '-', ' '\n    | replace: '–', ' '\n    | replace: '—', ' '\n    | replace: '@', ' '\n    | replace: '...', ' '\n    | replace: '…', ' '\n    | replace: '.', ' '\n    | replace: '/', ' '\n    | replace: ':', ' '\n    | replace: ',', ' '\n    | split: ' '\n    | sort\n    | uniq\n    | where_exp: \"item\", \"item.size > 2\"\n    | where_exp: \"item\", \"item.size < 21\"\n    %}\n  {% assign _wordlist_string = _wordlist | join: ',' %}\n\n  {% assign _words = _words | append: \",\" | append: _wordlist_string %}\n  {% assign _wordlists = _wordlists | push: _wordlist %}\n\n  {% assign _id = forloop.index | minus: 1 %}\n\n  {% endcapture %}{% assign codeblock = nil %}{%\n    unless _page.index == false\n      %}{%\n\n        if _first == false\n        %},{%\n        endif\n\n      %}{\n        \"id\": {{ _id }},\n        \"title\": {{ _page.title | strip | default: fallback_title | jsonify }},\n        \"slug\": {{ _page.slug | strip | jsonify }},\n        \"url\": \"{{ site.baseurl }}{{ _page.url }}\",\n        \"type\": {{ _type | jsonify }},\n        \"category\": {{ _page.category | join: \",\" | strip | jsonify }},\n        \"tags\": {{ _page.tags | join: \",\" | strip | replace: \", \", \",\" | replace: \",,\", \",\" | downcase | split: \",\" | sort | uniq | jsonify }},\n        {% if _page.date %}\n        \"date\" : \"{{ _page.date | date_to_xmlschema }}\",\n        \"datestring\" : \"{{ _page.date | date: '%A %-d %B %Y' }}\",\n        {% endif %}\n        \"wordcount\": {{ _content | remove: site.excerpt_separator | number_of_words }},\n        \"wordlist\": {{ _wordlist | join: \" \" | jsonify }},\n        \"summary\": {{ _blurb | replace: \"\\n\", \" \" | strip | truncatewords: 50 | jsonify }}\n      }{%\n\n      assign _first = false\n    %}{%\n  endunless\n%}{% endfor %}\n"
  },
  {
    "path": "_includes/twitter.html",
    "content": "{% assign id = include.id | default: config.twitter_id %}\n{% assign _account = include.account | default: config.twitter_username %}\n{% assign limit = include.limit | default: 3 %}\n\n{% if include.id %}\n  <script id=\"twitter-wjs\" src=\"//platform.twitter.com/widgets.js\"></script>\n  <script>\n    // Load the Twitter widget JS in a <script> at the top of the doc\n    !function (doc, tag, id) {\n      var scriptTag,\n      firstScriptTag = doc.getElementsByTagName(tag) [0];\n\n      if (!doc.getElementById(id)) {\n        scriptTag = doc.createElement(tag);\n        scriptTag.id = id;\n        scriptTag.src = '//platform.twitter.com/widgets.js';\n        firstScriptTag.parentNode.insertBefore(scriptTag, firstScriptTag);\n      }\n    }(document, 'script', 'twitter-wjs');\n  </script>\n  <div class=\"twitter-timeline\"\n       data-chrome=\"noheader nofooter noborders noscrollbar transparent\"\n       data-dnt=\"\"\n       {% if include.color %}\n         data-link-color=\"{{ include.color }}\"\n       {% endif %}\n         data-tweet-limit=\"{{ limit }}\"\n         data-widget-id=\"{{ id }}\"\n         href=\"https://twitter.com/{{ _account }}\">\n    <noscript>The embedded Twitter timeline requires JavaScript.</noscript>\n  </div>\n  <div class=\"more-link pull-right\">\n    <a href=\"https://twitter.com/{{ _account }}\">More tweets by @{{ _account }}…</a>\n  </div>\n{% else %}\n  <em><strong>ERROR</strong>: You must include a Twitter ID.</em>\n{% endif %}\n"
  },
  {
    "path": "_layouts/default.html",
    "content": "---\nlayout: essential\n---\n{% include page_header.html %}\n\n<div class=\"page-content\" id=\"page-wrap\" role=\"main\">\n  <div class=\"wrapper\">\n    {{ content }}\n  </div>\n</div>\n\n{% include page_footer.html %}\n"
  },
  {
    "path": "_layouts/essential.html",
    "content": "<!DOCTYPE html>\n<html class=\"{{ page.class }} {{ page.url | replace: \"/\", \"-\" | prepend: \"-path\"}}\" lang=\"{{ site.lang | default: 'en' }}\">\n\n  <head>\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width initial-scale=1\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\n    <title>{% if page.title %}{{ page.title | strip_html }} &mdash; {% endif %}{{ site.title | strip_html }}</title>\n\n    <link rel=\"canonical\" href=\"{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}\">\n\n    <link rel=\"manifest\" href=\"{{ site.baseurl }}/manifest.json\">\n\n    <meta name=\"description\" content=\"{{ site.description }}\">\n    <meta property=\"og:site_name\" content=\"{{ site.title }}\">\n    <meta property=\"og:title\" content=\"{{ page.title | strip_html }}\">\n    <meta property=\"og:description\" content=\"{{ page.summary | strip_html }}\">\n    <meta property=\"og:type\" content=\"website\">\n    <meta property=\"og:url\" content=\"{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}\">\n    <meta name=\"author\" content=\"{{ site.data.authors[page.author].name }}\">\n    <meta property=\"og:image\" content=\"{{ site.baseurl }}/images/site/opengraph.png\">\n    {% if site.color %}<meta name=\"theme-color\" content=\"{{ site.color }}\">{% endif %}\n\n    <!-- Favicon -->\n    {% assign _favicon = site.static_files | where_exp: \"item\", \"item.path contains '/images/favicon.'\" %}\n    {% if _favicon[0] %}\n      <link rel=\"shortcut icon\" href=\"{{ _favicon[0].path | prepend: site.baseurl }}\" type=\"image/png\">\n    {% endif %}\n\n\n    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->\n    <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->\n    <!--[if lt IE 9]>\n    <script src=\"//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js\"></script>\n    <script src=\"//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js\"></script>\n    <![endif]-->\n\n    <script src=\"{{ \"/assets/main.js\" | prepend: site.baseurl }}\"></script>\n    <link rel=\"stylesheet\" href=\"{{ \"/assets/main.css\" | prepend: site.baseurl }}\">\n  </head>\n\n\n  <body id=\"page-top\">\n    {% assign content_fixedyt = content\n    | replace: 'youtube.com/embed', 'www.youtube-nocookie.com/embed'\n    | replace: 'www.www.youtube', 'www.youtube' %}\n    {% if site.rewrite_images == false %}\n      {{ content_fixedyt }}\n    {% else %}\n      {% assign img_untreated = 'img src=\"/' %}\n      {% assign baseurlslash = site.baseurl | append: \"/\" %}\n      {% assign img_baseurl = img_untreated | replace: \"/\", baseurlslash | replace: 'img', 'img loading=\"lazy\"' %}\n      {% assign rewritten = content_fixedyt | replace: img_untreated, img_baseurl %}\n\n      {% if site.baseurl != \"\" %}\n        {% assign doublebase = site.baseurl | append: site.baseurl %}\n        {{ rewritten | replace: doublebase, site.baseurl }}\n      {% else %}\n        {{ rewritten }}\n      {% endif %}\n    {% endif %}\n  </body>\n\n</html>\n"
  },
  {
    "path": "_layouts/guide.html",
    "content": "---\nlayout:\n---\n{% capture empty %}\n  {% comment %} Cockpit-specific guide template {% endcomment %}\n\n  {% assign html_tag = '<html' %}\n  {% assign head_tag = '</head>' %}\n  {% assign nav_tag = '<table class=\"navigation\"' %}\n  {% assign book_tag = '<div class=\"book\"'%}\n  {% assign toc_tag = '<div class=\"toc\"'%}\n  {% assign part_tag = '<div class=\"part\"'%}\n  {% assign ref_tag = '<div class=\"refentry\"'%}\n  {% assign chap_tag = '<div class=\"chapter\"'%}\n\n  {% assign html_mod = '<html class=\"cockpit-guide\" lang=\"en\"'%}\n    \n  {% assign role_main = ' role=\"main\"'%}\n  {% assign role_nav = ' role=\"navigation\"'%}\n\n  {% capture head_mod %}\n    <meta name=\"viewport\" content=\"width=device-width initial-scale=1\" />\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <link rel=\"canonical\" href=\"{{ page.url | replace:'index.html','' | prepend: site.baseurl | prepend: site.url }}\">\n    <link rel=\"manifest\" href=\"{{ site.baseurl }}/manifest.json\">\n\n    {% assign _favicon = site.static_files | where_exp: \"item\", \"item.path contains '/images/favicon.'\" %}\n    {% if _favicon[0] %}\n      <link rel=\"shortcut icon\" href=\"{{ _favicon[0].path | prepend: site.baseurl }}\" type=\"image/png\">\n    {% endif %}\n\n    <link rel=\"stylesheet\" href=\"{{ \"/assets/main.css\" | prepend: site.baseurl }}\">\n    {{ head_tag }}\n  {% endcapture %}\n\n  {% capture header_html %}{% include page_header.html %}{% endcapture %}\n\n  {% if content contains book_tag %}\n    {% assign header_orig = book_tag %}\n    {% assign header_mod = book_tag | prepend: header_html %}\n    {% assign toc_mod = toc_tag | append: role_main %}\n  {% else %}\n    {% assign header_orig = nav_tag %}\n    {% assign header_mod = nav_tag | prepend: header_html | append: role_nav %}\n    {% assign ref_mod = ref_tag | append: role_main %}\n    {% assign chap_mod = chap_tag | append: role_main %}\n    {% assign part_mod = part_tag | append: role_main %}\n    {% assign toc_mod = toc_tag %}\n  {% endif %}\n\n{%\n  endcapture\n%}{{ content\n  | replace_first: html_tag, html_mod\n  | replace_first: head_tag, head_mod\n  | replace_first: ref_tag, ref_mod\n  | replace_first: chap_tag, chap_mod\n  | replace_first: part_tag, part_mod\n  | replace_first: toc_tag, toc_mod\n  | replace_first: header_orig, header_mod\n}}\n"
  },
  {
    "path": "_layouts/markdown.html",
    "content": "---\nlayout: default\n---\n<div class=\"post\">\n\n  <header class=\"post-header\">\n    <h1 class=\"post-title\">{{ page.title }}</h1>\n  </header>\n\n  <h1>THIS IS MARKDOWN</h1>\n\n  <article class=\"post-content\">\n    {{ content }}\n  </article>\n\n</div>\n"
  },
  {
    "path": "_layouts/page.html",
    "content": "---\nlayout: default\n---\n\n<header class=\"post-header\">\n  <h2 class=\"post-title\">{{ page.title }}</h2>\n</header>\n\n<article class=\"post-content\">\n  {{ content }}\n</article>"
  },
  {
    "path": "_layouts/post.html",
    "content": "---\nlayout: default\n---\n\n{% include post.html author_card=true %}\n"
  },
  {
    "path": "_posts/2014-02-13-introducing-cockpit.md",
    "content": "---\ntitle: Introducing Cockpit\ndate: 2014-02-13 12:46\ntags: technical\nslug: introducing-cockpit\ncategory: release\n---\n\nGave a [talk at DevConf][] in Brno about the project a bunch of us have\nbeen working on: [Cockpit][]. It's a UI for Linux Servers. Currently in\nthe prototype stage...  \n  \n![Cockpit login](/images/cockpit1.png)\n\nHopefully there'll be a video of the talk available soon. You can try\nout the Cockpit prototype in Fedora like so:  \n  \n```text\n# yum install --enablerepo=updates-testing cockpit\n# setenforce 0 # issue 200\n# systemctl enable cockpit-ws.socket\n$ xdg-open http://localhost:21064\n\n  \n**Don't run this on a system you care about (yet).** Sorry about the\n```\n\ncertificate warning. Groan ... I know ... working on that.  \n  \nNeedless to say I'm excited about where this is going...\n\n\n  [talk at DevConf]: http://thewalter.net/stef/misc/cockpit-devconf-2014-talk.pdf\n  [Cockpit]: https://cockpit-project.org/\n"
  },
  {
    "path": "_posts/2014-04-22-cockpit-has-a-terminal.md",
    "content": "---\ntitle: Cockpit has a terminal\ndate: 2014-04-22 16:06\ntags: cockpit technical\nslug: cockpit-has-terminal\ncategory: release\n---\n\n[Cockpit][] 0.5 now has a nice terminal in a web browser. AKA\n[term.js][] is awesome.  \n  \n![Cockpit terminal](/images/cockpit-terminal.png)\n\n  [Cockpit]: https://cockpit-project.org/\n  [term.js]: https://github.com/chjj/term.js/\n"
  },
  {
    "path": "_posts/2014-04-25-cockpit-does-docker.md",
    "content": "---\ntitle: Cockpit does Docker\ndate: 2014-04-25 19:39\ntags: cockpit technical\nslug: cockpit-does-docker\ncategory: release\n---\n\nHere's a short video showing how Cockpit manages Docker containers.\nCockpit is in RHEL branding here, but it's basically the same thing as\nyou get from [cockpit-project.org][]\n\n<iframe src=\"//www.youtube.com/embed/5dM4CqIp2s4\" allowfullscreen=\"\" frameborder=\"0\" height=\"480\" width=\"853\"></iframe>\n  \nThis UI is going to be refined somewhat, but it's nice to see things\ncoming together.\n\n  [cockpit-project.org]: https://cockpit-project.org/\n"
  },
  {
    "path": "_posts/2014-06-20-cockpit-simple-networking-configuration.md",
    "content": "---\ntitle: Cockpit Simple Networking Configuration\ndate: '2014-06-20'\ncategory: release\ntags: cockpit network-manager linux\n---\n\n Cockpit 0.11 now has an all new simple Networking UI. Still some work to do, but it's\ncoming together. You can see it here:\n\n![Cockpit simple networking configuration](/images/cockpit-simple-network.png)\n"
  },
  {
    "path": "_posts/2014-06-24-cockpit-has-docker-pull-support.md",
    "content": "---\ntitle: Cockpit has Docker pull support\ndate: '2014-06-24'\ncategory: release\ntags: cockpit docker\n---\n\nCockpit 0.12 now has support for pulling Docker images from the\n[Docker registry](https://registry.hub.docker.com/).\n\n![Docker pull support](/images/cockpit-docker-pull.png)\n\nUnfortunately Docker doesn't have support for cancelling the pull of an image. So that\nsort of hampers the UI a bit. At least for now.\n"
  },
  {
    "path": "_posts/2014-11-04-cockpit-multi-server-dashboard.md",
    "content": "---\ntitle: Cockpit Multi-Server Dashboard\ndate: '2014-11-04'\ncategory: release\ntags: cockpit kubernetes\n---\n\nAndreas and Marius have been working on implementing a new multi-server dash\nboard for Cockpit. It's really looking great.\n\nThe goal here is that the dash board should work with either one server or several,\nand give you an overview of what's going on. Problems that require attention should\nbe highlighted clearly. You should be able to click in spots to jump either to a\nserver, a sub-system, a service/container/pod or to the source of a problem.\n\nThe graphs will be correlated across multiple machines, and draggable. Hopefully down\nroad we'll be using a source of data like [PCP](http://www.performancecopilot.org/) to\ngather the data more consistently. Problems will show up on the graphs as clickable.\nYou can add and remove servers, and we want to show the state of important services/server\napplications/pods on those servers.\n\nOnce the basic code has landed, it would be good to tie this into Kubernetes as well.\nIf running a [Kubernetes](https://github.com/GoogleCloudPlatform/kubernetes) cluster,\nand Cockpit is loaded on the master, we should use information from Kubernetes to\npopulate the dashboard.\n\nHere are some wireframes, click to expand:\n\n![Multi server dashboard wireframes](/images/navigation-horizontal-2.png)\n\n[Pull request is here ](https://github.com/cockpit-project/cockpit/pull/1455)\n"
  },
  {
    "path": "_posts/2014-11-04-dbus-powerful-ipc.md",
    "content": "---\ntitle: DBus is powerful IPC\ndate: '2014-11-04'\ncategory: linux\ntags: dbus linux\nslug: d-bus-is-powerful-ipc\n---\n\nD-Bus is powerful IPC Cockpit is heavily built around DBus. We send DBus over our\n[WebSocket transport](https://github.com/cockpit-project/cockpit/blob/master/doc/protocol.md),\nand marshal them in JSON.\n\nDBus is powerful, with lots of capabilities. Not all projects use all of these, but so many of\nthese capabilities are what allow Cockpit to implement its UI.\n\n * Method Call Transactions\n * Object Oriented\n * Efficient Signalling\n * Properties and notifications\n * Race free watching of entire Object trees for changes\n * Broadcasting\n * Discovery\n * Introspection\n * Policy\n * Activation\n * Synchronization\n * Type-safe Marshalling\n * Caller Credentials\n * Security\n * Debug Monitoring\n * File Descriptor Passing\n * Language agnostic\n * Network transparency\n * No trust required\n * High-level error concept\n * Adhoc type definitions\n\nLennart goes into these further [in a kdbus talk](http://youtu.be/HPbQzm_iz_k?t=2m6s), as well as some of the weaknesses of DBus.\n"
  },
  {
    "path": "_posts/2014-11-13-cockpit-plugin-tutorial.md",
    "content": "---\ntitle: Creating Plugins for the Cockpit User Interface\nauthor: stef\ndate: '2020-05-04'\ncategory: tutorial\ntags: cockpit linux\nslug: creating-plugins-for-the-cockpit-user-interface\n---\n\n_**Note**: This post was updated in Aug 2022 to adjust to reflect Cockpit UI and development best practices._\n{:.note}\n\n[Cockpit is a web-based graphical interface for servers](https://cockpit-project.org). You can easily add your own custom pages to the navigation.\n\n![Navigation menu](/images/pages-menu-top.png)\n\nFor this tutorial you need to [install your distribution's cockpit packages](../running.html) or [build it from git](https://github.com/cockpit-project/cockpit/blob/master/HACKING.md).\n\nWe'll make a package called *pinger* that checks whether your server has network connectivity to the Internet by pinging another host. It's simple and not too fancy. The package will spawn a process on the server to do all the work.\n\nThis example package is already [included in the Cockpit sources](https://github.com/cockpit-project/cockpit/tree/master/examples/pinger). You can look it over and modify it.\n\nTo start, let's get ready for development by launching a terminal on your local computer.\n\nFirst, create a project directory and download the example:\n\n```sh\nmkdir pinger; cd pinger\ncurl -O https://raw.githubusercontent.com/cockpit-project/cockpit/master/examples/pinger/manifest.json\ncurl -O https://raw.githubusercontent.com/cockpit-project/cockpit/master/examples/pinger/ping.html\ncurl -O https://raw.githubusercontent.com/cockpit-project/cockpit/master/examples/pinger/pinger.js\n```\n\nCockpit pages — more specifically their HTML and Javascript files — live in [package directories](https://cockpit-project.org/guide/latest/packages.html). In the package directory there's also a [manifest.json](https://cockpit-project.org/guide/latest/packages.html#package-manifest) file which tells Cockpit about the package. The `pinger` directory above is such a package. Its `manifest.json` file looks like this:\n\n```text\n{\n    \"version\": 0,\n    \"tools\": {\n        \"pinger\": {\n            \"label\": \"Pinger\",\n            \"path\": \"ping.html\"\n        }\n    }\n}\n```\n\nThe manifest above has a `\"tools\"` subsection, which means that it will appear in the lower section of the menu (see the [manifest documentation](https://cockpit-project.org/guide/latest/packages.html#package-manifest) for details). Each tool is listed in the menu by Cockpit. The `\"path\"` is the name of the HTML file that implements the tool, and the `\"label\"` is the text to show in the menu.\n\nYou'll notice that we haven't told Cockpit about how to find the package yet. To do so you either copy or symlink the package into one of two places:\n\n * `~/.local/share/cockpit` in your home directory. It's used for user specific packages and ones that you're developing. You can edit these on the fly and refresh your browser to see changes.\n * `/usr/share/cockpit` is the location for installed packages available to all users of a system. Changing files in this path requires administrator (\"root\") privileges. These should not be changed while Cockpit is running.\n\nSince we're going to be actively editing this package, let's symlink it into the first location, in your home directory.\n\n```sh\nmkdir -p ~/.local/share/cockpit\nln -snf $PWD ~/.local/share/cockpit/pinger\n```\n\nTo list the Cockpit packages which are installed, use the following command:\n\n```text\n$ cockpit-bridge --packages\n...\npinger: /home/.../.local/share/cockpit/pinger\n...\n```\n\nYou should see `pinger` listed among all the active modules, like the above example.\n\nLog into Cockpit on this machine with your current user name, as the package is installed in your home directory. (If you're already logged in to Cockpit with your user account, you can simply reload your browser.)\n\nYou should now see a new item:\n\n![Tools menu with pinger](/images/cockpit-tools-pinger.png)\n\nThe pinger tool itself looks like this:\n\n![Pinger tool](/images/cockpit-pinger-tool.png)\n\nLets take a look at the pinger HTML, and see how it works.\n\n```html\n<!DOCTYPE html>\n<html>\n<head>\n    <title>Pinger</title>\n    <meta charset=\"utf-8\">\n    <script src=\"../base1/cockpit.js\"></script>\n</head>\n<body>\n    <main tabindex=\"-1\">\n        <section>\n            <div>\n                <div>\n                    <label for=\"address\">Address</label>\n                    <input id=\"address\" value=\"8.8.8.8\">\n                </div>\n                <div>\n                    <button id=\"ping\">Ping</button>\n                    <span id=\"result\"></span>\n                </div>\n                <div>\n                    <pre id=\"output\"></pre>\n                </div>\n            </div>\n        </section>\n    </main>\n\n    <script src=\"pinger.js\"></script>\n</body>\n</html>\n```\n\nIncluded in the `<head>` block: `cockpit.js` is the basic API for interacting with the system, as well as Cockpit itself. You can find [detailed documentation in the Cockpit guide](https://cockpit-project.org/guide/latest/api-base1.html).\n\nThe HTML is pretty basic. It defines a little form with a field to type an address, a button to click to start pinging, and an area to present output and results.\n\nThe logic lives in `pinger.js`, shown in full here:\n\n```js\nconst address = document.getElementById(\"address\");\nconst output = document.getElementById(\"output\");\nconst result = document.getElementById(\"result\");\nconst button = document.getElementById(\"ping\");\n\nfunction ping_run() {\n    cockpit.spawn([\"ping\", \"-c\", \"4\", address.value])\n        .stream(ping_output)\n        .then(ping_success)\n        .catch(ping_fail);\n\n    result.innerHTML = \"\";\n    output.innerHTML = \"\";\n}\n\nfunction ping_success() {\n    result.style.color = \"green\";\n    result.innerHTML = \"success\";\n}\n\nfunction ping_fail() {\n    result.style.color = \"red\";\n    result.innerHTML = \"fail\";\n}\n\nfunction ping_output(data) {\n    output.append(document.createTextNode(data));\n}\n\n// Connect the button to starting the \"ping\" process\nbutton.addEventListener(\"click\", ping_run);\n\n// Send a 'init' message.  This tells integration tests that we are ready to go\ncockpit.transport.wait(function() { });\n```\n\nFirst we get a bunch of variables pointing to the HTML elements we want to interact with. Next we attach a handler to the *Ping* button so that the `ping_run()` function is called when it is clicked.\n\n```js\nfunction ping_run() {\n}\n...\nbutton.addEventListener(\"click\", ping_run);\n```\n\nThe `ping_run()` function is where the magic happens. [cockpit.spawn](https://cockpit-project.org/guide/latest/cockpit-spawn.html) lets you spawn processes on the server and interact with them via `stdin` and `stdout`.\n\nHere we spawn the `ping` command with some arguments:\n\n```js\ncockpit.spawn([\"ping\", \"-c\", \"4\", address.val()])\n```\n\nIn a web browser you cannot block and wait until a method call completes. Anything that doesn't happen instantaneously gets its results reported back to you by [means of callback handlers](https://cockpit-project.org/guide/latest/cockpit-spawn.html#cockpit-spawn-then).\n\nJavaScript has a standard interface called a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise). You add handlers by calling the `.then()` or `.catch()` methods and registering callbacks (Note: historically these have been called `.done()` and `.fail()`, but these should not be used any more in new code.) The `cockpit.spawn` specific `.stream()` handler registers a callback to be invoked whenever the process produces output.\n\n```js\n   <some promise>\n   .stream(ping_output)\n   .then(ping_success)\n   .catch(ping_fail);\n}\n```\n\nThe `ping_success()` and `ping_fail()` and `ping_output()` update the display as you would expect.\n\n_**Warning**: Don't start long-running, uninterruptible processes in this naïve way. Browser tabs are easily closed, network connections get severed, laptops suspend, and so on. Take care to use a mechanism like [systemd-run](https://www.freedesktop.org/software/systemd/man/systemd-run.html) (or similar) for processes that should not be interrupted, such as installation procedures._\n{:.warning}\n\nThis should be enough to get you started with your first useful (but admittedly basic) Cockpit page!  Please see the [Contributing](https://cockpit-project.org/external/wiki/Contributing.html) page for more documentation on where to grow from here.\n"
  },
  {
    "path": "_posts/2014-11-13-dbus-basics.md",
    "content": "---\ntitle: Using DBus from Javascript in Cockpit\ndate: '2014-11-13'\ncategory: tutorial\ntags: cockpit linux\nslug: using-dbus-from-javascript-in-cockpit\n---\n\n*Note: This post has been updated for changes in Cockpit 0.90 and later.*\n{:.note}\n\n[Cockpit is a user interface for servers](https://cockpit-project.org). As we covered in the [last tutorial](https://cockpit-project.org/blog/creating-plugins-for-the-cockpit-user-interface.html) you can add user interface component to Cockpit, and build your own parts of the Server UI.\n\nMuch of Cockpit interacts with the server using DBus. We have a powerful yet simple API for doing that, and you should use DBus too when building your own Cockpit user interfaces. For this tutorial you'll need at least Cockpit 0.41. A few tweaks landed in that release to solve a couple rough edges we had in our DBus support. You can install it in [Fedora 21](https://lists.fedorahosted.org/pipermail/cockpit-devel/2014-November/000196.html) or [build it from git](https://github.com/cockpit-project/cockpit/blob/master/HACKING.md).\n\nHere we'll make a package called *zoner* which lets you set the time zone of your server. We use the systemd [timedated DBus API](http://www.freedesktop.org/wiki/Software/systemd/timedated/) to do actually switch time zones.\n\nI've prepared the [zoner package here](https://cockpit-project.org/files/zoner.tgz). It's just two files. To download them and extract to your current directory, and installs it as a Cockpit package:\n\n```text\n$ wget https://cockpit-project.org/files/zoner.tgz -O - | tar -xzf -\n$ cd zoner/\n$ mkdir -p ~/.local/share/cockpit\n$ ln -snf $PWD ~/.local/share/cockpit/zoner\n```\n\nPreviously we [talked about](https://cockpit-project.org/blog/creating-plugins-for-the-cockpit-user-interface.html) how packages are installed, and what `manifest.json` does so I won't repeat myself here. But to make sure the above worked correctly, you can run the following command. You should see `zoner` listed in the output:\n\n```text\n$ cockpit-bridge --packages\n...\nzoner: .../.local/share/cockpit/zoner\n...\n```\n\nIf you're logged into Cockpit on this machine, first log out. And log in again. Make sure to log into Cockpit with your current user name, since you installed the package in your home directory. You should now see a new item in the *Tools* menu called *Time Zone*:\n\n![Pinger tool](/images/cockpit-zoner-tool.png)\n\nTry it out by typing `Australia/Tasmania` in the box, and clicking *Change*. You should see that the *Time Zone* changes. You can verify this by typing the following on the same server in a terminal:\n\n```text\n$ date\nSa 15. Nov 01:48:01 AEDT 2014\n```\n\nTry typing an invalid timezone like `blah`, and you'll see an error message displayed. Now try changing the timezone from the terminal using the `timedatectl` command while you have Cockpit open displaying your *Time Zone* screen:\n\n```text\n$ sudo timedatectl set-timezone UTC\n```\n\nYou should see your timezone on your screen update immediately to reflect the new state of the server. So how does this work? Lets take a look at the zoner HTML:\n\n```html\n<head>\n    <title>Time Zone</title>\n    <meta charset=\"utf-8\">\n    <link href=\"../base1/cockpit.css\" type=\"text/css\" rel=\"stylesheet\">\n    <script src=\"../base1/jquery.js\"></script>\n    <script src=\"../base1/cockpit.js\"></script>\n</head>\n<body>\n    <div class=\"container-fluid\" style='max-width: 400px'>\n        <table class=\"cockpit-form-table\">\n            <tr>\n                <td>Time Zone</td>\n                <td><span id=\"current\"></span></td>\n            </tr>\n            <tr>\n                <td>New Zone</td>\n                <td><input class=\"form-control\" id=\"new\" value=\"UTC\"></td>\n            </tr>\n            <tr>\n                <td><button class=\"btn btn-default btn-primary\" id=\"change\">Change</button></td>\n                <td><span id=\"failure\"></span></td>\n            </tr>\n        </table>\n    </div>\n\n    <script>\n        var input = $(\"#new\");\n        var current = $(\"#current\");\n        var failure = $(\"#failure\");\n\n        $(\"#change\").on(\"click\", change_zone);\n\n        var service = cockpit.dbus('org.freedesktop.timedate1');\n        var timedate = service.proxy();\n        $(timedate).on(\"changed\", display_zone);\n\n        function display_zone() {\n            current.text(timedate.Timezone);\n        }\n\n        function change_zone() {\n            var call = timedate.SetTimezone(input.val(), true);\n            call.fail(change_fail);\n            failure.empty();\n        }\n\n        function change_fail(err) {\n            failure.text(err.message);\n        }\n\n    </script>\n</body>\n</html>\n```\n\nFirst we include `jquery.js` and `cockpit.js`. `cockpit.js` defines the basic API for interacting with the system, as well as Cockpit itself. You can find [detailed documentation here](https://cockpit-project.org/guide/latest/api-cockpit.html).\n\n```html\n<script src=\"../base1/jquery.js\"></script>\n<script src=\"../base1/cockpit.js\"></script>\n```\n\nWe also include the cockpit.css file to make sure the look of our tool matches that of Cockpit. The HTML is pretty basic, defining a little form where the current timezone is shown, a field to type an address, a button to click change to a new one, and an area to show errors.\n\nIn the javascript code, first we get a bunch of variables pointing to the HTML elements we want to interact with.\nNext we attach a handler to the *Change* button so that the `change_zone()` function is called when it is clicked.\n\n```javascript\n$(\"#change\").on(\"click\", change_zone);\n```\n\nNext we connect to the [timedated](http://www.freedesktop.org/wiki/Software/systemd/timedated/) DBus service using the [`cockpit.dbus()`](https://cockpit-project.org/guide/latest/api-cockpit.html#latest-dbus-dbus) function:\n\n```javascript\nvar service = cockpit.dbus('org.freedesktop.timedate1');\n```\n\nNow we make a proxy which represents a particular DBus interface containing methods and properties. Simple services have only one interface. When more than one interface or instance of that interface is present, there are additional arguments to the [`.proxy()`](https://cockpit-project.org/guide/latest/api-cockpit.html#latest-dbus-proxy) method that you can specify.\n\n```javascript\nvar timedate = service.proxy();\n```\n\nEach interface proxy has a [`\"changed\"`](https://cockpit-project.org/guide/latest/api-cockpit.html#latest-dbus-proxy-onchanged) event we can connect to. When properties on the proxy change, or are received for the first time, this event is fired. We use this to call our `display_zone()` function and update the display of the current time zone:\n\n```javascript\n$(timedate).on(\"changed\", display_zone);\n\n`Timezone` is a property on the [timedated DBus interface](http://www.freedesktop.org/wiki/Software/systemd/timedated/). We can access these properties directly, and the proxy will keep them up to date. Here we use the property to update our display of the current time zone:\n\nfunction display_zone() {\n    current.text(timedate.Timezone);\n}\n\n`SetTimezone` is a method on the [timedated DBus interface](http://www.freedesktop.org/wiki/Software/systemd/timedated/) interface, and we can invoke it directly as we would a javascript function. In this case we pass the arguments the DBus method expects, a `timezone` string, and a `user_interaction` boolean.\n\nfunction change_zone() {\n    var call = timedate.SetTimezone(input.val(), true);\n```\n\nIn a web browser you cannot block and wait until a method call completes. Anything that doesn't happen instantaneously gets its results reported back to you by [means of callback handlers](https://cockpit-project.org/guide/latest/api-cockpit.html#latest-dbus-done). jQuery has a standard interface [called a promise](http://api.jquery.com/deferred.promise/). You add handlers by calling the `.done()` or `.fail()` methods and registering callbacks.\n\n```unknown\n    call.fail(change_fail);\n    failure.empty();\n}\n```\n\nThe `change_fail()` displays any failures that happen. In this case, `SetTimezone` DBus method has no return value, however if there were, we could use something like `call.done(myhandler)` to register a handler to receive them.\n\nNotice that we relied on DBus to tell us when things changed and just updated the display from our event handler. That way we reacted both when the time zone changed due to an action in Cockpit, as well as an action on the server.\n\nAgain this is a simple example, but I hope it will whet your appetite to what [Cockpit can do with DBus](https://cockpit-project.org/guide/latest/api-cockpit.html#latest-dbus). Obviously you can also do signal handling, working with return values from methods, tracking all instances of a given interface, and other stuff you would expect to do as a DBus client.\n"
  },
  {
    "path": "_posts/2014-11-20-rhel-atomic-beta.md",
    "content": "---\ntitle: Cockpit on RHEL Atomic Beta\ndate: '2014-11-20'\ncategory: release\ntags: cockpit linux rhel atomic\nslug: cockpit-on-rhel-atomic-beta\n---\n\nIf you've tried out the [RHEL Atomic Host Beta](http://developerblog.redhat.com/2014/11/11/red-hat-enterprise-linux-7-atomic-host-beta-now-available/) you might notice that Cockpit is not included by default, like it is in the Fedora Atomic or CentOS Atomic. But there's an easy work around:\n\n```:text\n$ sudo docker run --privileged -v /:/host -d stefwalter/cockpit-atomic:wip\n```\n\nThis is an interim solution, and has some drawbacks:\n\n * Only really allows Cockpit to be used as root.\n * The Storage and user accounts UIs don't work.\n\nAnd in general privileged containers are a mixed bag. They're not portable, and really not containers at all, in the sense that they're not contained.  But this is an easy way to get Cockpit going on RHEL Atomic for the time being.\n"
  },
  {
    "path": "_posts/2014-12-16-protocol-interaction.md",
    "content": "---\ntitle: Protocol for Web access to System APIs\ndate: '2014-12-16'\ncategory: tutorial\ntags: cockpit linux\nslug: protocol-for-web-access-to-system-apis\n---\n\n*Note: This post has been updated for changes in Cockpit 0.48 and later.*\n{:.note}\n\nA Linux system today has a lot of local system configuration APIs. I'm not talking about library APIs here, but things like DBus services, command/scripts to be executed, or files placed in various locations. All of these constitute the API by which we configure a Linux system. In [Cockpit](https://cockpit-project.org) we access these APIs from a web browser (after authentication of course).\n\nHow do we access the system APIs? The answer is the `cockpit-bridge` tool. It proxies requests from the Cockpit user interface, running in a web browser, to the system. Typically the `cockpit-bridge` runs as the logged in user, in a user session. It has similar permissions and capabilities as if you had used `ssh` to log into the system.\n\nLets look at an example DBus API that we call from Cockpit. systemd has an API to set the system host name, called [SetStaticHostname](http://www.freedesktop.org/wiki/Software/systemd/hostnamed/). In Cockpit we can invoke that API using simple JSON like this:\n\n```text\n{\n  \"call\": [\n    \"/org/freedesktop/hostname1\",\n    \"org.freedesktop.hostname1\",\n    \"SetStaticHostname\", [ \"mypinkpony.local\", true ]\n  ]\n}\n```\n\nThe protocol that the web browser uses is a [message based protocol](https://github.com/cockpit-project/cockpit/blob/master/doc/protocol.md), and runs over a [WebSocket](http://en.wikipedia.org/wiki/WebSocket). This is a \"post-HTTP\" protocol, and isn't limited by the request/response semantics inherent to HTTP. Our protocol has a lot of JSON, and has a number of interesting characteristics, which you'll see below. In general we've tried to keep this protocol readable and debuggable.\n\nThe `cockpit-bridge` tool speaks this protocol on its standard in and standard output. The `cockpit-ws` process hosts the WebSocket and passes the messages to `cockpit-bridge` for processing.\n\n**Following along:** In order to follow along with the stuff below, you'll need at least Cockpit 0.48. The protocol is not yet frozen, and we merged some cleanup recently. You can install it on [Fedora 21 using a COPR](https://lists.fedorahosted.org/pipermail/cockpit-devel/2014-November/000196.html) or [build it from git](https://github.com/cockpit-project/cockpit/blob/master/HACKING.md).\n\nChannels\n--------\n\nCockpit can be doing lots of things at the same time and we don't want to have to open a new WebSocket each time. So we allow the protocol to be shared by multiple concurrent tasks. Each of these is assigned a *channel*. Channels have a string identifier. The data transferred in a channel is called the payload. To combine these into a message I simply concatenate the identifier, a new line, and the payload. Lets say I wanted to send the message `Oh marmalade!` over the channel called `scruffy` the message would look like this:\n\n```text\nscruffy\nOh marmalade!\n```\n\nHow do we know what channel to send messages on? We send *control messages* on a *control channel* to open other channels, and indicate what they should do. The identifier for the control channel is an empty string. More on that below.\n\nFraming\n-------\n\nIn order to pass a message based protocol over a plain stream, such the standard in and standard out of `cockpit-bridge`, one needs some form of framing. This framing is not used when the messages are passed over a WebSocket, since WebSockets inherently have a message concept.\n\nThe framing the `cockpit-bridge` uses is simply the byte length of the message, encoded as a string, and followed by a new line. So Scruffy's 21 byte message above, when sent over a stream, would like this:\n\n```text\n21\nscruffy\nOh marmalade!\n```\n\nAlternatively, when debugging or testing `cockpit-bridge` you can run in an interactive mode, where we frame our messages by using boundaries. That way we don't have to count the byte length of all of our messages meticulously, if we're writing them by hand. We specify the boundary when invoking `cockpit-bridge` like so:\n\n```text\n$ cockpit-bridge --interact=----\n```\n\nAnd then we can send a message by using the `----` boundary on a line by itself:\n\n```text\nscruffy\nOh marmalade!\n----\n```\n\nControl channels\n----------------\n\nBefore we can use a channel, we need to tell `cockpit-bridge` about the channel and what that channel is meant to do. We do this with a *control message* sent on the *control channel*. The *control channel* is a channel with an empty string as an identifier. Each control message is a JSON object, or dict. Each control message has a `\"command\"` field, which determines what kind of control message it is.\n\nThe `\"open\"` control message opens a new channel. The `\"payload\"` field indicates the type of the channel, so that `cockpit-bridge` knows what to do with the messages. The various [channel types are documented](https://github.com/cockpit-project/cockpit/blob/master/doc/protocol.md). Some channels connect talk to a DBus service, others spawn a process, etc.\n\nWhen you send an `\"open\"` you also choose a new channel identifier and place it in the `\"channel\"` field. This channel identifier must not already be in use.\n\nThe `\"echo\"` channel type just sends the messages you send to the `cockpit-bridge` back to you. Here's the control message that is used to open an echo channel. Note the empty channel identifier on the first line:\n\n<pre>\n\n{\n  \"command\": \"open\",\n  \"channel\": \"mychannel\",\n  \"payload\": \"echo\"\n}\n</pre>\n\nNow we're ready to play ... Well almost.\n\nThe very first control message sent to and from `cockpit-bridge` should be an `\"init\"` message containing a version number. That version number is `1` for the foreseeable future.\n\n<pre>\n\n{\n  \"command\": \"init\",\n  \"version\": 1\n}\n</pre>\n\nTry it out\n----------\n\nSo combining our knowledge so far, we can run the following:\n\n```text\n$ cockpit-bridge --interact=----\n```\n\nIn this debugging mode sent by `cockpit-bridge` will be bold in your terminal. Now paste the following in:\n\n<pre>\n\n{ \"command\": \"open\", \"channel\": \"mychannel\", \"payload\": \"echo\" }\n----\nmychannel\nThis is a test\n----\n</pre>\n\nYou'll notice that `cockpit-bridge` sends your message back. You can use this technique to experiment. Unfortunately\n`cockpit-bridge` exits immediately when it's stdin closes, so you [can't yet use shell redirection from a file effectively](https://github.com/cockpit-project/cockpit/issues/1594).\n\nMaking a DBus method call\n-------------------------\n\nTo make a DBus method call, we open a channel with the payload type `\"dbus-json3\"`. Then we send JSON messages as payloads inside that channel. An additional field in the `\"open\"` control message is required. The `\"name\"` field is the bus name of the DBus service we want to talk to:\n\n<pre>\n\n{\n  \"command\": \"open\",\n  \"channel\": \"mydbus\",\n  \"payload\": \"dbus-json3\",\n  \"name\": \"org.freedesktop.hostname1\"\n}\n</pre>\n\nOnce the channel is open we send a JSON object as a payload in the channel with a `\"call\"` field. It is set to an array with the DBus interface, DBus object path, method name, and an array of arguments.\n\n<pre>\nmydbus\n{\n  \"call\": [ \"/org/freedesktop/hostname1\", \"org.freedesktop.hostname1\",\n```unknown\n        \"SetStaticHostname\", [ \"mypinkpony.local\", true ] ],\n  \"id\": \"cookie\"\n}\n</pre>\n```\n\nIf we want a reply from the service we specify an `\"id\"` field. The resulting `\"reply\"` will have a matching `\"id\"` and would look something like this:\n\n<pre>\nmydbus\n{\n  \"reply\": [ null ],\n  \"id\": \"cookie\"\n}\n</pre>\n\nIf an error occurred you would see a reply like this:\n\n<pre>\nmydbus\n{\n  \"error\": [\n```unknown\n\"org.freedesktop.DBus.Error.UnknownMethod\",\n[ \"MyMethodName not available\"]\n  ],\n  \"id\":\"cookie\"\n}\n</pre>\n```\n\nThis is just the basics. You can do much more than this with DBus, including watching for signals, lookup up properties, tracking when they change, introspecting services, watching for new objects to show up, and so on.\n\nSpawning a process\n------------------\n\nSpawning a process is easier than calling a DBus method. You open the channel with the payload type `\"stream\"` and you specify the process you would like to spawn in the `\"open\"` control message:\n\n<pre>\n\n{\n  \"command\": \"open\",\n  \"channel\": \"myproc\",\n  \"payload\": \"stream\",\n  \"spawn\": [ \"ip\", \"addr\", \"show\" ]\n}\n</pre>\n\nThe process will send its output in the payload of one or more messages of the `\"myproc\"` channel, and at the end you'll encounter the `\"close\"` control message. We haven't looked at until now. A `\"close\"` control message is sent when a channel closes. Either the `cockpit-bridge` or its caller can send this message to close a channel. Often the `\"close\"` message contains additional information, such as a problem encountered, or in this case the exit status of the process:\n\n<pre>\n\n{\n  \"command\": \"close\",\n  \"channel\": \"myproc\",\n  \"exit-status\": 0\n}\n</pre>\n\nDoing it over a WebSocket\n-------------------------\n\nObviously in Cockpit we send all of these messages from the browser through a WebSocket hosted by `cockpit-ws`. `cockpit-ws` then passes them on to `cockpit-bridge`. You can communicate this way too, if you [configure Cockpit to accept different Websocket Origins](https://cockpit-project.org/guide/cockpit.conf.5.html).\n\nAnd on it goes\n--------------\n\nThere are payload types for reading files, replacing them, connecting to unix sockets, accessing system resource metrics, doing local HTTP requests, and more. Once the protocol is stable, solid documentation is in order.\n\nI hope that this has given some insight into how Cockpit works under the hood. If you're interested in using this same protocol, I'd love to get feedback ... especially while the basics of the protocol are not yet frozen.\n"
  },
  {
    "path": "_posts/2015-06-09-cockpit-does-kubernetes.md",
    "content": "---\ntitle: Cockpit's Kubernetes Dashboard\ndate: 2015-06-09 23:51\ntags: cockpit technical kubernetes\nslug: cockpit-kubernetes-dashboard\ncategory: release\n---\n\nHere's a video showing what I've been working on together with some help from a couple Cockpit folks. It's a [Cockpit](https://cockpit-project.org) dashboard for Kubernetes.\n\nIf you haven't heard about [Kubernetes](http://kubernetes.io/) ... it's a way to schedule docker containers across a cluster of machines, and take care of their networking, storage, name resolution etc. It's not completely baked, but pretty cool when it works.\n\n<iframe src=\"//www.youtube.com/embed/Fcfsu22RssU\" html5=1 frameborder=\"0\" height=\"450\" width=\"800\"></iframe>\n\nThe Cockpit dashboard you see in the video isn't done by any means ... there's a lot missing. But I'm pretty happy with what we have so far. I'm using Cockpit 0.61 in the demo. There are some nagging details to make things work, but hopefully we can solve them later. The Nulecule support isn't merged yet, [Subin has been working on it](https://github.com/cockpit-project/cockpit/pull/2332).\n\nThe Cockpit dashboard actually mostly works with [Openshift v3](https://github.com/openshift/origin). Openshift v3 is based on Kubernetes underneath, which makes apps that are developed there really portable.\n"
  },
  {
    "path": "_posts/2015-07-10-rest-api-plugin.md",
    "content": "---\ntitle: Making REST calls from Javascript in Cockpit\ndate: '2015-07-10'\ncategory: tutorial\ntags: cockpit linux\nslug: making-rest-calls-from-javascript-in-cockpit\n---\n\n*Note: This post has been updated for changes in Cockpit 0.90 and later.*\n{:.note}\n\n[Cockpit is a user interface for servers](https://cockpit-project.org). In [earlier](https://cockpit-project.org/blog/creating-plugins-for-the-cockpit-user-interface.html) [tutorials](https://cockpit-project.org/blog/using-dbus-from-javascript-in-cockpit.html) there's a guide on how to add components to Cockpit.\n\nNot all of the [system APIs use DBus](https://cockpit-project.org/blog/d-bus-is-powerful-ipc.html). So sometimes we find ourselves in a situation where we have to use REST (which is often just treated as another word for HTTP) to talk to certain parts of the system. For example [Docker has a REST API](https://docs.docker.com/reference/api/docker_remote_api/).\n\nFor this tutorial you'll need at least Cockpit 0.58. There was one last tweak that helped with the ```superuser``` option you see below. You can install it in [Fedora 22](https://cockpit-project.org/running.html) or [build it from git](https://github.com/cockpit-project/cockpit/blob/master/HACKING.md).\n\nHere we'll make a package called *docker-info* which shows info about the docker daemon. We use the `/info` [docker API](https://docs.docker.com/reference/api/docker_remote_api_v1.18/#display-system-wide-information) to retrieve that info.\n\nI've prepared the [docker-info package here](https://cockpit-project.org/files/docker-info.tgz). It's just two files. To download them and extract to your current directory, and installs it as a Cockpit package:\n\n```text\n$ wget https://cockpit-project.org/files/docker-info.tgz -O - | tar -xzf -\n$ cd docker-info/\n$ mkdir -p ~/.local/share/cockpit\n$ ln -snf $PWD ~/.local/share/cockpit/\n```\n\nPreviously we [talked about](https://cockpit-project.org/blog/creating-plugins-for-the-cockpit-user-interface.html) how packages are installed, and what `manifest.json` does so I won't repeat myself here. But to make sure the above worked correctly, you can run the following command. You should see `docker-info` listed in the output:\n\n```text\n$ cockpit-bridge --packages\n...\ndocker-info: .../.local/share/cockpit/docker-info\n...\n```\n\nIf you're logged into Cockpit on this machine, first log out. And log in again. Make sure to log into Cockpit with your current user name, since you installed the package in your home directory. You should now see a new item in the *Tools* menu called *Docker Info*:\n\n![Docker Info tool](/images/cockpit-docker-info.png)\n\nAfter a moment, you should see numbers pop up with some stats about the docker daemon. Now in a terminal try to run something like:\n\n```text\n$ sudo docker run -ti fedora /bin/bash\n```\n\nYou should see the numbers update as the container is pulled and started. When you type ```exit``` in the container, you should see the numbers update again. How is this happening? Lets take a look at the `docker-info` HTML:\n\n```html\n<head>\n    <title>Docker Info</title>\n    <meta charset=\"utf-8\">\n    <link href=\"../base1/cockpit.css\" type=\"text/css\" rel=\"stylesheet\">\n    <script src=\"../base1/jquery.js\"></script>\n    <script src=\"../base1/cockpit.js\"></script>\n</head>\n<body>\n    <div class=\"container-fluid\">\n        <h2>Docker Daemon Info</h2>\n        <ul>\n            <li>Total Memory: <span id=\"docker-memory\">?</span></li>\n            <li>Go Routines: <span id=\"docker-routines\">?</span></li>\n            <li>File Descriptors: <span id=\"docker-files\">?</span></li>\n            <li>Containers: <span id=\"docker-containers\">?</span></li>\n            <li>Images: <span id=\"docker-images\">?</span></li>\n        </ul>\n    </div>\n\n    <script>\n        var docker = cockpit.http(\"/var/run/docker.sock\", { superuser: \"try\" });\n\n        function retrieve_info() {\n            var info = docker.get(\"/info\");\n            info.done(process_info);\n            info.fail(print_failure);\n        }\n\n        function process_info(data) {\n            var resp = JSON.parse(data);\n            $(\"#docker-memory\").text(resp.MemTotal);\n            $(\"#docker-routines\").text(resp.NGoroutines);\n            $(\"#docker-files\").text(resp.NFd);\n            $(\"#docker-containers\").text(resp.Containers);\n            $(\"#docker-images\").text(resp.Images);\n        }\n\n        /* First time */\n        retrieve_info();\n\n        var events = docker.get(\"/events\");\n        events.stream(got_event);\n        events.always(print_failure);\n\n        function got_event() {\n            retrieve_info();\n        }\n\n        function print_failure(ex) {\n            console.log(ex);\n        }\n    </script>\n</body>\n</html>\n```\n\nFirst we include `jquery.js` and `cockpit.js`. `cockpit.js` defines the basic API for interacting with the system, as well as Cockpit itself. You can find [detailed documentation here](https://cockpit-project.org/guide/latest/api-cockpit.html).\n\n```html\n<script src=\"../base1/jquery.js\"></script>\n<script src=\"../base1/cockpit.js\"></script>\n```\n\nWe also include the cockpit.css file to make sure the look of our tool matches that of Cockpit. The HTML is pretty basic, defining a little list where the info shown.\n\nIn the javascript code, first we setup an HTTP client to access docker. Docker listens for HTTP requests on a Unix socket called `/var/run/docker.sock`. In addition the permissions on that socket often require escalated privileges to access, so we tell Cockpit to try to gain `superuser` privileges for this task, but continue anyway if it cannot:\n\n```javascript\nvar docker = cockpit.http(\"/var/run/docker.sock\", { superuser: \"try\" });\n```\n\nFirst we define how to retrieve info from Docker. We use the REST `/info` API to do this.\n\n```javascipt\nfunction retrieve_info() {\n    var info = docker.get(\"/info\");\n    info.done(process_info);\n    info.fail(print_failure);\n}\n```\n\nIn a browser you cannot stop and wait until a REST call completes. Anything that doesn't happen instantaneously gets its results reported back to you by [means of callback handlers](https://cockpit-project.org/guide/latest/api-cockpit.html#cockpit-http-done). jQuery has a standard interface [called a promise](http://api.jquery.com/deferred.promise/). You add handlers by calling the `.done()` or `.fail()` methods and registering callbacks.\n\nThe result of the `/info` call is JSON, and we process it here. This is standard jQuery for filling in text data into the various elements:\n\n```javascript\nfunction process_info(data) {\n    var resp = JSON.parse(data);\n    $(\"#docker-memory\").text(resp.MemTotal);\n    $(\"#docker-routines\").text(resp.NGoroutines);\n    $(\"#docker-files\").text(resp.NFd);\n    $(\"#docker-containers\").text(resp.Containers);\n    $(\"#docker-images\").text(resp.Images);\n}\n```\n\nAnd then we trigger the invocation of our `/info` REST API call.\n\n```javascript\n/* First time */\nretrieve_info();\n```\n\nBecause we want to react to changes in Docker state, we also start a long request to its `/events` API.\n\n```javascript\nvar events = docker.get(\"/events\");\n```\n\nThe `.get(\"/events\")` call returns a jQuery Promise. When a line of event data arrives, the `.stream()` callback in invoked, and we use it to trigger a reload of the Docker info.\n\n```javascript\nevents.stream(got_event);\nevents.always(print_failure);\n\nfunction got_event() {\n    retrieve_info();\n}\n```\n\nThis is a simple example, but I hope it helps you get started. There are further REST [javascript calls](https://cockpit-project.org/guide/latest/api-cockpit.html#latest-http). Obviously you can also do `POST` and so on.\n"
  },
  {
    "path": "_posts/2015-09-23-cockpit-0.77.md",
    "content": "---\ntitle: Cockpit 0.77 Released\ndate: 2015-09-23 21:23\ntags: cockpit linux technical\nslug: cockpit-0.77\nsummary: Cockpit releases every week. This week it was 0.77\ncategory: release\n---\n\nCockpit releases every week. This week it was 0.77\n\n### Componentizing Cockpit\n\nMarius and Stef completed a long running refactoring task of splitting\nCockpit into components.\n\nIn an age long gone Cockpit used to be one monolithic piece of HTML and\njavascript. Over the last year we've steadily refactored to split this\nout so various components can be loaded optionally and/or from different\nservers depending on capabilities and operating system versions.\n\nMarius also removed a cockpitd DBus service that we've also been moving\naway from. Cockpit wants to talk to system APIs and not install its own\nAPI wrappers like cockpitd.\n\n\n### The URLs changed\n\nBecause of the above, we unfortunately had to change the URLs. But we've\ntaken the opportunity to make them a lot simpler and cleaner.\n\n<iframe width=\"640\" height=\"480\" src=\"//youtube.com/embed/xLa4uRyGVrA?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Authentication when Embedding Cockpit\n\nStef worked on partitioning the cockpit authentication so that embedders\nof Cockpit components don't need to share authentication state with a\nnormal instance of Cockpit loaded in a browser.\n\n<iframe width=\"640\" height=\"480\" src=\"//youtube.com/embed/xbxvEFXaIGw?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Deleting and Adjusting Kubernetes Objects\n\nSubin implemented deletion kubernetes objects, and adjust things like\nthe number of replicas in Replication Controllers.\n\n<iframe width=\"640\" height=\"480\" src=\"//youtube.com/embed/tiv9tIs4qkw?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n\n### Warning when too many machines\n\nCockpit now gives a warning when adding \"too many\" machines to the\ndashboard. We've set the warning to 20 machines, but various operating\nsystems can set this warning to be lower.\n\n![Screenshot](https://trello-attachments.s3.amazonaws.com/55d623eddcb5795e8b5cff13/968x790/0e77b8ce653b79d29a2cc9de75b86b03/dc0c74d8-5e2f-11e5-91fc-901b633a059d.png)\n\n\n### From the Future\n\nAndreas did designs for managing the SSH keys loaded for use when connecting to machines:\n\n![Wireframes](https://trello-attachments.s3.amazonaws.com/55f14b769262e42e89775936/3555x3301/0c0166255eaf092025c8a5c95f84f15f/ssh-keys-v2.png)\n\n\n### Try it out\n\nCockpit 0.77 is available now here:\n\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.77)\n * [Fedora 23 and Fedora Rawhide](https://bodhi.fedoraproject.org/updates/FEDORA-2015-16557)\n * [COPR for Fedora 21, 22, CentOS and RHEL](https://copr.fedoraproject.org/coprs/sgallagh/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2015-09-30-cockpit-0.78.md",
    "content": "---\ntitle: Cockpit 0.78 Released\ndate: 2015-09-30 21:23\ntags: cockpit linux technical\nslug: cockpit-0.78\nsummary: Cockpit releases every week. This week it was 0.78\ncategory: release\n---\n\nCockpit releases every week. This week it was 0.78\n\n<!--BREAK-->\n\n### Multipath Storage\n\nCockpit now deals with multipath storage, although it doesn't yet provide a way to set it up.\n\n<iframe width=\"640\" height=\"480\" src=\"//youtube.com/embed/QPDUNpG7Z2o?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Cockpit Guide\n\nThe Cockpit Guide has been updated and includes information about how\nvarious features are implemented, and what sort of privileges they use\non the system.\n\nHere's a link to [the guide](https://cockpit-project.org/guide/latest/) or you can take a look at\nthe [privileges docs](https://cockpit-project.org/guide/latest/privileges.html).\n\n\n### Compatibility with old Cockpit\n\nRecent releases of Cockpit had some compatibility issues when older servers were added to the dashboard, and vice versa. These have been fixed in 0.78\n\n\n### CPU usage issue\n\nA CPU usage bug in Cockpit 0.77 was fixed.\n\n\n### From the future\n\nMarius has done some really cool work on iSCSI. It's not yet in a Cockpit release, but take a peek here:\n\n<iframe width=\"640\" height=\"480\" src=\"//youtube.com/embed/N1Lw2OVLDoo?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n\n### Try it out\n\nCockpit 0.78 is available now:\n\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.78)\n * [Fedora 23 and Fedora Rawhide](https://bodhi.fedoraproject.org/updates/FEDORA-2015-977ba13a92)\n * [COPR for Fedora 21, 22, CentOS and RHEL](https://copr.fedoraproject.org/coprs/sgallagh/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2015-10-07-cockpit-0.79.md",
    "content": "---\ntitle: Cockpit 0.79 Released\ndate: 2015-10-07 22:23\ntags: cockpit linux technical\nslug: cockpit-0.79\nsummary: Cockpit releases every week. This week it was 0.79\ncategory: release\n---\n\nCockpit releases every week. This week it was 0.79\n\n### Vagrant File\n\nCockpit now has a vagrant file. If you want to checkout the latest\nCockpit, test pull requests, or hack on Cockpit, you can:\n\n```text\n$ sudo vagrant up\n\n... in a Cockpit git repo. There's a\n[tutorial with more information](https://cockpit-project.org/blog/cockpit-vagrantfile.html)\n```\n\n### Testing with libvirt\n\nDominik migrated the Cockpit integration tests to run on libvirt, rather\nthan using Qemu directly. This makes the tests more portable, and is an\nimportant step towards running them distributed.\n\n\n### From the future\n\nMarius has done some work on configuring NTP servers. Hopefully this will\nbe in a release soon:\n\n<iframe width=\"640\" height=\"480\" src=\"//youtube.com/embed/aZ1Nm2ZkW3Q?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n\n### Try it out\n\nCockpit 0.79 is available now:\n\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.79)\n * [Fedora 23 and Fedora Rawhide](https://bodhi.fedoraproject.org/updates/FEDORA-2015-7e1880ba02)\n * [COPR for Fedora 21, 22, CentOS and RHEL](https://copr.fedoraproject.org/coprs/sgallagh/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2015-10-08-cockpit-vagrantfile.md",
    "content": "---\ntitle: Using Vagrant to Develop Cockpit\ndate: '2015-10-08'\ncategory: tutorial\ntags: cockpit linux\nslug: cockpit-vagrantfile\n---\n\nStarting with Cockpit release 0.79 you can use [Vagrant](https://www.vagrantup.com/) to bring up a VM in which\nyou can test or develop Cockpit. The VM is isolated from your main system so any system configuration\nyou change via Cockpit will only happen in the VM.\n\nThe Vagrant VM mounts the Cockpit package assets from your git repository checkout, so when you make on the\nhost system, you can refresh the browser and immediately see the resulting changes. For changes to\nC code, the Cockpit binaries would have to be rebuilt and testing via Vagrant won't work.\n\n\n## Getting Started\n\nTo start, you'll need Vagrant. On Fedora I use *vagrant-libvirt*. In addition keep in mind that on\n*vagrant-libvirt* requires root privileges, so you'll need to use vagrant with `sudo`.\n\n```text\n$ sudo yum install vagrant vagrant-libvirt\n```\n\nNext, in a copy of the Cockpit git repository, you run `vagrant up`:\n\n\n```text\n$ git clone https://github.com/cockpit-project/cockpit\n$ cd cockpit\n$ sudo vagrant up\n```\n\nThe first time this runs it'll take a while, but eventually you'll have a Vagrant VM running. When you\ndo this step again, it should be pretty fast.\n\nThe VM will\nlisten for connections on your local machine's [`http://localhost:9090`](http://localhost:9090), but\neven though you're connecting to *localhost* it'll be Cockpit in the VM you're talking to.\n\nIf you already have Cockpit running on your local machine, then this won't work, and you'll need to\nuse the IP address of the VM instead of *localhost*. To find it:\n\n```text\n$ sudo vagrant ssh-config\n```\n\nTwo user accounts are created in the VM, and you can use either one to log into Cockpit:\n\n * User: \"admin\" Password: \"foobar\"\n * User: \"root\" Password: \"foobar\"\n\n\n## Testing a Pull Request\n\nIf there's a Cockpit [pull request](https://github.com/cockpit-project/cockpit/pulls) that you'd like to\ntest, you can now do that with the Vagrant VM.  Replace the *0000* in the following command with the\nnumber of the pull request:\n\n```text\n$ git fetch origin pull/0000/head\n$ git checkout FETCH_HEAD\n```\n\nThe pull request can only contain code to Cockpit package assets. If it contains changes to the `src/`\ndirectory, then the pull request involves rebuilding binaries, and testing it via Vagrant won't work.\n\nNow refresh your browser, or if necessary, login again. You should see the changes in the pull request\nreflected in Cockpit.\n\n\n## Making a change\n\nYou can make a change to Cockpit while testing that out in your Vagrant VM. The changes should be\nto Cockpit package assets. If you change something in the `src/` directory, then binaries will have\nto be rebuilt, and testing it via Vagrant won't work.\n\nI chose change some wording in the sidebar in `pkg/shell/index.html`:\n\n```text\n          <a data-toggle=\"collapse\" data-target=\"#tools-panel\" class=\"collapsed\" translatable=\"yes\">\n-           Tools\n+           Beavers 'n Ducks\n          </a>\n```\n\nAnd after refreshing Cockpit, I can see that change:\n\n![Showing the change made](/images/vagrant-change.png)\n\nThe same applies to javascript or CSS changes as well. In order to actually contribute a change to Cockpit\nyou'll want to look at the information about\n[Contributing](https://github.com/cockpit-project/cockpit/wiki/Contributing) and if you need help\nunderstanding how to add a\n[plugin package](https://cockpit-project.org/blog/creating-plugins-for-the-cockpit-user-interface.html)\nyou can look at the [Developer Guide](https://cockpit-project.org/guide/latest/development.html).\n\n\n## Bringing the Vagrant VM in sync\n\nAfter each Cockpit release, there will be new binary parts to Cockpit. In order to continue to use the\nVagrant VM, you'll need to rebuild it. A message like this should appear when that's necessary.\n\n![Cockpit is incompatible with sources](/images/cockpit-incompatible-sources.png)\n\nRebuild the Vagrant VM like this:\n\n```text\n$ sudo vagrant destroy\n$ sudo vagrant up\n```\n\n## Troubleshooting\n\nOn Fedora, FirewallD got in the way of Vagrants use of NFS. On my machine, I had to do this\nto get it to work:\n\n```text\n$ sudo firewall-cmd --set-default-zone=trusted\n"
  },
  {
    "path": "_posts/2015-10-14-cockpit-0.80.md",
    "content": "---\ntitle: Cockpit 0.80 Released\ndate: 2015-10-14 22:19\ntags: cockpit linux technical\nslug: cockpit-0.80\nsummary: Cockpit releases every week. This week it was 0.80\ncategory: release\n---\n\nCockpit releases every week. This week it was 0.80\n\n### SSH private keys\n\nYou can now use Cockpit to load SSH private keys into the ssh-agent that's\nrunning in the Cockpit login session. These keys are used to authenticate\nagainst other systems when they are added to the dashboard. Cockpit also\nsupports inspecting and changing the passwords for SSH private keys.\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/RZ_N2iCPm_U\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Always start an SSH agent\n\nCockpit now always starts an SSH agent in the Cockpit login session. Previously\nthis would happen if the correct PAM modules were loaded.\n\n### From the future\n\nPeter has done work to build an OSTree UI, useful for upgrading and rolling back\nthe operating system on Atomic Host:\n\n[![OSTree Design Work](/images/cockpit-ostree-design.png)](https://raw.githubusercontent.com/cockpit-project/cockpit-design/master/software-updates/software-updates-ostree-alt.png)\n\nSubin has done work to get Nulecule Kubernetes applications working with Atomic\nand larger Kubernetes clusters.\n\n### Try it out\n\nCockpit 0.80 is available now:\n\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.80)\n * [Fedora 23 and Fedora Rawhide](https://bodhi.fedoraproject.org/updates/FEDORA-2015-28a7f2b07f)\n * [COPR for Fedora 21, 22, CentOS and RHEL](https://copr.fedoraproject.org/coprs/sgallagh/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2015-10-21-cockpit-0.81.md",
    "content": "---\ntitle: Cockpit 0.81 Released\ndate: 2015-10-21 22:19\ntags: cockpit linux technical\nslug: cockpit-0.81\nsummary: Cockpit releases every week. This week it was 0.81\ncategory: release\n---\n\nCockpit releases every week. This week it was 0.81\n\n\n### NTP servers\n\nCockpit now allows configuration of which NTP servers are used for time syncing.  This configuration is possible when [timesyncd](http://www.freedesktop.org/software/systemd/man/systemd-timesyncd.service.html) is being used as the NTP service.\n\n<iframe width=\"640\" height=\"480\" src=\"//youtube.com/embed/Rmzt1L4ANgo?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Network switch regression\n\nThere was a regression in Cockpit 0.78 where certain on/off switches in the networking configuration stopped working. This has now been fixed.\n\n\n### Delete Openshift routes and deployment configs\n\nIn the Kubernetes cluster dashboard, it's now possible to delete Openshift style routes and deployment configs.\n\n### From the future\n\nI've refactored the Cockpit Kubernetes [container terminal widget](https://github.com/kubernetes-ui/container-terminal/) for use by other projects. It's been integrated into the Openshift Web Console for starters. This widget will be used by Cockpit soon.\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/SMxVQBD3Kho?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Try it out\n\nCockpit 0.81 is available now:\n\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.81)\n * [Fedora 23 and Fedora Rawhide](https://bodhi.fedoraproject.org/updates/FEDORA-2015-c3b74dffee)\n * [COPR for Fedora 21, 22, CentOS and RHEL](https://copr.fedoraproject.org/coprs/sgallagh/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2015-10-28-cockpit-0.82.md",
    "content": "---\ntitle: Cockpit 0.82 Released\ndate: 2015-10-28 19:05\ntags: cockpit linux technical\nslug: cockpit-0.82\nsummary: Cockpit releases every week. This week it was 0.82\ncategory: release\n---\n\nCockpit releases every week. This week it was 0.82\n\n### Distributed Tests\n\nIn Cockpit we run thousands of integration tests per day against pull requests and git master. Each test brings up up Cockpit in a full operating system VM, and hammers on it in some way. Without these tests it's impossible to validate that Cockpit actually works.\n\nLast week, the server doing this testing work broke down. I've been working over the last week to fix that, along with others.\n\nBut we've done more, instead of just putting this on another server, we've worked to make these integration tests run in a distributed manner across several machines each doing a part of the tests.\n\nThe tests are staged via privileged containers, and run in libvirt VMs.\n\nHere's [some documentation](https://github.com/cockpit-project/cockpit/blob/master/test/README) on how to use the new tests.\n\n\n### Certificate Chains\n\nCockpit has supported using certificate chains for its cockpit-ws component, but only when the underying GLib (2.44+) supported it. In this release we start to support running TLS with proper certificate chains even on older GLib versions. The [documentation](https://cockpit-project.org/guide/0.82/https.html#https-certificates) and appropriate tests were updated.\n\n### Try it out\n\nCockpit 0.82 is available now:\n\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.82)\n * [Fedora 23 and Fedora Rawhide](https://bodhi.fedoraproject.org/updates/FEDORA-2015-273bc74c11)\n * [COPR for Fedora 21, 22, CentOS and RHEL](https://copr.fedoraproject.org/coprs/sgallagh/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2015-11-19-cockpit-0.84.md",
    "content": "---\ntitle: Cockpit 0.83 and 0.84 Released\ndate: 2015-11-19 11:24\ntags: cockpit linux technical\nslug: cockpit-0.84\nsummary: Cockpit releases every week. This week it was 0.84\ncategory: release\n---\n\nCockpit releases every week. This week it was 0.84. I'll also include notes from 0.83 here.\n\n### Building Cockpit on Debian\n\nAt systemd.conf Dominik worked with Michael Biebl one of the Debian systemd maintainers on packaging Cockpit for Debian. We're still looking for a maintainer long term.\n\nHere's a [blog post](http://dominik.perpeet.eu/cockpit-on-debian-8-2) with more details.\n\n\n### Cross Distro Integration Tests\n\nIn Cockpit we run hundreds of tests on real operating systems for each pull request. Without running these tests on an OS it's impossible to know that the features of Cockpit actually works. So far we've been running these tests on Fedora, Atomic, and RHEL. But we'd really like to run them on Debian as well. That'll make Cockpit much more well rounded.\n\nMarius worked on the first steps toward running the tests on Debian, by doing the Cockpit [build inside of our test VM images](https://github.com/cockpit-project/cockpit/pull/3138). Hopefully we'll see more progress on this.\n\n\n### SELinux certificate file type\n\nThe ```cockpit.service``` helpfully sets the appropriate user and group [on the certificates](https://cockpit-project.org/guide/latest/https.html) that cockpit-ws will use for TLS. Now it also sets the SELinux file context type properly, so this is one less things to break for an admin.\n\n\n### Cockpit manual page\n\nThere is now a ```man cockpit``` overview manual page that links to the guide and elsewhere.\n\n\n### From the future\n\nMarius has done work on an SOS reporting view. Needs some further backend work, but should be ready soon:\n\n<iframe width=\"640\" height=\"480\" src=\"//youtube.com/embed/-6rfWUoOQbs?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\nPeter has mostly completed the work to add machines with alternate users, and non-standard SSH ports. Among other things, this is useful for cloud instances. I'm looking forward to seeing this in Cockpit 0.85.\n\n\n[![Machine Dialogs Wireframes](/images/machine-dialogs.png)](https://raw.githubusercontent.com/cockpit-project/cockpit-design/master/add-system/machine-dialogs.png)\n\n\n### Try it out\n\nCockpit 0.84 is available now:\n\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.84)\n * [Fedora 23 and Fedora Rawhide](https://bodhi.fedoraproject.org/updates/FEDORA-2015-96b41c5190)\n * [COPR for Fedora 22, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2015-11-27-cockpit-0.85.md",
    "content": "---\ntitle: Cockpit 0.85 Released\ndate: 2015-11-27 11:24\ntags: cockpit linux technical\nslug: cockpit-0.85\nsummary: Cockpit releases every week. This week it was 0.85\ncategory: release\n---\n\nCockpit releases every week. This week it was 0.85.\n\n### Varying users on dashboard machines\n\nCockpit now supports adding machines to the dashboard with different\nuser logins for each one. This can be useful in cases where you're\nadding cloud instances to your dashboard, and they require logging in\nwith a *cloud-user* and not the same user as your other servers.\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/N93I0gzvj5c?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n\n### Non standard SSH ports\n\nWhen Cockpit connects to a machine that was added to the dashboard, it\ndoes so over SSH. Cockpit can now connect on non-standard SSH ports.\n\nSee the video above.\n\n\n### Troubleshooting machine connectivity\n\nCockpit now allows you to fix connectivity issues for servers that are\nadded to the dashboard. This includes adjusting authentication, checking\non host keys and more.\n\n[![Machine Dialogs Wireframes](/images/machine-dialogs.png)](https://raw.githubusercontent.com/cockpit-project/cockpit-design/master/add-system/machine-dialogs.png)\n\n\n### Fix SELinux certificate file type bug\n\nCockpit 0.84 failed to start on certain distros because SELinux wasn't\navailable or couldn't be used to reset the certificate file context.\nThis [bug has been fixed](https://github.com/cockpit-project/cockpit/issues/3206).\n\n\n### Work around bug in Firefox 42\n\nA bug in Firefox 42 caused Cockpit to often load with a blank screen,\ndue to layout calculation issues. The layout code has been changed to\nwork around [this issue](https://bugzilla.redhat.com/show_bug.cgi?id=1185136).\n\n\n### Docker restart container timeout\n\nPreviously Cockpit called the Docker API without a timeout when\nrestarting containers. This caused Docker to immediately kill the\ncontainer without waiting for it to shutdown cleanly. Cockpit now\n[passes a timeout](https://github.com/cockpit-project/cockpit/issues/3230).\n\n\n### From the future\n\nMarius has [made progress](https://github.com/cockpit-project/cockpit/pull/3202)\ngetting the Cockpit integration test suite to run on Debian. Without the\nintegration tests running for a certain distro, there's no way to ensure Cockpit\nactually works there.\n\n\n### Try it out\n\nCockpit 0.85 is available now:\n\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.85)\n * [Fedora 23 and Fedora Rawhide](https://bodhi.fedoraproject.org/updates/FEDORA-2015-e368240084)\n * [COPR for Fedora 22, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2015-12-04-cockpit-0.86.md",
    "content": "---\ntitle: Cockpit 0.86 Released\ndate: 2015-12-04 13:04\ntags: cockpit linux technical\nslug: cockpit-0.86\ncategory: release\nsummary: Cockpit releases every week. This week it was 0.86\n---\n\nCockpit releases every week. This week it was 0.86.\n\n### SOS Reporting\n\nUsers can now prepare an SOS Report containing information about the system and send it to their support representative.\n\n<iframe width=\"640\" height=\"480\" src=\"//youtube.com/embed/-6rfWUoOQbs?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### From the future\n\nStef has done work to cleanup the Javascript dependencies of Cockpit. Broadly these fall into two categories:\n\n* Development dependencies: only used while developing Cockpit, not even used while building the tarball. These are ```node_modules```\n\n* Runtime dependencies: used while Cockpit is running and built\ninto the various Cockpit packages. These are ```bower_components```\n\nThe latter should be replaceable at build-time. The cleanup work moves in this direction, but it's not complete yet.\n\n### Try it out\n\nCockpit 0.86 is available now:\n\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.85)\n * [Fedora 23 and Fedora Rawhide](https://bodhi.fedoraproject.org/updates/FEDORA-2015-36d1df063f)\n * [COPR for Fedora 22, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2015-12-22-cockpit-0.89.md",
    "content": "---\ntitle: Cockpit 0.89 Released\ndate: 2015-12-22 13:04\ntags: cockpit linux technical\nslug: cockpit-0.89\ncategory: release\nsummary: Cockpit releases every week. This week it was 0.89\n---\n\nCockpit releases every week. Here's a summary of the 0.87, 0.88 and 0.89 releases.\n\n### OSTree upgrades and rollbacks\n\nPeter worked to finish the basic OSTree UI has been merged into Cockpit.\nThis lets the admin perform upgrades and rollbacks on Atomic Host.\n\nColin, Peter and the OSTree guys worked together to build a DBus\ninterface in rpm-ostree so that callers can interact with the update system.\n\n\nDemo: https://youtu.be/Tmj0Nrkasmk\n\nBefore this is usable by users, the cockpit-ostree package will need to\n(be included in Atomic Host, first on Fedora)[https://bugzilla.redhat.com/show_bug.cgi?id=1292826].\n\n\nCustom login authentication scripts\n-----------------------------------\n\nThe Cockpit WebService cockpit-ws component now supports custom\nauthenticators for various auth mechanisms. Some assembly required.\n\nPeter has implemented this as part of containerizing the kubernetes and\ndocker registry admin dashboards.\n\n<https://github.com/cockpit-project/cockpit/blob/master/doc/authentication.md>\n\n\nStubbed out bridge for non-local users\n--------------------------------------\n\nThis means that the Cockpit parts can be customized to that we can allow\nnon-local users to log in and interact with certain Cockpit components\nthat don't interact with the local system. Again this is part of\ncontainerizing the kubernetes and docker registry admin dashboards.\n\n\n\nSpecific dashboards can now be shown as default\n-----------------------------------------------\n\nA specific Cockpit dashboard can now be shown as the default when\nlogging in, by specifying a lower \"order\" than default dashboard.\n\n\n\n<https://github.com/cockpit-project/cockpit/pull/3317>\n\n\n\n\nFix login on Windows\n--------------------\n\nCockpit no longer prompts for a strange second login (which had to do\nwith SSO) on Windows. There are some remaining issues with how Cockpit\nworks on Internet Explorer, but most have been solved.\n\n<https://github.com/cockpit-project/cockpit/issues/2164>\n\n\nHost name in self-signed certificate\n------------------------------------\n\nIn order to make life easier, when generating a self-signed certificate,\nCockpit now includes the local host name. Self-signed certificates\nremain a stop gap. Real world deployments should replace them with\nproperly signed certificates from a certificate authority:\n\n<https://cockpit-project.org/guide/latest/https.html>\n\n\n\nRoutine Debian testing\n----------------------\n\nThe Cockpit Project has started routinely testing each Cockpit pull request on Debian Unstable using real Debian packaging. Marius did some great work here. This means we're are close to doing real continuous delivery to Debian. Next step, a repo, and a maintainer.\n\n<https://fedorapeople.org/groups/cockpit/status/debian-unstable.html>\n\nCase insensitive cockpit.conf\n-----------------------------\n\nThe cockpit.conf file is now case insensitive for options and headings. This should make editing it less error prone.\n\n<https://cockpit-project.org/guide/latest/cockpit.conf.5.html>\n\n\nReorder graphs on server summary page\n-------------------------------------\n\nThijs reordered the resource graphs on the server summary page in the same order as GNOME, Windows, and elsewhere.\n\n\nSyncing of users when adding a server\n-------------------------------------\n\nCockpit no longer requires or suggests that the admin accounts be synced between servers when adding another server to the dashboard. This feature is still available when editing the server options on the dashboard.\n\n\nWeak dependencies on Fedora 24+\n-------------------------------\n\nOn Fedora 24 and later, one can have 'Suggests' and 'Recommends' dependencies between packages. Cockpit now takes advantage of these for its 'cockpit' meta package making certain parts removable without removing 'cockpit'.\n\n\nVagrantfile working again\n-------------------------\n\nThe Vagrant file now pulls from the correct latest binary builds of Cockpit. To use it:\n\n\n```bash\n$ git clone https://github.com/cockpit-project/cockpit\n$ cd cockpit\n$ sudo vagrant up\n```\n\n### SOS Reporting\n\nUsers can now prepare an SOS Report containing information about the system and send it to their support representative.\n\n<iframe width=\"640\" height=\"480\" src=\"//youtube.com/embed/-6rfWUoOQbs?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### From the future\n\nStef has done work to cleanup the Javascript dependencies of Cockpit. Broadly these fall into two categories:\n\n* Development dependencies: only used while developing Cockpit, not even used while building the tarball. These are ```node_modules```\n\n* Runtime dependencies: used while Cockpit is running and built\ninto the various Cockpit packages. These are ```bower_components```\n\nThe latter should be replaceable at build-time. The cleanup work moves in this direction, but it's not complete yet.\n\n### From the future\n\n\nRyan Barry has posted a pull request adding tuned (system performance\nprofile) support to Cockpit:\n\n<https://github.com/cockpit-project/cockpit/pull/3279>\n\n\n\n\n### Try it out\n\nCockpit 0.86 is available now:\n\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.85)\n * [Fedora 23 and Fedora Rawhide](https://bodhi.fedoraproject.org/updates/FEDORA-2015-36d1df063f)\n * [COPR for Fedora 22, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2016-02-12-cockpit-0.95.md",
    "content": "---\ntitle: Cockpit 0.95 Released\ndate: 2016-02-12 20:32\ntags: cockpit linux technical\nslug: cockpit-0.95\ncategory: release\nsummary: Cockpit releases every week. Here's highlights from 0.90 through 0.95\n---\n\nCockpit releases every week. Here are the highlights from 0.90 through 0.95.\n\n\nSet CPU performance profile via tuned\n-------------------------------------\n\nCockpit can now talk to tuned and set the CPU performance profile of the\nsystem. Thanks to Ryan Barry for doing the initial prototype, and\nJaroslav Škarvada for fixing up tuned to include profile descriptions.\n\n<iframe width=\"640\" height=\"480\" src=\"//youtube.com/embed/u1ba4aQkueA?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n\niSCSI initiator support\n-----------------------\n\nThe iSCSI support that Marius worked on with the storaged folks has\nfinally landed in a Cockpit release. It was waiting on fixes in some\ndependencies. Have a look:\n\n<iframe width=\"640\" height=\"480\" src=\"//youtube.com/embed/N1Lw2OVLDoo?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n\nSupport for WebSocket client in cockpit-bridge\n----------------------------------------------\n\nIn order to better talk to services like Kubernetes or the Atomic Docker\nRegistry we've added WebSocket support to the cockpit-bridge. It can now\nconnect to local WebSockets on the system.\n\nBut here's an example of what you can do with that: The demo below shows\nGTK+ 3 apps running inside of Cockpit. GTK+ 3 supports HTML5 as a\ndisplay mode, and Cockpit can wrap that in authentication and a real\nLinux login session:\n\n<iframe width=\"640\" height=\"480\" src=\"//youtube.com/embed/6ZbTYj3xzzg?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n\nDebian Source Packages\n----------------------\n\nAs a step towards working getting Cockpit into Debian we now create\nDebian source packages during our continuous delivery process. These end\nup here for now:\n\n<pre>\ndeb-src https://fedorapeople.org/groups/cockpit/debian-unstable ./\n</pre>\n\n\nContent Security Policy\n-----------------------\n\nBecause the Cockpit javascript code has as much access to the system as\nthe logged in user, Cockpit needs to make sure that attackers cannot\nsneak in javascript code into the browser session.\n\nObviously we do this by escaping HTML output carefully and other best\npractices. But in addition to that we've started to deploy Content\nSecurity Policy.\n\nIf you're unfamiliar with [Content Security Policy](https://en.wikipedia.org/wiki/Content_Security_Policy)\n it's a bit like SELinux for a browser session. It tells the browser we explicitly don't\nwant to execute any code, styling or other resources that get loaded\nfrom Cockpit itself.\n\nWe haven't turned on the strict policy for all of Cockpit yet, and we're\ndoing it component by component.\n\n\nFix cockpit-ws start while reading from /dev/urandom\n----------------------------------------------------\n\nPreviously when there were interruptions during reading from\n/dev/urandom while starting cockpit-ws, then initialization would fail.\nThis has now been fixed.\n\n\nOAuth login support\n-------------------\n\nCockpit now has OAuth login support. It doesn't exactly work out of the\nbox for logging into a local Linux system, but it can be used to create\ncustom dashboards or containers based on Cockpit components that use\nOAuth to authenticate.\n\nSee [the documentation](https://rawgit.com/cockpit-project/cockpit/master/doc/authentication.md)\nfor more info.\n\n\nRunning RHEL QE Tests\n---------------------\n\nWhen you open a Cockpit pull request, take a look at the test suites\nthat are run against it.\n\nThis week we finished work to run the Cockpit RHEL QE tests upstream git\npull request. Rather than catching issues on the backend of things,\nwe'll be ahead of the game.\n\n\nVagrant without NFS\n-------------------\n\nCockpit's Vagrantfile used to use NFS to keep the git checkout in sync\nwith the image. This caused many folks to have a hard time using Vagrant\nto hack on Cockpit, so the NFS stuff is now dropped. You can still bring\nup the vagrant VM as before:\n\n```unknown\n$ sudo vagrant up\n```\n\nAnd then access Cockpit on https://localhost:9090\n\nHowever if you make changes to the stuff in the git repo, you need to\nrun an extra vagrant command before the running VM will pick it up:\n\n```unknown\n$ sudo vagrant rsync\n```\n\nSee [HACKING.md in the git](https://rawgit.com/cockpit-project/cockpit/master/HACKING.md)\nrepo for more details.\n\n\n### Try it out\n\nCockpit 0.95 is available now:\n\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.95)\n * [Fedora 23 and Fedora Rawhide](https://bodhi.fedoraproject.org/updates/cockpit-0.95-1.fc23)\n * [COPR for Fedora 22, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2016-03-24-cockpit-0.99.md",
    "content": "---\ntitle: Cockpit 0.99 Released\ndate: 2016-03-24 18:35\ntags: cockpit linux technical\nslug: cockpit-0.99\ncategory: release\nsummary: Cockpit releases every week. Here's highlights from 0.96 through 0.99\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). There's a new release every week. Here are the highlights from 0.96 through 0.99.\n\n### Kubernetes Cockpit Pod\n\nThe Kubernetes cluster admin interface is now deployable as a [Kubernetes](http://kubernetes.io) pod. Peter did a lot of work to make this happen. It's a good example of taking just one part Cockpit, containerizing it and running it in a completely different environment.\n\nYou can use the [commands listed in the documentation](https://cockpit-project.org/guide/latest/feature-kubernetes.html) to run the pod. Here's a demo:\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/OCbuzBe7Ems?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n\n### Locking down Cockpit with Content-Security-Policy\n\n[Content-Security-Policy](http://content-security-policy.com/) is like SELinux in your browser. You declare\nwhat your application is allowed to do, and the browser prevents other things from happening, like cross site scripting attacks.  Because the Cockpit javascript code has as much access to the system as the logged in user, Cockpit needs to make sure that attackers cannot sneak in javascript code into the browser session.\n\nIn the last few releases, a strict policy was applied to the network, Kubernetes, Docker, storage, and accounts parts of the interface, just a few more remaining before all of Cockpit is locked down in this way.\n\n\n### Debian packages\n\nCockpit has been testing each change and release against Debian during continuous integration for a while. Lars recently added installable Debian binary packages for each release. We're still looking for a [DD maintainer](https://wiki.debian.org/DebianDeveloper) to help take those tested packages and include them in Debian proper.\n\nSee the [documentation for how to use the Cockpit Debian packages](https://cockpit-project.org/running.html).\n\n\n### From the future\n\nThe ability to troubleshoot [SELinux](http://stopdisablingselinux.com/) in Cockpit is pretty exciting. Dominik has lots of the work in this area and it's nearly ready. Watch the video below. Once it's finished you'll be able to just click a button to resolve many (most?) SELinux issues found on a server.\n\n<iframe width=\"960\" height=\"720\" src=\"//youtube.com/embed/s6C29f8dSRQ?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\nGarret designed a UI for using Docker with an LVM pool as you would on [Atomic Host](http://www.projectatomic.io/download/). That is: A UI for [docker-storage-setup](https://github.com/projectatomic/docker-storage-setup). I'm looking forward to this in Cockpit. Sneak peak here:\n\n![Container Storage Designs](https://raw.githubusercontent.com/cockpit-project/cockpit-design/9bd7086a4a8492b72269c58272d063b3372116c3/containers/container-storage.png)\n\n### Try it out\n\nCockpit 0.99 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.95)\n * [Fedora 24](https://bodhi.fedoraproject.org/updates/cockpit-0.99-1.fc24)\n * [COPR for Fedora 23, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2016-04-01-cockpit-0.100.md",
    "content": "---\ntitle: Cockpit 0.100 Released\ndate: 2016-04-01 15:30\ntags: cockpit linux technical kubernetes\nslug: cockpit-0.100\ncategory: release\nsummary: Cockpit releases every week. Here's highlights from 0.100\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). There's a new release every week. Here are the highlights from this weeks 0.100 release. Even though 0.100 may seem to be a magical number ... it's really just the number after 0.99 :D\n\n### SELinux Troubleshooting\n\nCockpit can now help you troubleshoot [SELinux](http://stopdisablingselinux.com/) problems, and show you fixes for repairing the various issues. This is pretty amazing for system admins who really would rather be secure, but keep bumping into stuff that SELinux is blocking. There's more to come on both SELinux and troubleshooting in the future. Take a look at what landed in this release:\n\n<iframe width=\"960\" height=\"720\" src=\"//youtube.com/embed/eBGK6qSmnng?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Image Registry Interface\n\nThere's a new Image Registry user interface. It works with [Atomic Platform](http://www.projectatomic.io/) or [Openshift](https://www.openshift.org/) clusters. By default this shows up in the Cockpit \"Cluster\" admin dashboard.\n\nBut more importantly you can deploy this as a standalone image registry, complete with storage, authentication and an interface. See [www.projectatomic.io/registry](http://www.projectatomic.io/registry) for more info.\n\nHere's a quick demo:\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/VSOAASf1Usw?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Storage sliders and more\n\nMarius has been working on cleaning up the storage UI. One of the changes you'll notice is that you can now use a slider to choose a size for new volumes or file systems, and specify the size units you want to use:\n\n![Storage number slider](/images/cockpit-storage-slider.png)\n\nDebian builds now also include the Storage page.\n\n\n### From the future\n\nPeter worked on adding Cluster storage configuration to the Kubernetes admin dashboard. Basic support will be in the next release. Here's a screenshot:\n\n![Kubernetes persistent volume](/images/cockpit-kubernetes-storage.png)\n\n### Try it out\n\nCockpit 0.100 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.100)\n * [Fedora 24](https://bodhi.fedoraproject.org/updates/cockpit-0.100-1.fc24)\n * [COPR for Fedora 23, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2016-04-08-cockpit-0.101.md",
    "content": "---\ntitle: Cockpit does Kubernetes Data Volumes\ndate: 2016-04-08 12:35\ntags: cockpit linux technical kubernetes\nslug: cockpit-0.101\ncategory: release\nsummary: Cockpit releases every week. Here's highlights from 0.101\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). There's a new release every week. Here are the highlights from this weeks 0.101 release.\n\n### Kubernetes Volumes\n\nYou can now set up Kubernetes [persistent volume claims](http://kubernetes.io/docs/user-guide/persistent-volumes/) through the Cockpit cluster admin interface. These volumes are used to store persistent container data and possibly share them between containers. Each container pod declares the volumes it needs, and when deploying such an application admins configure the locations to store the data in those volumes.\n\nTake a look:\n\n<iframe width=\"960\" height=\"720\" src=\"//youtube.com/embed/rlWeO_MsJOA?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Show SELinux failure messages properly\n\nAs a follow up from last week, several bug fixes landed in the new SELinux troubleshooting support.\n\n### Try it out\n\nCockpit 0.101 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.101)\n * [Fedora 24](https://bodhi.fedoraproject.org/updates/cockpit-0.101-1.fc24)\n * [COPR for Fedora 23, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2016-04-14-cockpit-0.102.md",
    "content": "---\ntitle: Cockpit with Docker Restart Policy\ndate: 2016-04-14 13:33\ntags: cockpit linux technical kubernetes\nslug: cockpit-0.102\ncategory: release\nsummary: Cockpit releases every week. Here's highlights from 0.102\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). There's a new release every week. Here are the highlights from this weeks 0.102 release.\n\n### Docker Restart Policy\n\nWhen running a Docker container in Cockpit, you can now set the restart policy, so when the docker daemon restarts the containers will be restarted too. Justin Robertson contributed this feature. Take a look.\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/8YYHui-FQco?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Single Dialog for Creating Logical Volumes\n\nThe storage interface in Cockpit now has a single combined dialog when creating logical volumes.\nThis is a first tiny step towards advanced LVM2 features such as RAID layouts and caches. The dialog will get more fields and more interesting behavior as we implement more of the features offered by LVM2, such as the various RAID levels, as indicated by the hidden options for the \"Purpose\" and \"Layout\" fields.\n\n![Single dialog for logical volumes](/images/cockpit-logical-volume-one-dialog.png)\n\n### Storage interface now available on Debian\n\nThe storage interface in Cockpit has been enabled and built on Debian. The\n[storaged API](https://github.com/storaged-project/storaged/) is now available on Debian too.\n\n### Don't Distribute jshint due to License\n\nWe stopped distributing [jshint](http://jshint.com/) or requiring it as a build dependency due\nto its [controversial license](https://github.com/jshint/jshint/issues/1234).\n\n### Try it out\n\nCockpit 0.102 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.102)\n * [Fedora 24](https://bodhi.fedoraproject.org/updates/cockpit-0.102-1.fc24)\n * [COPR for Fedora 23, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2016-04-20-cockpit-0.103.md",
    "content": "---\ntitle: Cockpit 0.103\ndate: 2016-04-20 15:45\ntags: cockpit linux technical kubernetes\nslug: cockpit-0.103\ncategory: release\nsummary: Cockpit releases every week. Here's highlights from 0.102\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). There's a new release every week. Here are the highlights from this weeks 0.103 release.\n\n### Kubernetes connection configuration\n\nWhen a Kubernetes client wants to access the API of the cluster, it looks for a \"kubeconfig\" file to tell it how to find the cluster and how to authenticate when accessing the API. The usual location for this file is in the current user's home directory at the ```~/.kube/config``` file path. If that doesn't exist, then usually the cluster isn't available. This applies to both clients like the ```kubectl``` command as well as Cockpit's cluster dashboard.\n\nCockpit can now prompt for this information, and build this file for you. If it doesn't exist, then there's a helpful \"Troubleshoot\" button to help get this configuration in place.\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/WSh7wYhAXrA\" frameborder=\"0\" allowfullscreen></iframe>\n\n\n### Upload each Release to an Ubuntu PPA\n\nEach weekly release of Cockpit is now uploaded to an Ubuntu PPA. Here's how to make use of it:\n\n```unknown\nsudo add-apt-repository ppa:cockpit-project/cockpit\nsudo apt-get update\nsudo apt-get install cockpit\n```\n\n### Remove jQuery Usage from cockpit.js API\n\nAs part of stabilizing the internals of Cockpit, we removed jQuery usage from the cockpit.js file. [The javascript API itself](https://cockpit-project.org/guide/latest/api-base1.html) hasn't changed, but this change helps to help keep a stable API in the future.\n\n\n### Try it out\n\nCockpit 0.103 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.103)\n * [Fedora 24](https://bodhi.fedoraproject.org/updates/cockpit-0.103-1.fc24)\n * [COPR for Fedora 23, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2016-04-28-cockpit-0.104.md",
    "content": "---\ntitle: Cockpit 0.104\ndate: 2016-04-28 15:21\ntags: cockpit linux technical kubernetes\nslug: cockpit-0.104\ncategory: release\nsummary: Cockpit releases every week. Here's highlights from 0.104\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). There's a new release every week. Here are the highlights from this weeks 0.104 release.\n\n\n### Kubernetes iSCSI Volumes\n\nPeter added support for iSCSI Kubernetes Volumes in the Cockpit Cluster dashboard. When you\nhave container pods that need to store data somewhere, it's now real easy to configure use\nan iSCSI initiator. Take a look:\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/ytNGsIDYNSQ\" frameborder=\"0\" allowfullscreen></iframe>\n\n\n### Listing View Expansion\n\nAndreas, Dominik, and I worked on a better listing view pattern. In Cockpit we like to give\nadmins the option to expand data inline, and compare it between multiple entries on the same\npage. But after feedback from the [Patternfly folks](https://www.patternfly.org/) we added an\nexplicit expander to do this.\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/myXr_hnr5Jg\" frameborder=\"0\" allowfullscreen></iframe>\n\n\n### Tagging Docker Images in the Registry\n\nThe Atomic Registry and Openshift Registry support mirroring images from another image registry\nsuch as the Docker Hub. When the images are mirrored, they are copied and available in your\nown registry. Cockpit now has support for telling the registry which specific tags you'd like\nto mirror. And Aaron is adding support for various mirroring options as well.\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/MJzqob5AYI8\" frameborder=\"0\" allowfullscreen></iframe>\n\n\n### From the Future\n\nMarius has a working proof of concept that lets you configure where Docker stores container and image\ndata on its host. Take a look at the demo below. Marius adds disks to the container storage pool:\n\n<iframe width=\"960\" height=\"720\" src=\"//youtube.com/embed/9YiG4AY6HeY?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n\n### Try it out\n\nCockpit 0.104 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.104)\n * [Fedora 24](https://bodhi.fedoraproject.org/updates/cockpit-0.104-1.fc24)\n * [COPR for Fedora 23, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2016-05-04-cockpit-0.105.md",
    "content": "---\ntitle: Cockpit 0.105\ndate: 2016-05-04 14:27\ntags: cockpit linux technical kubernetes\nslug: cockpit-0.105\ncategory: release\nsummary: Cockpit releases every week. Here's highlights from 0.105\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). There's a new release every week. Here are the highlights from this weeks 0.105 release.\n\n\n### Strict Content-Security-Policy enforced everywhere\n\nAll of the Cockpit components now ship strict Content-Security-Policy. This is like\nSELinux in your browser, where you declare the kind of things the application is\npermitted to do and anything else is blocked.\n\nCockpit now only allows talking to and loading code from the server(s) that it's\nrunning on. Everything else is blocked, including inline scripts, evaluating\njavascript code, and using inline styles.\n\n\n### Timeout for Cockpit Authentication\n\nCockpit uses PAM for authenticating local users. It now expects that authentication\nprocess to complete within a certain timeout.\n\nMore details [in this document](https://github.com/cockpit-project/cockpit/blob/master/doc/authentication.md).\n\n\n### Cluster Users can be Added and Removed from Groups\n\nIn the Cluster admin interface, users can be added to groups and remove\nthem with a few clicks. Here's a short video:\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/TzvqNj9VywM\"frameborder=\"0\" allowfullscreen></iframe>\n\n### Registry Mirroring from Insecure Registries\n\nIn [the Registry user interface](http://www.projectatomic.io/registry/) there's now a\ncheckbox that allows you to choose whether the registry from which you're mirroring\ncontainer images is insecure or not.\n\n![Insecure Registry option](/images/cockpit-insecure-registry.png)\n\n### Deletion of Kubernetes Nodes\n\nIn the Cluster admin interface you can now delete Nodes from the cluster, and select\nwhich ones to delete. Andreas has also done design work to allow upgrading the\nnode operating system as well as cordoning nodes, which makes them unavailable for\nscheduling containers.\n\n![Deleting Nodes](/images/cockpit-delete-nodes.png)\n\n### Try it out\n\nCockpit 0.105 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.105)\n * [Fedora 24](https://bodhi.fedoraproject.org/updates/cockpit-0.105-1.fc24)\n * [COPR for Fedora 23, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2016-05-12-cockpit-0.106.md",
    "content": "---\ntitle: Cockpit 0.106\ndate: 2016-05-12 15:40\ntags: cockpit linux technical kubernetes\nslug: cockpit-0.106\ncategory: release\nsummary: Cockpit releases every week. Here's highlights from 0.106\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). There's a new release every week. Here are the highlights from this weeks 0.106 release.\n\n\n### Stable Cockpit Styles\n\nOne of the annoying things about CSS is that when you bring in stylesheets from\nmultiple projects, they can conflict. You have to choose a nomen-clature to\nnamespace your CSS, or nest it appropriately.\n\nWe're stabilizing the internals of Cockpit in the browser, so when folks write\nplugins, they can count on them working. To make that happen we had to namespace\nall our own Cockpit specific CSS classes. Most of the styling used in Cockpit\ncome from [Patternfly](https://www.patternfly.org/) and this change doesn't affect\nthose styles at all.\n\n[Documentation is on the wiki](https://github.com/cockpit-project/cockpit/wiki/Cockpit-CSS-Styling)\n\n\n### Container Image Layers\n\nDocker container image layers are now shown much more clearly. It should be clearer to tell\nwhich is the base layer, and how the others are layered on top:\n\n![Image Layers](/images/cockpit-image-layers.png)\n\n### Try it out\n\nCockpit 0.106 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.106)\n * [Fedora 24](https://bodhi.fedoraproject.org/updates/cockpit-0.106-1.fc24)\n * [COPR for Fedora 23, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2016-06-26-cockpit-0.111.md",
    "content": "---\ntitle: Cockpit 0.111\ndate: 2016-06-26 09:00\ntags: cockpit linux technical\nslug: cockpit-0.111\ncategory: release\nsummary: Cockpit releases every week. Here's highlights from 0.107 through 0.111.\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). There's a new release every week, although it's been a while since the release notes were posted. Here are the highlights from this weeks 0.107 through 0.111 releases.\n\n### SELinux enforcing policy\n\nYou can now temporarily disable SELinux enforcing mode from the SELinux troubleshooting\ndashboard. This is useful when diagnosing permission issues that you might think are\nSELinux related.\n\n![SELinux Enforcing](/images/cockpit-selinux-enforcing.png)\n\n### Stable Javascript API\n\nCockpit now has a [stable Javascript API](https://cockpit-project.org/guide/latest/api-base1.html)\nfor components or plugins to build off of. Various unstable portions were removed from the\nbase1 package in preparation for this. There's more work going on to help make it easy to build\nout of tree components or plugins.\n\n### GlusterFS in Kubernetes Dashboard\n\nThe [Kubernetes](http://kubernetes.io/) dashboard now lists [Gluster](http://gluster.org/)\nvolumes in the dashboard, lets you configure them for pods to use.\n\n![GlusterFS Persistent Volumes](/images/cockpit-glusterfs-volume.png)\n\n### Kubernetes pending Persistent Volume Claims\n\nThe [Kubernetes](http://kubernetes.io/) dashboard lists pods which have\noutstanding volume claims, and then allows you to fulfill those claims\nby creating appropriate persistent volumes.\n\n![Persistent Volume Claims](/images/cockpit-dashboard-claim.png)\n\n![Persistent Volume Claims](/images/cockpit-volume-claims.png)\n\n### From the Future\n\nMarius [has worked on](https://github.com/cockpit-project/cockpit/pull/4571) adding support\nfor Linux [network teaming](http://libteam.org/) to the Cockpit admin interface. Teaming\nis a better more coherent way of building a network bond.\n\n### Try it out\n\nCockpit 0.111 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.111)\n * [Fedora 24](https://bodhi.fedoraproject.org/updates/cockpit-0.111-1.fc24)\n * [COPR for Fedora 23, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2016-07-07-cockpit-0.113.md",
    "content": "---\ntitle: Cockpit 0.113\ndate: 2016-07-07 17:30\ntags: cockpit linux technical\nslug: cockpit-0.113\ncategory: release\nsummary: Cockpit releases every week. Here's highlights from 0.112 and 0.113.\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). There's a new release every week. Here are the highlights from this weeks 0.111 and 0.112 releases.\n\n### Display time information for systemd timer jobs\n\nHarish Anand a Google Summer of Code student working on Cockpit, and he's implementing\nsystemd timers. These are similar to cron jobs, and are a structured way of running\na command or other systemd unit at a specific time. Some of his initial work got merged,\nand you can see it in action here:\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/2mGAlpZWQUQ?rel=0\"\nframeborder=\"0\" allowfullscreen></iframe>\n\n### Hide Unmanaged Network Interfaces\n\nNetworkManager has the concept of marking certain network interfaces as \"unmanaged\".\nThis is done with a ```NM_CONTROLLED=\"no\"``` setting in a file placed in\n```/etc/sysconfig/network-scripts/```. Cockpit now respects the admins wishes and\nand hides such interfaces from its Network configuration.\n\nThe *On/Off* switch is also disabled appropriately for unknown interfaces.\n\n### Network bonds are created with Active/Backup\n\nWhen a new network bond is created the *Active/Backup* mode is used as\nthe default. This is a more common choice for admins, and makes sense\nto point people in this direction.\n\n![Bond Active/Backup](/images/cockpit-active-backup.png)\n\n### Added textual fields to container resource sliders\n\nUsers can now type actual amounts in memory megabytes, or CPU shares\nwhen starting a container, in addition to being able to use a slider.\n\n![Resource Slider Text](/images/cockpit-resource-sliders-text.png)\n\n### Disable tuned correctly when disabling performance profiles\n\nThe tuned service needs to be stopped and disabled when choosing the \"none\"\nperformance profile. The behavior now lines up with what users expect\nusing the ```tuned-adm``` command line tooling.\n\n### From the Future\n\nLars [is working on](https://github.com/cockpit-project/cockpit/pull/4633) making the\nterminal be resizable, so you're not limited to a small display when working on\nthe machine.\n\n### Try it out\n\nCockpit 0.113 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.113)\n * [Fedora 24](https://bodhi.fedoraproject.org/updates/cockpit-0.113-1.fc24)\n * [COPR for Fedora 23, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2016-07-12-cockpit-0.114.md",
    "content": "---\ntitle: Cockpit 0.114\ndate: 2016-07-12 13:51\ntags: cockpit linux technical\nslug: cockpit-0.114\ncategory: release\nsummary: Cockpit releases every week. Here's highlights from 0.114.\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). There's a new release every week. Here are the highlights from this weeks 0.114 release.\n\n### Test every change on CentOS\n\nCockpit runs all its tests suites against code before that code is merged, much less\nbecomes part of a release. This isn't just unit tests, but integration booting of\nRHEL, Debian, Fedora and Atomic machines.\n\nWe now added CentOS to that list. We now boot CentOS 7.x instances many hundreds of times\na day to test aspects of the system, and how Cockpit and a given pull request interact with it.\n\n### Show SSH host keys and machine ID\n\nThe main system info page now shows the\n[local machine ID](https://www.freedesktop.org/software/systemd/man/machine-id.html) for\neasy access.\n\nYou can also see the fingerprints of all the [SSH host keys](https://en.wikipedia.org/wiki/Secure_Shell).\nThese are the fingerprints that you would be expected to recognize and/or add to the\n```known_hosts``` file when accessing the machine over SSH.\n\n![SSH host keys](/images/cockpit-ssh-host-keys.png)\n\n### Allow changing the ethernet MTU\n\nYou can now change the ethernet\n[maximum transmission unit](https://en.wikipedia.org/wiki/Maximum_transmission_unit) in the\nnetwork configuration.\n\n### Show intelligent password error messages\n\nWhen choosing a password Cockpit validates the password using the ```pwscore``` tool.\nAppropriate and descriptive error messages are now shown when the validation fails:\n\n![pwscore message](/images/cockpit-pwscore-message.png)\n\n### Red Hat subscription registration options\n\nThe Red Hat subscriptions functionality has been enhanced. You can now specify an activation\nkey when registering the system. This key is generated in your organization in such a\nway that it uniquely identifies whan kind of software should be available on the system.\n\nYou can now also specify an organization when registering the system.\n\n### From the Future\n\nMarek [is working on](https://github.com/cockpit-project/cockpit/pull/4434) a new part of\nthe admin interface to list the virtual machines running on the current system. This is\nthe beginnings of a web accessible [virt-manager](https://virt-manager.org/) tool:\n\n![pwscore message](/images/cockpit-libvirt-message.png)\n\n### Try it out\n\nCockpit 0.114 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.114)\n * [Fedora 24](https://bodhi.fedoraproject.org/updates/cockpit-0.114-1.fc24)\n * [COPR for Fedora 23, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2016-08-11-cockpit-0.117.md",
    "content": "---\ntitle: Cockpit 0.117\ndate: 2016-08-11 12:36\ntags: cockpit linux technical\nslug: cockpit-0.117\ncategory: release\nsummary: Cockpit releases every week. Here's highlights from 0.115, 0.116 and 0.117.\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). There's a new release almost every week. Here are the highlights from this the 0.115, 0.116 and 0.117 releases.\n\n### Configure volumes and environment for a Docker container\n\nVanlos Wang implemented support for configuring volumes and environment\nvariables when running a container in the Cockpit UI. This allows you\nsee what environment variables and volumes an image is pre-configured\nto have. It then allows the user to define additional environment variables\nand volumes for the new container, and then commit those changes to a\nnew image if desired.\n\nTake a look:\n\n<iframe width=\"1280\" height=\"720\" src=\"//youtube.com/embed/l9E78Uevg00\"\nframeborder=\"0\" allowfullscreen></iframe>\n\n\n### Setup container and image storage\n\nMarius worked with Dan Walsh and and others to implement a UI for configuring\nthe Docker container and image storage pool. It's now easy to add additional\ndisks or storage to that pool, or reset it to a clean state.\n\nOn some operating systems like [Atomic Host](http://www.projectatomic.io/download/),\nthis storage pool is present by default,\nand elsewhere this container storage pool can be set up.\n\nRelatedly on the command line, checkout the new\n[```atomic storage```](https://raw.githubusercontent.com/projectatomic/atomic/master/docs/atomic-storage.1.md)\nsub-command which does the same configuration tasks, that previously had to be configured\nwith arcane configuration files.\n\n<iframe width=\"1280\" height=\"720\" src=\"//youtube.com/embed/l9fmMa5WJMk?rel=0\"\nframeborder=\"0\" allowfullscreen></iframe>\n\n\n### Support for Network Teaming\n\nMarius also added support for\n[configuring network teaming](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/Networking_Guide/ch-Configure_Network_Teaming.html)\nto Cockpit. Network teams are\nsimilar to network bonds, in that they combine two network interfaces into\none, and involve failover or load balancing modes. But teams have more robust\nterminology and implementation.\n\nSince teams are a server side feature, this will replace the functionality for\ndefining teams in Linux Desktop control center applications.\n\nSupport for configuring bonds in Cockpit will remain for the time being until\nthe team support can be relied upon to completely replace that functionality.\nBoth NetworkManager and Cockpit are involved in this.\n\nHere's a video demoing the changes:\n\n<iframe width=\"960\" height=\"720\" src=\"//youtube.com/embed/-sob1W33Xus?rel=0\"\nframeborder=\"0\" allowfullscreen></iframe>\n\n\n### Pulling images without authentication from the Openshift Registry\n\nThe Openshift image registry now supports pulling images without first\nlogging in. It can be configured to allow this on a per-project basis.\nThis allows images to be shared from the registry with a broader audience\nof developers or image consumers, such as scripts.\n\nAaron Weitekamp worked on adding support the Registry console to\nconfigure projects to allow pulling images without authentication.\nHere's a video of those changes:\n\n<iframe width=\"1280\" height=\"720\" src=\"//youtube.com/embed/fpsvtq5hENk\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Don't allow formatting extended partitions\n\nCockpit no longer erroneously allows formatting certain partitions, such as\nextended partitions containing other logical partitions.\n\n\n### Try it out\n\nCockpit 0.117 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/0.117)\n * [Fedora 24](https://bodhi.fedoraproject.org/updates/cockpit-0.117-1.fc24)\n * [COPR for Fedora 23, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n\n"
  },
  {
    "path": "_posts/2016-09-08-cockpit-118.md",
    "content": "---\ntitle: Cockpit 118\ndate: 2016-09-08 14:50\ntags: cockpit linux technical\nslug: cockpit-118\ncategory: release\nsummary: Cockpit releases regularly. Here's highlights from 118\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). There's usually\na release every week, but this time around we were delinquent and it's been nearly a month.\n\nYou'll notice that we've dropped the ```0.x``` from the beginning of the\nversion numbers. This underscores the fact that Cockpit is stable. We've been\nregularly releasing functionally stable releases for most of the last year.\n\nAnd over the last few months we've worked hard on identifying stable javascript\nAPIs and protocols for various Cockpit components to consume. We'll be itemizing\nthese stability guarantees in the documentation shortly.\n\n### Timer jobs in systemd\n\nHarish did great work during Google Summer of Code to add support for\n[systemd timers](https://www.freedesktop.org/software/systemd/man/systemd.timer.html).\nTimers let users schedule tasks similar to cron jobs. Timers are now listed,\nand dialogs for defining jobs and their recurring patterns are now included\nin Cockpit.\n\nHarish [detailed his work in a blog post](https://medium.com/@harishanand95/gsoc-creating-timers-in-cockpit-f4034c79df51#.wdq8gtdxc).\n\n![Timers](/images/cockpit-timers.png)\n\n### Two factor auth on login screen\n\nPeter pulled off a major change to have full PAM conversations supported\non the Cockpit login screen. This means you can use two factor\nauthentication dongles or Yubikeys in your login workflow in Cockpit.\n\nIn addition, for the next release Stef worked on allowing the user to\nchange expired passwords while logging in, similar to how they would\non the console.\n\nTake a look:\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/gXsOt6zgBs4?rel=0\"\nframeborder=\"0\" allowfullscreen></iframe>\n\n### Use Webpack to build the Cockpit interface\n\nMost of Cockpit is written in javascript and runs in the browser. This\ncode is now built with [Webpack](https://webpack.github.io/). It's bundled\ninto single page application bundles per Cockpit component. Among\nother things, this makes hacking on Cockpit much easier.\n\nThe [documentation has been updated](https://github.com/cockpit-project/cockpit/blob/master/HACKING.md)\nto show what you need to do to make a change to Cockpit either with\nVagrant or on your local machine.\n\n### SSH key loading and Docker resources work on Debian\n\nThe container resource usage graphs and resource limit dialogs now\nwork properly on Debian. Stef adapted the code to account for the different\nCGroup layout than Docker uses on Debian.\n\nIn addition the SSH key listing code now works on Debian.\n\n### Configure Cockpit URLs with an HTTP prefix\n\nThe HTTP URLs that Cockpit uses can now have a (mostly) arbitrary prefix\nin their path. This is useful in scenarios where Cockpit is proxied by\nanother application or management console. Use the ```UrlRoot``` option\n[in cockpit.conf](https://cockpit-project.org/guide/latest/cockpit.conf.5.html).\n\n### Components can require a minimum Cockpit version\n\nCockpit is built from various components that are independently installable\nand composable. Various components provide network configuration, or storage,\nor container functionality.\n\nThese components can now indicate which part of the base javascript and base\n```cockpit-bridge``` they require in order to function. This is\n[configured in the package manifest](https://cockpit-project.org/guide/latest/packages.html#package-manifest).\n\n![Incompatible Cockpit](/images/cockpit-incompatible.png)\n\n### Try it out\n\nCockpit 118 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/118)\n * [Fedora 25](https://bodhi.fedoraproject.org/updates/cockpit-118-1.fc25)\n * [COPR for Fedora 24, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n"
  },
  {
    "path": "_posts/2016-10-21-cockpit-120.md",
    "content": "---\ntitle: Cockpit 120\ndate: 2016-10-21 13:22\ntags: cockpit linux technical\nslug: cockpit-120\ncategory: release\nsummary: Cockpit releases regularly. Here's highlights from 119 and 120\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release\nregularly. Here are the release notes from versions 119 and 120.\n\nYou'll notice that we've dropped the ```0.x``` from the beginning of the\nversion numbers. This underscores the fact that Cockpit is stable. We've been\nregularly releasing functionally stable releases for most of the last year.\n\n### Expandable and Filterable Containers and Images\n\nLars reworked the Containers section of Cockpit. The various images and\ncontainers are not expandable inline, and it's also easy to find a specific\nimage and container by using the filter bar to search for it.\n\nTake a look:\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/-huY6q7kcmU\" frameborder=\"0\" allowfullscreen></iframe>\n\n### VM Configuration and Monitoring\n\nMarek worked on a new interface in Cockpit for configuring and monitoring\nvirtual machines running on the current system. This has the ability to\ngrow into something like the desktop ```virt-manager``` tool.\n\nIt looks something like this:\n\n![Virtual Machines](/images/vms.png)\n\n### Unmanaged Network Devices\n\nCockpit now shows unmanaged network devices in its listing. You can't configure\nthem or do much with them, but their presence is acknowledged. This should make\ntroubleshooting non-standard configurations easier.\n\n### Sidebar for Physical Volumes in a Volume Group\n\nMarius added a sidebar that shows up on LVM groups or volumes, that shows\nwhich physical devices are involved.\n\nHere's an example:\n\n![SSH subprocesses](/images/cockpit-pv-sidebar.png)\n\n### SSH connections are run in a separate process\n\nWhen Cockpit connects to an additional server it uses SSH, much like\nAnsible or other tools. We now launch a separate ```cockpit-ssh``` process\nfor each outgoing connection to another server.\n\nThis lets us isolate the involved code much better, providing security\nbenefits. But it also makes it possible to insert additional logic when\nembedding Cockpit. It's possible to put in shims to lookup keys, single-sign-on\ntokens or keytabs, and so on.\n\n![SSH subprocesses](/images/cockpit-ssh.png)\n\n### Only connect to remote machines already known to Cockpit\n\nWhen connecting to additional machines via SSH, Cockpit now refuses to\nconnect to machines it doesn't have a host key for. This tightens up\nsecurity and prevents certain reflection attacks.\n\n### Fix bugs preventing Logs page from working in Firefox 49\n\nThe Logs section of Cockpit failed to function on Firefox 49. This\nversion includes a fix for that.\n\n### Add tooltip describing group name in Roles list\n\nWhen configuring local user accounts, one can assign various roles such\nas 'Server Administrator' to the account. Cockpit now displays the Unix\nuser group that is involved in the role.\n\n![User Unix Group](/images/cockpit-unix-group.png)\n\n### From the future\n\nMarius added support for NetworkManager checkpoints. This means that\nwhile configuring network interfaces, if a change would cause Cockpit\nto disconnect, then Cockpit can revert the change and retain connectivity\nto the system.\n\nThis is similar to how a Linux Desktop asks you to click in a dialog\nif you accept the new screen configuration. Except in the networking\ncase we can test the connectivity automatically.\n\n### Try it out\n\nCockpit 120 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/120)\n * [Fedora 25](https://bodhi.fedoraproject.org/updates/cockpit-120-1.fc25)\n * [COPR for Fedora, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n"
  },
  {
    "path": "_posts/2016-10-28-cockpit-121.md",
    "content": "---\ntitle: Cockpit 121\ndate: 2016-10-28 18:06\ntags: cockpit linux technical\nslug: cockpit-121\ncategory: release\nsummary: Cockpit releases regularly. Network Checkpoints and other highlights from\n  version 121\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release\nregularly. Here are the release notes from version 121\n\nYou'll notice that we've dropped the ```0.x``` from the beginning of the\nversion numbers. This underscores the fact that Cockpit is stable. We've been\nregularly releasing functionally stable releases for most of the last year.\n\n### Network Configuration Rollback\n\nNetworkManager now has support in its API for detecting whether a network\nconfiguration change broke connectivity to the system. Marius did work\nso that Cockpit can detect this and have NetworkManager rollback the\nchanges that would have caused a remote admin to be disconnected from\nthe system.\n\nThis is similar to how a Linux desktop asks you to click in a dialog\nif you accept the new display configuration. Except in the networking\ncase we can test the connectivity automatically.\n\nCheck it out:\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/fNIaDl5UR4Q?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n\n### Debian Branding\n\nCockpit now shows proper branding when running on Debian, and uses the\nlogo installed on the system on its login screen.\n\n![Virtual Machines](/images/debian-branding.png)\n\n### Fix Kerberos single sign on Debian and Ubuntu\n\nStef fixed Kerberos single sign on Debian and Ubuntu. More changes are\ncoming in the next release including support for use with\n[gssproxy](https://fedoraproject.org/wiki/Features/gss-proxy) and expanding\nsupport for non-Kerberos GSSAPI authentication mechanisms.\n\n\n### Debugging info for Javascript and CSS\n\nCockpit now ships proper Javascript and CSS debugging \"map\" files in its\ncockpit-debuginfo packages. These make it easier to troubleshoot issues\nand develop code that runs in Cockpit.\n\n### From the future\n\nPeter is adding support for specifying an alternate server to connect\nto on the login screen.\n\nThis completes the story of the \"bastion host\" which is accessible via\na web browser, in effect letting you connect via the Web Browser from\nthe login screen to other machines which only have SSH access available.\nWhen using a bastion setup like this you only need a single trusted\nTLS certificate and the remaining trust is ensured by SSH known host keys.\n\nThis feature will be used to implement click-through access to configure a host\nin projects such as ManageIQ or RHEV.\n\n### Try it out\n\nCockpit 121 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/121)\n * [Fedora 25](https://bodhi.fedoraproject.org/updates/cockpit-121-1.fc25)\n * [COPR for Fedora, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n"
  },
  {
    "path": "_posts/2016-11-03-cockpit-122.md",
    "content": "---\ntitle: Cockpit 122\ndate: 2016-11-03 20:31\ntags: cockpit linux technical\nslug: cockpit-122\ncategory: release\nsummary: About bastion hosts and other highlights from version 122\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release\nregularly. Here are the release notes from version 122\n\n### Logging into a system via a Bastion Host\n\nOn the Cockpit login screen you can now choose an alternate host to connect\nto. Cockpit with use SSH to authenticate you against that host, and display\nthe admin interface for that host.\n\nAlthough browsers cannot use SSH directly to connect to machines or\nauthenticate against them, Cockpit can make this happen. Only one host\nneeds to have Cockpit listen on port 9090 available to browsers over TLS,\nand other hosts can only have SSH accessible on the usual port 22.\n\nHere's an example:\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/yc64DUydciI\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Works with UDisks in addition to storaged\n\n[storaged](https://github.com/storaged-project/storaged)\nis an actively maintained API for configuring storage on a Linux system.\nIt is a fork of the older\n[UDisks](https://www.freedesktop.org/wiki/Software/udisks/). storaged\nhas additional functionality, like LVM, iSCSI and Btrfs and a large number\nof stability fixes.\n\nHowever some systems like older RHEL or Ubuntu don't yet have storaged.\nCockpit can now also use the older UDisks to configure storage on a system.\nA large number of features are disabled, but basic functionality is present.\n\n\n### Explicitly specify javascript dependency versions\n\nCockpit's bundles various javascript dependencies in its admin interfaces,\nsuch as\n[Patternfly](http://www.patternfly.org) or\n[React](https://reactjs.org/). In order to help packagers\nwe've now explicitly specified the versions of those dependencies. And\nduring development we pull them in using the standard\n[Bower](https://bower.io/) registry.\n\nYou can see [those versions here](https://raw.githubusercontent.com/cockpit-project/cockpit/master/bower.json).\n\n### From the future\n\nLars has worked on functionality to show the OpenSCAP security scan results\nfor containers. This uses the usual ```atomic scan``` functionality that\nyou see on Atomic Host.\n\n![Virtual Machines](/images/image-scanning.png)\n\n### Try it out\n\nCockpit 122 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/122)\n * [Fedora 25](https://bodhi.fedoraproject.org/updates/cockpit-122-1.fc25)\n * [COPR for Fedora, CentOS and RHEL](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/)\n"
  },
  {
    "path": "_posts/2016-11-25-cockpit-125.md",
    "content": "---\ntitle: Cockpit 125\nauthor: stef\ndate: 2016-11-25 09:14\ntags: cockpit linux\nslug: cockpit-125\ncategory: release\nsummary: Cockpit is properly translatable and displays OSTree signatures.\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release\nregularly. Here are the release notes from version 123, 124 and 125.\n\n### Cockpit is now properly translatable\n\nCockpit is now properly translatable. It was a big task to extract\nall the translatable strings and make translations work consistently\nbetween the browser and installed tools like the bridge.\n\nWe now start also run the login user session with a proper locale and\n```LANG``` environment variables.\n\nYou can help\n[translate cockpit in Zanata](https://fedora.zanata.org/iteration/view/cockpit/master)\nor if you find text in the frontend that isn't translatable, then\nplease do report it.\n\n![Display Language Dialog](/images/translatable.png)\n\n### Display OSTree signatures\n\nPeter implement displaying\n[OSTree tree](http://www.projectatomic.io/docs/os-updates/) signatures. You\ncan tell where a certain update tree came from and who signed it.\n\n![Display Language Dialog](/images/ostree-signatures.png)\n\n### New expandable views for storage partitions\n\nMarius implemented expandable views in the *Storage* pages. These let\nyou dive into the details of a particular partition without having\nto navigate away from the page describing where it lives.\n\n![Expandable Logical Volumes](/images/storage-listing.png)\n\n### Other storage fixes\n\nMarius did work to fix many other storage related bugs. In particular\nCockpit now deals properly with passphrases stored for LUKS encrypted\ndevices, and also no longer offers to format read-only block devices.\n\n### Full testing on RHEL 7.3, Ubuntu 16.04 and Debian 8 Jessie\n\nThe Cockpit project started testing on Cockpit on RHEL 7.3, Ubuntu 16.04\nand Debian 8 Jessie along with the operating systems we tested with earlier.\nThese will be part of our usual continuous integration, where we boot\nthousands or tens of thousands of instances per day to test code changes\nand contributions.\n\nMarius fixed many bugs we found, and filed operating system bugs in\nthe issue trackers for those operating systems.\n\nYou can see the [which operating systems](https://cockpit-project.org/running.html)\nwe test Cockpit on. There's no Debian Jessie repository yet, but hopefully\nwe can have that ready as time permits.\n\n### System shutdown can be scheduled by date\n\nFridolin did work a long time ago, so that users could select a specific\ndate and time to schedule a shutdown or reboot of the system. Stef\nfinished that work added tests and it's now in Cockpit.\n\n![Expandable Logical Volumes](/images/shutdown-date.png)\n\n### Properly terminate user sessions on the Accounts page\n\nThe *Accounts* page now properly terminates user sessions when the\n*Terminate Session* button is clicked. We use the correct systemd\n[loginctl](https://www.freedesktop.org/software/systemd/man/loginctl.html)\ncommands.\n\n### Try it out\n\nCockpit 125 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/125)\n * [Fedora 25](https://bodhi.fedoraproject.org/updates/cockpit-125-1.fc25)\n"
  },
  {
    "path": "_posts/2017-01-09-cockpit-127.md",
    "content": "---\ntitle: Cockpit 126 and 127\nauthor: stef\ndate: 2017-01-09 09:44\ntags: cockpit linux\nslug: cockpit-127\ncategory: release\nsummary: Cockpit shows container image security scan info.\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release\nregularly. Here are the release notes from version 126 and 127.\n\n### Show security scan information about container images\n\nLars did work to show security scan information about container images. The\ndisplayed scans happen via the\n[atomic scan](https://developers.redhat.com/blog/2016/05/02/introducing-atomic-scan-container-vulnerability-detection/)\ntools and the data comes from the [OpenSCAP](https://www.open-scap.org/) system.\nTake a look at the video below.\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/zANUkEmfaAk\"\nframeborder=\"0\" allowfullscreen></iframe>\n\n### Choose whether password is cached and reused on the login screen\n\nThe typical workflow for performing privileged tasks on a Linux system is to\nlog in as a non-root user and then use [sudo](https://www.sudo.ws/) or\n[Polkit](https://en.wikipedia.org/wiki/Polkit) to escalate privileges.\n\nStef did work to make Cockpit's privilege escalation reflect this properly.\nCockpit now has an option on the login screen to\n*Reuse my password for privileged tasks*. Checking this option automatically\nperforms reuses the login password as necessary to escalate privileges. If\nyou leave this box unchecked then Cockpit will behave exactly as a normal\nuser login without special privileges.\n\nIn the future we'll have a way to enable this option once logged in, and\nretype your password inside of the logged in session.\n\nHere's a video which shows how this works:\n\n<iframe width=\"853\" height=\"480\" src=\"//youtube.com/embed/TW6UsPbNkV4\"\nframeborder=\"0\" allowfullscreen></iframe>\n\n### The remotectl command can now combine certificate and key files\n\nPeter did work to make it easier to use TLS certificate and key files with\nCockpit for port 9090. Normally the server certificate(s) and key need to be\ncombined into a single file and placed into the ```/etc/cockpit/ws-certs.d```\ndirectory. The ```remotectl``` command that comes with Cockpit can now be\nused to build such a combined file:\n\n```unknown\nremotectl certificate server.pem chain.pem key.pem\n```\n\nDue to this, when Cockpit is deployed as an Openshift Pod it can use certificates\nprovided by Openshift.\n\n### Cockpit respects /etc/shells\n\nMartin fixed Cockpit so it only allows the user to log in if the user has a\nvalid shell listed in ```/etc/shells```. In addition bugs on Ubuntu and Debian\nhave been fixed where users were created without valid shells.\n\n### Allow renaming of active devices in networking interface\n\nYou can now rename network devices like bonds or bridges while they're active.\nThe change will apply immediately and without any interruption in service.\n\n### Rename cockpit-shell to cockpit-system\n\nThe ```cockpit-shell``` subpackage has been renamed to ```cockpit-system``` to\nbetter reflect its focus: configuring and troubleshooting the local system.\n\n### Kerberos authentication now work even if gss-proxy is in use\n\nSometimes Kerberos (or GSSAPI) single-sign-on authentication requires multiple\nround trips to the server. Cockpit now supports this properly, and the end result\nis that SSO works even when fancy things like\n[GSS-Proxy](https://fedorahosted.org/gss-proxy/) are in use.\n\n### Try it out\n\nCockpit 127 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/127)\n * [Fedora 25](https://bodhi.fedoraproject.org/updates/cockpit-127-1.fc25)\n"
  },
  {
    "path": "_posts/2017-01-19-cockpit-129.md",
    "content": "---\ntitle: Cockpit 128 and 129\nauthor: dperpeet\ndate: 2017-01-19 09:00\ntags: cockpit linux\nslug: cockpit-129\ncategory: release\nsummary: Cockpit supports rebasing on Atomic Host with OSTree.\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release\nregularly. Here are the release notes from version 128 and 129.\n\n### Manage remotes and rebasing in OSTree\n\nWhen working with OSTrees on operating systems like [Atomic Host](http://www.projectatomic.io/docs/os-updates/)\nthere will often be multiple branches to choose from. For example there may be a beta version of the operating system.\nThanks to Peter's work, Cockpit can now switch between branches and view and activate OSTrees from those branches.\nAlso, Cockpit supports managing multiple remotes and viewing their branches. Remotes are a way of describing\nwhere OSTree should pull updates from. Take a look at the video below for a demo.\n\n<iframe width=\"560\" height=\"315\" src=\"//youtube.com/embed/dF8M3xq9FcI\" frameborder=\"0\" allowfullscreen></iframe>\n\n### The subpackage cockpit-dashboard has been split out\n\nThe new ```cockpit-dashboard``` subpackage contains the dashboard itself and\nthe ```cockpit-ssh``` process. Eventually this paves the way for more flexibility\nregarding authentication processes, but for now ```cockpit-ws``` unconditionally\ndepends on ```cockpit-dashboard```, and also requires the identical versions.\nNothing changes for those who install the ```cockpit``` package. But this allows more\nflexibility when using Cockpit for specific use cases.\n\n### Issues upgrading Cockpit on Debian and Fedora have been fixed\n\nOur packaging changes in recent versions broke upgrading Cockpit on Debian and Fedora.\nThis is fixed now and updates should work properly once again.\n\n### On Atomic, sosreport works again\n\nA bug that prevented the diagnostic tool sosreport from working on Atomic systems was fixed.\nGenerating and accessing these diagnostic reports can be very helpful when diagnosing or\nreporting an issue on the system.\n\n### Optionally disable the dependency on libssh\n\nWhen configuring Cockpit, the option ```disable-ssh``` disables building ```cockpit-ssh``` and removes the\ndependency on ```libssh```. This is useful when building on an operating system where ```libssh``` is not available.\n\n### Try it out\n\nCockpit 129 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/129)\n * [Fedora 25](https://bodhi.fedoraproject.org/updates/cockpit-129-1.fc25)\n"
  },
  {
    "path": "_posts/2017-02-24-cockpit-132.md",
    "content": "---\ntitle: Cockpit 130, 131 and 132\nauthor: dperpeet\ndate: 2017-02-24 09:00\ntags: cockpit linux\nslug: cockpit-132\ncategory: release\nsummary: Cockpit supports configuring kdump and MAC addresses\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release\nregularly. Here are the release notes from version 130, 131 and 132.\n\n### Kernel dump configuration support added\n\nKernel crash dump configuration is now possible in Cockpit: view and toggle the status of the kdump service,\nwith hints how to enable if the kernel boot parameters need to be changed. Cockpit shows the amount of reserved\nmemory and setting a path for dumping the kernel on the local filesystem, with a toggle for compressing the crash dumps.\nTake a look at the video below for a demo.\n\n<iframe width=\"560\" height=\"315\" src=\"//youtube.com/embed/VXhuqPR2K5c?ecver=1\" frameborder=\"0\" allowfullscreen></iframe>\n\n### MAC addresses for ethernet adapters and bonds can be modified\n\nOn the Networking page, MAC addresses for ethernet adapters can now be clicked to edit them, starting with\nNetworkManager version 1.4. For bonds, the MAC addresses are shown and can be edited starting with NetworkManager\nversion 1.6. Take a look at the video below for a demo.\n\n<iframe width=\"560\" height=\"315\" src=\"//youtube.com/embed/JIHQmFHOrO4?ecver=1\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Show session virtual Machines on the machines page\n\nLibvirt differentiates between system virtual machines and session ones, which are tied to the user. In Cockpit\nall the virtual machines accessible to the logged in user, system and session, are now shown in a combined list.\n\n![Session virtual machines](/images/cockpit-machines-session.png)\n\n### SELinux functionality is now available without setroubleshootd\n\nThe SELinux page in Cockpit can do more than just troubleshoot. It was therefore renamed to ```SELinux``` and\nthe functionality of toggling between enforcing/permissive mode is now also available even if ```setroubleshoot-server```\nisn't installed. This was cause for unexpected behavior on Atomic Host systems without ```setroubleshoot-server```\nwhere it's non-trivial and often undesired to add that package.\n\n![SELinux without troubleshooting](/images/cockpit-selinux-disabled.png)\n\n### Try it out\n\nCockpit 132 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/132)\n * [Fedora 25](https://bodhi.fedoraproject.org/updates/cockpit-132-1.fc25)\n\nUse the packages to install this version of Cockpit. When installing from the tarball, remove\n/etc/systemd/system/cockpit.service.d/fatal.conf manually afterwards to prevent Cockpit from exiting in rare cases.\n"
  },
  {
    "path": "_posts/2017-03-02-cockpit-133.md",
    "content": "---\ntitle: Cockpit 133\nauthor: dperpeet\ndate: 2017-03-02 09:00\ntags: cockpit linux\nslug: cockpit-133\ncategory: release\nsummary: Cockpit supports alternate bridges via packages\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release\nregularly. Here are the release notes from version 133.\n\n### Remotely managed machines are now configured in /etc/cockpit/machines.d\n\nCockpit plugins, other packages, admins, VM management software, or config management systems like\nAnsible/puppet/cloud-init might want to pre-configure machines for cockpit. Previously this information\nwas stored in ```/var/lib/cockpit/machines.json```, but now that information is stored in individual json\nfiles in ```/etc/cockpit/machines.d```. Existing ```machines.json``` files are migrated automatically to the new\nformat. Check out the documentation below for more information on the format and use.\n\n[Multiple machines documentation](https://cockpit-project.org/guide/133/feature-machines.html)\n\n### Packages can register additional bridges\n\nOn the server side the ```cockpit-bridge``` connects to various system APIs. There are additional bridges for specific\ntasks that the main ```cockpit-bridge``` cannot handle, such as tasks that should be carried out with privilege\nescalation. These additional bridges can be registered in the ```bridges``` section of a package's ```manifest.json```\nfile. Check out the documentation below for more information on the format and use.\n\n[Additional bridges](https://cockpit-project.org/guide/133/packages.html#package-bridges)\n\n### Split translations into individual packages\n\nBehind the scenes there's been a lot of work on making translations work more smoothly and future-proof.\nAs part of this the translations have been split into the individual packages, which also means they can be updated\nper package in the future. Check out the Zanata link below, it's very easy to contribute translations to Cockpit.\nAt this time our top 3 translations (>90%) are Polish (pl), Ukrainian (uk) and Chinese (zh-CN). Every bit of help\nhere is greatly appreciated and a big thank you to our contributors!\n\n[Cockpit translations](https://fedora.zanata.org/project/view/cockpit?dswid=-8859)\n\n### Try it out\n\nCockpit 133 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/133)\n * [Fedora 25](https://bodhi.fedoraproject.org/updates/cockpit-133-1.fc25)\n"
  },
  {
    "path": "_posts/2017-03-09-cockpit-134.md",
    "content": "---\ntitle: Cockpit 134\nauthor: dperpeet\ndate: 2017-03-09 18:00\ntags: cockpit linux\nslug: cockpit-134\ncategory: release\nsummary: Cockpit is now fully translatable\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 134.\n\n### Login page is now translatable\n\nThe majority of Cockpit has long been translatable. Since the login page is a bit of a special case, it required some\nspecial attention to make that also play well with the language display settings. Take a look at the video below for a demo.\nCheck out the Zanata link below, it's very easy to contribute translations to Cockpit.\nAt this time our top 3 translations (>90%) are Polish (pl), Ukrainian (uk) and Chinese (zh-CN). Every bit of help\nhere is greatly appreciated and a big thank you to our contributors!\n\n[Cockpit translations](https://fedora.zanata.org/project/view/cockpit?dswid=-8859)\n\n<iframe width=\"560\" height=\"315\" src=\"//youtube.com/embed/_4jQ6NYSL-c?ecver=1\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Show message of the day on the System page\n\nCockpit now supports one more feature it was previously missing compared to the command line login: the ```System```\npage now shows the current message of the day (```/etc/motd```). When dismissed by clicking on the ```X``` close button,\nthe message is hidden until it changes.\n\n![Message of the day](/images/cockpit-motd.png)\n\n### Expose fewer system service actions\n\nCockpit previously exposed systemd unit actions such as ```Reload or Try Restart``` which are primarily intended for\nscripts. The dropdown list now only shows actions which are useful for interactive human usage: ```Start```, ```Stop```,\n```Restart``` and ```Reload```.\n\n![Service actions](/images/cockpit-service-actions.png)\n\n### Try it out\n\nCockpit 134 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/134)\n * [Fedora 25](https://bodhi.fedoraproject.org/updates/cockpit-134-1.fc25)\n"
  },
  {
    "path": "_posts/2017-03-15-cockpit-135.md",
    "content": "---\ntitle: Cockpit 135\nauthor: dperpeet\ndate: 2017-03-15 22:00\ntags: cockpit linux\nslug: cockpit-135\ncategory: release\nsummary: Cockpit with authorization and authentication changes\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 135.\n\n### Redesigned sidebar navigation\n\nThe existing page menu took some getting used to for some use cases. It's now easier to use when connected to multiple\nhosts and provides the basis for future improvements that will reduce or remove the horizontal menu entries. On systems\nwhere the top navigation bar doesn't have any useful information, such as when there is no Dashboard, the top\nnavigation bar is removed entirely. Check out the screenshot below for a peek at the new sidebar design.\n\n![Sidebar navigation](/images/cockpit-page-menu.png)\n\n### Indicator in top bar shows privilege escalation\n\nOn the login page a user can allow Cockpit to use the password for privileged tasks. A new indicator in the top bar\nshows an ```unlocked``` state when these privileges are available and a ```locked``` state if they aren't. The user\ncan click on the indicator in the ```unlocked``` state to drop privileges for the rest of the session. In some cases\nprivileges cannot be dropped - among others for root and no-password sudo users - and the indicator will disappear.\nCheck out the video below to see this in action.\n\n<iframe width=\"560\" height=\"315\" src=\"//youtube.com/embed/3eZSYW89zMI?ecver=1\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Disks are now shown for virtual machines\n\nThe expanded information for entries on the ```Virtual Machines``` page now contains information on a machine's disks,\nsuch as the device, read only state and for disk images the local file path. Information on disk capacity is only\navailable with more recent versions of libvirt. Check out the screenshot below to see how this looks.\n\n![Virtual machine disks](/images/cockpit-vm-disks.png)\n\n### New developer tool can close active Cockpit pages\n\nOnce pages in Cockpit, such as ```Networking``` or ```System```, are opened they usually stay open in the background,\neven if they aren't visible. This is important on most pages to ensure the code can continue interacting with the\nsystem in the background, user input isn't lost, and the page doesn't have to be reloaded when the user returns to it.\nFor the cases when a user wishes to actually close the page there is a new entry next to ```Display Language``` in\nthe user drop down menu, named ```Active Pages```. It only becomes visible when the ```ALT``` key is pressed while\nclicking on the menu dropdown. On some drag enabled browsers it doesn't work to just use ```ALT```, but any combination\ninvolving ```ALT```, such as ```CTRL+ALT```, also works. Check out the screenshot below for a peek.\n\n![Active Pages](/images/cockpit-active-pages.png)\n\n### SSH connections established within the user session\n\nWhen one Cockpit instance connects to other machines it does so via SSH. Previously\nthese connections were launched from cockpit-ws, the process listening on the network.\n\nAs part of making Cockpit mirror standard Linux practices better, SSH connections are\nnow made from within the logged in user session, launched from the cockpit-bridge\nprocess. This allows Cockpit to use credentials from the logged in user session while\nestablishing those SSH connections, such as kerberos tickets, the ssh-agent or private keys.\n\n### Try it out\n\nCockpit 135 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/135)\n * [Fedora 25](https://bodhi.fedoraproject.org/updates/cockpit-135-1.fc25)\n"
  },
  {
    "path": "_posts/2017-03-30-cockpit-137.md",
    "content": "---\ntitle: Cockpit 136 and 137\nauthor: dperpeet\ndate: 2017-03-30 22:00\ntags: cockpit linux\nslug: cockpit-137\ncategory: release\nsummary: Cockpit with menu and storage changes\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from versions 136 and 137.\n\n### Reordered entries in the sidebar menu\n\nAs a followup to the new look, the entries in the sidebar menu have now been reordered in a more sensible fashion:\n\n * System information\n * Logs for troubleshooting\n * Configuring major subsystems: Storage, Networking\n * What's running: Containers and Virtual Machines\n * Implementation details: Admin accounts, Services/Units\n\nCheck out the screenshot below to see how this looks now.\n\n![Sidebar order](/images/cockpit-menu-order.png)\n\n### Storage management is more convenient\n\nIn order to make configuring storage more convenient, the Cockpit UI now prevents removing disks from a RAID when\nremoval would lead to data loss due to an insufficient number of remaining volumes in the RAID. Also, when creating\na Volume Group (LVM) or adding disk space to a Volume Group, unpartitioned space is now offered as a choice.\nIf selected, Cockpit automatically creates a partition before adding it to the Volume Group. Check out the screenshots\nbelow to see how these features look.\n\n![Remove RAID disk](/images/cockpit-remove-raid-disk.png)\n![Add unpartitioned disk](/images/cockpit-storage-add-unpartitioned.png)\n\n### Consider user known_hosts for ssh connections\n\nWhen managing remote machines, Cockpit now considers known host keys in the user's `~/.ssh/known_hosts` in addition to\nthe system-wide `/etc/ssh/ssh_known_hosts`. This makes Cockpit behave more like the standard ssh client.\n\n### Try it out\n\nCockpit 137 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/137)\n * [Fedora 25](https://bodhi.fedoraproject.org/updates/cockpit-137-1.fc25)\n"
  },
  {
    "path": "_posts/2017-06-09-cockpit-142.md",
    "content": "---\ntitle: Cockpit 142\nauthor: pitti\ndate: 2017-06-09 16:00\ntags: cockpit linux\nslug: cockpit-142\ncategory: release\nsummary: Cockpit with Virtual Machine improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from versions 141 and 142.\n\n### Virtual machines display an interactive console\n\nThe Virtual Machines page now offers easy access to graphical consoles in the new \"Console\" tab. If the VM has a VNC server\nenabled, then there is now an inline [noVNC](https://github.com/novnc/noVNC) console:\n\n![Machines inline console](/images/machines-inline-console.png)\n\nIf the VM only has a SPICE server, or the inline console is not sufficient, you can use \"Switch to Desktop Viewer\" and with a\nsingle button click open virt-viewer for that VM:\n\n![Machines external console](/images/machines-external-console.png)\n\nSee it in action:\n\n<iframe width=\"960\" height=\"720\" src=\"//youtube.com/embed/_zVi44KQ8KU?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Document how to grant/restrict access via polkit rules\n\nUsers who are not administrators can normally not perform actions such as\nchanging the hostname or start/stop systemd services. The\n[Privileges and Permissions](https://cockpit-project.org/guide/latest/privileges.html#privileges-polkit)\nsection in the guide and the\n[systemd feature page](https://cockpit-project.org/guide/latest/feature-systemd.html) now describe how to use polkit\nrules allow fine-grained permissions such as \"that user can restart this particular service\".\n\n### Attempt to tear down used partitions when formatting disks\n\nTrying to format a disk on the \"Disks\" page which still has partitions which are in use (mounted or used as an LVM\nphysical volume) will now attempt to unmount/remove the physical volume, instead of just failing:\n\n![Automatic device teardown](/images/cockpit-storage-teardown-device.png)\n\n### Try it out\n\nCockpit 142 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/142)\n * [Fedora 26](https://bodhi.fedoraproject.org/updates/cockpit-142-1.fc26)\n"
  },
  {
    "path": "_posts/2017-06-19-cockpit-143.md",
    "content": "---\ntitle: Cockpit 143\nauthor: pitti\ndate: 2017-06-19 14:00\ntags: cockpit linux\nslug: cockpit-143\ncategory: release\nsummary: Cockpit with new Software Updates page\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 143.\n\n### \"Software Updates\" page for package based operating systems\n\nThere is a new \"Software Updates\" page for classic dnf/yum/apt based systems,\nto complement the already existing one for OSTree on\n[Atomic](https://www.projectatomic.io). This uses the [PackageKit\nAPI](https://www.freedesktop.org/software/PackageKit/) for platform\nindependence. This feature is shipped in the new `cockpit-packagekit`\nsub-package.\n\nSee it in action:\n\n<iframe width=\"720\" height=\"540\" src=\"//youtube.com/embed/BENWI-dTKMs?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Inline VNC consoles\n\nThe inline VNC console advertised in [Cockpit 142](https://cockpit-project.org/blog/cockpit-142.html)\nwas not actually working from the released `cockpit-machine` package due to a\npackaging problem. Cockpit 143 corrects this problem. Thanks to Marek Libra!\n\n### Kubernetes RBAC authorization support\n\nThe Kubernetes page can now be used to log into Kubernetes installations that\nuse [RBAC authorization](https://kubernetes.io/docs/admin/authorization/rbac/).\n\n### RPM packages for IBM Z systems\n\nThe `cockpit-docker` RPM package is now being built on the s390x (IBM Z\nSystems) architecture, as the Fedora Docker package is available there.\n([#1462113](https://bugzilla.redhat.com/show_bug.cgi?id=1462113))\n\n### Try it out\n\nCockpit 143 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/143)\n * [Fedora 26](https://bodhi.fedoraproject.org/updates/cockpit-143-1.fc26)\n"
  },
  {
    "path": "_posts/2017-06-27-cockpit-hackfest.md",
    "content": "---\ntitle: Cockpit Virtual Hackfest\nauthor: stef\ndate: 2017-06-27 10:25\ntags: cockpit linux\nslug: cockpit-virtual-hackfest\ncategory: release\nsummary: There's a Cockpit Hackfest underway in Karlsruhe, Germany. We're working\n  on virtual machine functionality in Cockpit.\n---\n\nThere's a Cockpit Hackfest underway in Karlsruhe, Germany. We're working on the\nvirtual machine functionality in Cockpit.\n\n![Hackfest](/images/hackfest-1.jpg)\n\nThat means interacting with libvirt. Although libvirt has remoting functionality\nit has no API that's actually remotable and callable from Cockpit javascript code.\nSo Lars and Pavel started working on a DBus wrapper for the API.\n\nAt the same time, Martin is working on making the current\n[virsh](http://libvirt.org/virshcmdref.html) based access to libvirt more\nperformant, so we don't block on waiting until the DBus wrapper is done.\n\nLots of work was done understanding [redux](https://redux.js.org/). The initial\nmachines code in Cockpit was written using redux, and we needed to map it's\nconcept of models and state to the Cockpit way of storing state on the server\nand UI concepts like dialogs. Everyone was involved.\n\nAndreas, Garrett have been working on designs for creating a virtual machine\nand editing virtual machines. Dominik started work on implementing that code.\n\nMarius worked on deletion of virtual machines, and already has a\n[pull request](https://github.com/cockpit-project/cockpit/pull/7113) open.\n\nStef worked on the integration tests for the virtual machine stuff\nand is booting nested VMs [using nested images](https://github.com/cockpit-project/cockpit/pull/7117).\n\n![Hackfest](/images/hackfest-2.jpg)\n\nWheeee.\n"
  },
  {
    "path": "_posts/2017-07-03-cockpit-hackfest-wrapup.md",
    "content": "---\ntitle: Cockpit Virtual Hackfest Wrapup\nauthor: stef\ndate: 2017-07-03 16:25\ntags: cockpit linux\nslug: cockpit-virtual-hackfest-wrapup\ncategory: release\nsummary: Here's what happened at the Cockpit Hackfest last week in Karlsruhe, Germany.\n  We've were working on virtual machine functionality in Cockpit.\n---\n\nLast week a bunch of us met up in Karlsruhe in Germany to work on virtual\nmachines support in Cockpit. We had some specialists there who helped us\nget up to speed with VMs. Tons of pull requests opened, designs put together.\nSome of the changes are already merged and\n[released in Cockpit 144](https://github.com/cockpit-project/cockpit/releases/tag/144).\n\nMarek helped all of us understand how\n[Redux](https://redux.js.org/)\nstores\nand models data. The oVirt folks are using Redux a lot in front end code\nand want to be able to share code. Marius\n[managed to reconcile](https://github.com/cockpit-project/cockpit/pull/7121)\nRedux with our dialog and\n[promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)\ncode.\n\nCreating virtual machines is hard. There's a surprising amount of strange\nlittle details and corner cases. Andreas, Garrett, Pavel, Dominik and Michal were\ninvolved in long discussions about how to make this work. And Dominik opened a\n[pull request](https://github.com/cockpit-project/cockpit/pull/7128).\n\n![Create dialog](https://raw.githubusercontent.com/cockpit-project/cockpit-design/master/virtual-machines/create-new-vm.png)\n\n![Create dialog details](https://raw.githubusercontent.com/cockpit-project/cockpit-design/master/virtual-machines/create-vm-dialog.png)\n\nStef and Marek worked on\n[sharing](https://github.com/cockpit-project/cockpit/pull/7139)\n[code](https://github.com/cockpit-project/cockpit/pull/7133)\n[between](https://github.com/cockpit-project/cockpit/pull/7128)\nthe oVirt javascript code based on Cockpit and the more general\nvirtual machines code in Cockpit. Since most of the code is shared, we decided we\ndidn't want to create any further API here that we had to keep stable, but rather\nbuild and develop the two in tandem. In the future some of the specific UI widgets\nwill be factored out into reusable stable javascript NPM components.\n\nMartin\n[refactored Cockpit's access to libvirt](https://github.com/cockpit-project/cockpit/pull/7131)\nto be more efficient and scalable with the number of VMs.\nIt currently uses [virsh](https://libvirt.org/sources/virshcmdref/html-single/).\n\nAt the same time Lars and Pavel started a\n[DBus based wrapper for libvirt](https://github.com/larskarlitski/libvirt-dbus). This\nwrapper should be maintained near other libvirt bindings, such as\n[libvirt-python](https://libvirt.org/python.html).\n\nMarius added functionality to\n[Delete virtual machines](https://github.com/cockpit-project/cockpit/pull/7113) from the\nCockpit UI.\n\nStef wrote code to\n[boot real virtual machines](https://github.com/cockpit-project/cockpit/pull/7117) during\nCI testing. We're using the same [Cirros](http://cirros-cloud.net/) Linux that oVirt and\nOpenstack use during testing.\n\nAnd there were more pull requests and discussions, but I'm running out of space.\n"
  },
  {
    "path": "_posts/2017-07-07-cockpit-145.md",
    "content": "---\ntitle: Cockpit 145\nauthor: pitti\ndate: 2017-07-07 16:00\ntags: cockpit linux\nslug: cockpit-145\ncategory: release\nsummary: Cockpit with Machines, Terminal, and Software Updates improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 144 and 145.\n\n### Terminal size\n\nThe Terminal now uses the full window size and dynamically resizes with it.\nPreviously its size was fixed to 80x24 characters.\n\n![Full-window terminal](/images/terminal-full-window.png)\n\n### Machines page reactiveness\n\nThe Machines page now listens to libvirt events instead of reading the entire\nstate of all virtual machines every ten seconds. This makes the page much more\nreactive to state changes and reduces the number of calls to `virsh`.\n\n### Delete VM functionality\n\nA \"Delete\" button/dialog was added to the Machines page. If the VM is still\nrunning, it will be force-stopped first. The dialog also offers you the choice\nto remove the VM's disk images as well.\n\n![Delete VM](/images/machines-delete.png)\n\n### Retire external Machines provider API\n\nCockpit 132 introduced an external API for the Machines page that allowed third\nparty plugins to dynamically add/manage virtual machines from providers other\nthan libvirt. This was found to be not supportable in the long run and thus was\ndiscontinued.\n\n### ABRT integration\n\nOn Fedora 26 the Logs Page now shows Problem reports from the ABRT crash\nreporting tool. They appear as new message class \"Problem\" in the journal view,\nand their details can be visited when clicking on them:\n\n![ABRT list view](/images/logs-abrt-list.png)\n\n![ABRT detail view](/images/logs-abrt-details.png)\n\nThanks to Matej Marusak for this feature!\n\n### Always recommend restarting after applying Software Updates\n\nMost supported operating systems in Cockpit don't provide a reliable\ndetection of whether they require restarting the machine after applying updates\nfor them to fully take effect. This particularly affects updates to the kernel,\nbut also restarting services. For now, Cockpit will always recommend to\nrestart the machine after applying updates:\n\n![Restart after Updates](/images/updates-restart.png)\n\n### Cancelling Software Updates\n\nThe Software Updates page now has a Cancel button that is enabled while it is\nstill safe to abort a running update, i.e. while the updates are still being\ndownloaded.\n\n### Try it out\n\nCockpit 145 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/145)\n * [Fedora 26](https://bodhi.fedoraproject.org/updates/cockpit-145-1.fc26)\n"
  },
  {
    "path": "_posts/2017-07-21-cockpit-146.md",
    "content": "---\ntitle: Cockpit 146\nauthor: pitti\ndate: 2017-07-21 10:00\ntags: cockpit linux\nslug: cockpit-146\ncategory: release\nsummary: Cockpit with Software Updates improvements and GCE support\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 146.\n\n### Software Updates page shows more information\n\nThe Available Updates and Restart recommended pages now show the packages\nfrom the previous update run. This makes it easier to see which services to\ncheck or to decide whether a restart is really necessary:\n\n![Update History](/images/updates-history.png)\n\nThe new Update Log expander shows the previous steps of the running update:\n\n![Update Log](/images/updates-live-log.png)\n\n### Improve available Software Updates layout for small/mobile screens\n\nThe Available Updates page now folds all information into a single column on\nvery narrow/mobile screens, to stay readable:\n\n![Narrow Updates Page](/images/updates-narrow.png)\n\nIn addition, updates with a long changelog or a large number of subpackages now\nget truncated, with a `More information…` expander. This avoids lots of empty\nspace that makes it difficult browse the updates list.\n\n### Support OAuth Kubernetes logins with Google Compute Engine\n\nThe Kubernetes pages (Cluster) can now log into Google Compute Engine. Note\nthat there is no way to get information about the user, so they are being\ndisplayed as `Unknown`.\n\n### Fix reporting ABRT crashes that are already known to the server\n\nTrying to report a crash (`Problems` category on the Logs page) that the FAF\nserver already knows previously caused an error message. This has been\ncorrected, and the report is now properly shown as `Reported`.\n\nThanks to Matej Marušák for this fix!\n\n### Scroll the virtual machine VNC console into view automatically\n\nWhen opening the builtin VNC console of a virtual machine, the page now\nautomatically gets scrolled to maximize visibility of the console.\n\nThanks to Marek Libra for this improvement!\n\n### Try it out\n\nCockpit 146 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/146)\n * [Fedora 26](https://bodhi.fedoraproject.org/updates/cockpit-146-1.fc26)\n"
  },
  {
    "path": "_posts/2017-07-25-cockpit-workshop-all-systems-go.md",
    "content": "---\ntitle: 'Cockpit Workshop before \"All Systems Go!\"'\nauthor: lars\ndate: 2017-07-25 16:00\n---\n\nWe're organizing a Cockpit workshop in Berlin on the 19th and 20th of October, the two days preceding the [All Systems Go! conference](https://all-systems-go.io/), the successor to last year's systemd.conf.\n\nThe idea is to bring the Cockpit community together to help each other out in various areas relating to Cockpit. For example: getting started writing a module, tackling beginner tasks, or understanding Cockpit's general architecture.\n\nIf you're interested, please let us know that you're planning on coming [on the list](https://lists.fedorahosted.org/archives/list/cockpit-devel@lists.fedorahosted.org/thread/KFHYTTUK4YK3JDKDXDMB4ONQNLZRJR6V/) and which topics you'd like to learn or teach about. This will help us to plan accordingly.\n\nAlso, spread the word if you like the idea!\n"
  },
  {
    "path": "_posts/2017-07-27-cockpit-147.md",
    "content": "---\ntitle: Cockpit 147\nauthor: pitti\ndate: 2017-07-27 15:00\ntags: cockpit linux\nslug: cockpit-147\ncategory: release\nsummary: Cockpit with Accounts improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 147.\n\n### Add configuration of expiry to Accounts page\n\nThe Accounts page can now display and change the expiration of user accounts\nand their passwords. Note that the login page supports changing expired\npasswords.\n\nSee it in action:\n\n<iframe width=\"960\" height=\"720\" src=\"//youtube.com/embed/q4JCoDF7XwY?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\nThanks to Fridolin Pokorny for this improvement!\n\n### Consistently ignore loopback traffic on all network load graphs\n\nThe network load graphics on the System, Networking, and Dashboard pages\nsometimes accounted traffic on the loopback network device (`lo`), which in\nmost cases is not interesting for administrators. Now the graphs always ignore\nthe loopback device.\n\n### Fix the Kdump page in Internet Exporer\n\nThis page previously produced errors when being opened in Internet Explorer due\nto using unsupported JavaScript functions. These got replaced.\n\n### Try it out\n\nCockpit 147 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/147)\n * [Fedora 26](https://bodhi.fedoraproject.org/updates/cockpit-147-1.fc26)\n"
  },
  {
    "path": "_posts/2017-08-04-cockpit-148.md",
    "content": "---\ntitle: Cockpit 148\nauthor: pitti\ndate: 2017-08-04 12:00\ntags: cockpit linux\nslug: cockpit-148\ncategory: release\nsummary: Cockpit with Internet Explorer support\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 148.\n\n### Support Cockpit in Internet Explorer\n\nWhen using Microsoft Windows Internet Explorer, navigating between pages and\nvarious other operations caused lost state changes, flickering, and lots of\nJavaScript errors. These have been corrected, and automatic tests now run with\nInternet Explorer as well.\n\n### Update Cluster/Registry design for image streams\n\nThe design of the image streams on the Cluster and Registry pages has been\nupdated to match the design of the current OpenShift Web Console.\n\n![Image Stream Tag Design](/images/registry-imagestreams-design.png)\n\n### Delete OpenShift session tokens on logout\n\nIf the Registry Console or Dashboard creates a new OpenShift session token on\nlogin, it will now delete that token again on logout. This behaviour now\nmatches what the OpenShift Web Console does.\n\n### Detect unregistered RHEL systems on Software Updates page\n\nOn RHEL systems which have not yet been registered or whose registration\nexpired, the Software Page would previously have claimed that \"the system is up\nto date\". Now it detects if the system is unregistered and thus cannot receive\nupdates:\n\n![Software Updates on unregistered RHEL system](/images/updates-unregistered.png)\n\n### Try it out\n\nCockpit 148 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/148)\n * [Fedora 26](https://bodhi.fedoraproject.org/updates/cockpit-148-1.fc26)\n"
  },
  {
    "path": "_posts/2017-09-08-cockpit-150.md",
    "content": "---\ntitle: Cockpit 150\nauthor: pitti\ndate: 2017-09-08 10:00\ntags: cockpit linux\nslug: cockpit-150\ncategory: release\nsummary: Cockpit with systemd and GCE 1.7.x improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from versions 149 and 150.\n\n### Add information about unmet conditions for systemd services\n\nSystemd units can have conditions which must be met in order for the service to\nstart. Cockpit now shows unmet conditions in the details of a service, so that\nusers can see why a service is in active.\n\n![Unmet systemd service conditions](/images/services-conditions.png)\n\n### Automatically enable and start newly created timers on the Services page\n\nCockpit allows the user to create custom systemd timers on the Services page,\nto run commands at particular times or after boot. Previously they had to be\nexplicitly enabled and started to become effective; this now happens\nautomatically.\n\n### Support Kubernetes authentication providers in kube config files\n\nSome kubernetes deployments such as Google Compute Engine use Kubernetes\nauthentication providers so that they can automatically regenerate their access\ntoken when needed. Cockpit now supports kube config files using this format.\n\n### Support sending non-maskable interrupt to VMs\n\nThe Shut Down button on the Machines page got a new option \"Send Non-Maskable\nInterrupt\". This normally does not trigger a reaction (other than a kernel\nmessage), but the Linux kernel can be configured to react to this with a kernel\npanic. This allows administrators to debug hung virtual machines.\n\n![Machines NMI](/images/machines-nmi.png)\n\n### Support Dashboard installation into OSTree overlay\n\nThe cockpit-dashboard package can now be installed as package overlay into\nrpm-ostree. This enables managing multiple remote servers through one Cockpit\ninstance on Atomic based systems.\n\n### Clear cockpit cookie on logout\n\nPreviously, after logging out (explicitly or due to session timeout) it could\nhappen that revisiting a seen page would show a cached version instead of the\nlogin page. This has now been fixed by properly clearing Cockpit's browser\ncookie.\n\n### Try it out\n\nCockpit 150 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/150)\n * [Fedora 26](https://bodhi.fedoraproject.org/updates/cockpit-150-1.fc26)\n"
  },
  {
    "path": "_posts/2017-09-21-cockpit-151.md",
    "content": "---\ntitle: Cockpit 151\nauthor: pitti\ndate: 2017-09-21 09:00\ntags: cockpit linux\nslug: cockpit-151\ncategory: release\nsummary: Cockpit with Kubernetes fixes and SSH improvement\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 151.\n\n### Support loading SSH keys from arbitrary paths\n\nThe User menu's Authentication dialog now supports entering arbitrary paths to\nSSH keys for adding to the SSH authentication agent. Previously this only\noffered keys present in the standard `~/.ssh` home directory.\n\nSee it in action:\n\n<iframe width=\"960\" height=\"720\" src=\"https://cockpit.fedorapeople.org/add-keys.webm\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Support X-Forwarded-Proto HTTP header for Kubernetes\n\nNewer Kubernetes versions support reading the\n[X-Forwarded-Proto](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto)\nHTTP header, which helps to determine whether or not a client used SSL to\nconnect to an intermediate proxy, load balancer, or similar. Cockpit's\nKubernetes (Cluster) dashboard now sets this header. Earlier versions have\nalready done that when hosted in OpenShift.\n\n### Fix Kubernetes connection hangs\n\nThe previous Cockpit release 150 introduced a regression when connecting to\nKubernetes clusters. In some cases, like specifying a wrong server name or when\nthe Cluster did not send Authentication Provider information, the connection\nattempt would hang indefinitely. This version corrects this bug.\n\n### Try it out\n\nCockpit 151 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/151)\n * [Fedora 26](https://bodhi.fedoraproject.org/updates/cockpit-151-1.fc26)\n"
  },
  {
    "path": "_posts/2017-10-06-cockpit-152.md",
    "content": "---\ntitle: Cockpit 152\nauthor: pitti\ndate: 2017-10-06 09:00\ntags: cockpit linux\nslug: cockpit-152\ncategory: release\nsummary: Cockpit with new Applications page and automatic software updates\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 152.\n\n### Add Applications page\n\nThis version introduces the \"Applications\" tool page. This is an extension\npoint for third-party software to add themselves to the Cockpit interface, by\nshipping appropriate [AppStream](https://www.freedesktop.org/wiki/Distributions/AppStream/)\nmetadata.\n\nNote that at the moment there are no real Cockpit applications available yet.\nFor testing this feature on Fedora, Marius Vollmer provides a\n[COPR](https://copr.fedorainfracloud.org/coprs/mvo/cockpit-app-freeipa/)\nrepository that can be enabled with these commands:\n\n```\ndnf copr enable mvo/cockpit-app-freeipa\ndnf install appstream-data-mvo\n```\n\nSee it in action:\n\n<iframe width=\"960\" height=\"720\" src=\"//youtube.com/embed/IXDqosBbAOc?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Add automatic update configuration for dnf to Software Updates\n\nOn Fedora ≥ 26, the Software Updates page now offers to enable and configure\n[dnf-automatic](https://fedoraproject.org/wiki/AutoUpdates) for automatic daily\nor weekly updates.\n\nFor now this is only shown if the `dnf-automatic` package is already installed.\nFuture Cockpit versions will install that on demand, and also cover\nDebian/Ubuntu systems.\n\n![Automatic Updates](/images/updates-auto-day.png)\n\n### Fix cockpit-bridge crash if /etc/os-release does not exist\n\nSome environments (particularly Docker containers) might not have an\n`/etc/os-release` file, which `cockpit-bridge` previously required.\n\n### Try it out\n\nCockpit 152 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/152)\n * [Fedora 27](https://bodhi.fedoraproject.org/updates/cockpit-152-1.fc27)\n"
  },
  {
    "path": "_posts/2017-10-17-cockpit-153.md",
    "content": "---\ntitle: Cockpit 153\nauthor: pitti\ndate: 2017-10-17 10:00\ntags: cockpit linux\nslug: cockpit-153\ncategory: release\nsummary: Cockpit with new oVirt package\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 153.\n\n### Add oVirt package\n\nThis version introduces the \"oVirt Machines\" page on Fedora for controlling\noVirt virtual machine clusters.  This code was moved into Cockpit as it shares\na lot of code with the existing \"Machines\" page, which manages virtual machines\nthrough libvirt.\n\nThis feature is packaged in cockpit-ovirt and when installed it will replace\nthe \"Machines\" page.\n\n![oVirt overview](/images/ovirt-overview.png)\n\n### Packaging cleanup\n\nThis release fixes a lot of small packaging issues that were spotted by\nrpmlint/lintian.\n\n### Try it out\n\nCockpit 153 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/153)\n * [Fedora 27](https://bodhi.fedoraproject.org/updates/cockpit-153-1.fc27)\n"
  },
  {
    "path": "_posts/2017-11-06-cockpit-155.md",
    "content": "---\ntitle: Cockpit 155\nauthor: pitti\ndate: 2017-11-06 17:00\ntags: cockpit linux\nslug: cockpit-155\ncategory: release\nsummary: Cockpit with NFS client support\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 155.\n\n### NFS client support\n\nThe Storage page now shows currently mounted NFS volumes and offers to\nmount/unmount them. Note that this does not yet support Kerberos\nauthentication; for now this relies on the classic `hosts.allow`/`hosts.deny` ACLs.\n\nSee it in action:\n\n<iframe width=\"960\" height=\"720\" src=\"//youtube.com/embed/PGCBda3Le9Y?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Add \"Maintenance\" switch for oVirt hosts\n\nSwitching a host to maintenance mode causes all VMs to be migrated to another\nrunning oVirt host.\n\n![oVirt Maintenance mode](/images/ovirt-maintenance.png)\n\n### Fix Terminal rendering issues in Chrome\n\nConsole programs like Midnight Commander which use graphical characters\nwere previously distorted in the Terminal in the Chrome Browser.\n\n### Improve Ctrl+W behaviour in the Terminal\n\nCtrl+W is commonly being used in a Terminal shell to delete the last word, but\nin web browsers it closes the current window or tab. Cockpit now causes a\nconfirmation dialog to pop up on Ctrl+W when the Terminal is focused to avoid\naccidental closing.\n\n### Support the upcoming OpenShift 3.7 release\n\nWhen available, use the `rbac.authorization` API instead of the `policybinding`\nAPI for determining project permissions. OpenShift 3.7 now properly supports\nthe former and stops supporting the latter. Cockpit remains compatible with\nolder OpenShift releases.\n\n### Try it out\n\nCockpit 155 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/155)\n * [Fedora 27](https://bodhi.fedoraproject.org/updates/cockpit-155-1.fc27)\n"
  },
  {
    "path": "_posts/2017-11-16-cockpit-156.md",
    "content": "---\ntitle: Cockpit 156\nauthor: pitti\ndate: 2017-11-16 08:00\ntags: cockpit linux\nslug: cockpit-156\ncategory: release\nsummary: Cockpit with navigation redesign\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 156.\n\n### Redesign main navigation and support mobile browsing\n\nThe top-level dashboard menus and second-level menus of them have been\nredesigned to clarify the structure, be more extensible, and use less vertical\nscreen space:\n\n![desktop mode](/images/mobilenav-desktop.png)\n\nThis version introduces proper support for using on mobile phones and tablets.\nAs part of this, the login screen was rearranged in mobile mode to avoid\noverlapping the on-screen keyboard with the user/password input fields:\n\n| ![mobile mode with menu](/images/mobilenav-mobile-menu.png) | &nbsp; | ![mobile login page](/images/mobilenav-login.png) |\n\n### Add project homepage links to Apps page\n\nApplications on the Apps page now show a link to the project home page, if\nprovided in the AppStream metadata:\n\n![apps homepage link](/images/apps-homepage-link.png)\n\nThanks Benjamin Deering for this feature!\n\n### Support alternate Kerberos keytabs\n\nIf present, Cockpit will now use the Kerberos `/etc/cockpit/krb5.keytab` file\ninstead of the default system keytab `/etc/krb5.keytab`.\n\nSee the [Single Sign On documentation](/guide/latest/sso.html#sso-server) for\ndetails.\n\n### Maintain an /etc/issue(5) file with current Cockpit status\n\nCockpit now maintains a `/run/cockpit/issue` file with instructions how to\nenable Cockpit (when disabled) or the Cockpit URL (when enabled).\n\nThe next util-linux 2.32 release will\n[support](https://github.com/karelzak/util-linux/commit/1fc82a1360305f696dc1be6105c9c56a9ea03f52)\n`/etc/issue.d/*.issue` drop-ins. Distributions or users can make use of this by\ninstalling an `/etc/issue.d/01-cockpit.issue` symlink to the above file.\n\n### Use event-driven refresh of oVirt virtual machine data instead of polling\n\nThis makes the page much more reactive and use less resources.\n\nThanks to Marek Libra for this improvement!\n\n### Try it out\n\nCockpit 156 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/156)\n * [Fedora 27](https://bodhi.fedoraproject.org/updates/cockpit-156-1.fc27)\n"
  },
  {
    "path": "_posts/2017-11-30-cockpit-157.md",
    "content": "---\ntitle: Cockpit 157\nauthor: pitti\ndate: 2017-11-30 15:00\ntags: cockpit linux\nslug: cockpit-157\ncategory: release\nsummary: Cockpit with virtual machine improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 157.\n\n### Virtual Machine network devices\n\nThe Machines page overview lists all libvirt defined virtual machines, which\nnow have a \"Networks\" tab. This shows the virtual machine's network devices and\nbuttons to plug/unplug them.\n\nThanks to Bohdan Iakymets for this feature!\n\n![virtual machine networks](/images/machines-networks.png)\n\n### The Apps page now displays SVG app icons\n\nBefore only PNG icons were supported.\n\nThanks to jeepingben for this feature!\n\n### Try it out\n\nCockpit 157 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/157)\n * [Fedora 27](https://bodhi.fedoraproject.org/updates/cockpit-157-1.fc27)\n"
  },
  {
    "path": "_posts/2017-12-13-cockpit-158.md",
    "content": "---\ntitle: Cockpit 158\nauthor: pitti\ndate: 2017-12-13 09:30\ntags: cockpit linux\nslug: cockpit-158\ncategory: release\nsummary: Cockpit with NFS client improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 158.\n\n### Add check boxes for common NFS mount options\n\nSetting up an NFS mount point on the Storage page now offers check boxes for\nthe most common mount options: \"Mount at boot\" and \"Mount read only\". Other\narbitrary options can still be given in the \"Custom\" input line, as before.\n\n![NFS option checkboxes](/images/storage-nfs-option-checkboxes.png)\n\n### Clarify Software Update status if only security updates are available\n\nIn that case the status message is now \"n security fixes\" instead of \"n\nupdates, including n security fixes\".\n\n### Create self-signed certificates with SubjectAltName\n\nWhen connecting to Cockpit through SSL (https://...) without explicitly\nconfiguring a certificate, Cockpit generates a self-signed one. This\ncertificate now has a `SubjectAltName:` field that is valid for\nlocalhost/127.0.0.1. Some browsers, like Chromium, require this field to accept\na certificate for an SSL connection.\n\nThis allows administrators or users to import Cockpit's certificate into the\nsystem oder user certificate database so that web browsers can connect to\nCockpit without SSL errors:\n\n```\nopenssl s_client -connect 127.0.0.1:9090 < /dev/null | \\\n    sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > /tmp/cert.pem\ncertutil -d sql:$HOME/.pki/nssdb -A -t \"TC,C,P\" -n cockpit -i /tmp/cert.pem\n```\n\n### Try it out\n\nCockpit 158 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/158)\n * [Fedora 27](https://bodhi.fedoraproject.org/updates/cockpit-158-1.fc27)\n"
  },
  {
    "path": "_posts/2018-01-10-cockpit-159.md",
    "content": "---\ntitle: Cockpit 159\nauthor: pitti\ndate: 2018-01-10 10:30\ntags: cockpit linux\nslug: cockpit-159\ncategory: release\nsummary: Cockpit with VDO support and VM improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 159.\n\n### Configure data deduplication with VDO devices\n\nThe \"Virtual Data Optimizer\" is a new feature to eliminate duplication and add\ncompression to block devices. This is mostly aimed at providing storage for\nvirtual machines or object storage systems like Ceph.\n\nThis is being developed upstream by the [dm-vdo GitHub\nproject](https://github.com/dm-vdo). It is currently available in\n[RHEL 7.5 alpha](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/storage_administration_guide/vdo)\nand expected to land in other distributions eventually.\n\nCockpit's Storage page can now create and configure VDO devices. See it in action:\n\n<iframe width=\"960\" height=\"720\" src=\"//youtube.com/embed/_iOYN4Y24aY?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Add serial console to virtual Machines page and redesign the Consoles tab\n\nThe Machines page has offered in-browser and external VNC console access to\nvirtual machines for some time. However, this does not work on \"headless\"\nvirtual machines that don't provide a (virtual) graphics card and VNC libvirt\ndevice.  The Consoles tab now offers a serial console for these kind of VMs to\nbe able to administer them from Cockpit as well.\n\nThis went along with a redesign of the Consoles tab to better fit the various\ntypes of consoles.\n\nSee it in action:\n\n<iframe width=\"960\" height=\"720\" src=\"//youtube.com/embed/nT2EA6wYkKI?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\nThanks to Marek Libra for this feature!\n\n### Show more error message details for VM failures on virtual Machines page\n\nErrors from virtual machine operations on the Storage page can now be expanded\nto show more details:\n\n![VM error expander](/images/machines-error-expander.png)\n\nThanks to Marek Libra for this improvement!\n\n### Try it out\n\nCockpit 159 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/159)\n * [Fedora 27](https://bodhi.fedoraproject.org/updates/cockpit-159-1.fc27)\n"
  },
  {
    "path": "_posts/2018-01-24-cockpit-160.md",
    "content": "---\ntitle: Cockpit 160\nauthor: pitti\ndate: 2018-01-24 10:00\ntags: cockpit linux\nslug: cockpit-160\ncategory: release\nsummary: Cockpit with Kubevirt, Software Updates, and AppStream improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 160.\n\n### Add kubevirt Virtual Machines overview\n\n[kubevirt](http://www.kubevirt.io) is a project for running KVM virtual\nmachines in [Kubernetes](https://kubernetes.io/). Cockpit's \"Cluster\"\n(Kubernetes/OpenShift) dashboard can now show the status of these VMs in the\nnew \"Virtual Machines\" menu entry. This only appears when kubevirt is installed\nand active:\n\n![Cluster kubevirt list](/images/kubernetes-kubevirt-list.png)\n\nIn the future this will be extended to also do operations on the VMs.\n\nThanks to Jakub Niedermertl for this feature!\n\n### Redesign package list on Software Updates page and show RHEL Errata\n\nThe table of available updates now looks and behaves much more consistently to\nother products that handle software packages, like\n[Satellite](https://www.redhat.com/de/technologies/management/satellite) and\n[Welder](https://github.com/weldr/welder-web):\n\n * It now only shows the first line of the description and number of fixed\n   security issues or bugs in the table, and moves the full description and\n   detailed bug/CVE lists into an expander.\n\n * It shows icons for the severity of the update, i. e. \"security\", \"bug fix\",\n   or \"enhancement\".\n\n * On Red Hat operating systems it also shows the\n   [classification](https://access.redhat.com/security/updates/classification)\n   of security updates and links to the corresponding Errata.\n\n![Software Updates redesign and Errata](/images/packagekit-errata.png)\n\n * [PackageKit](http://packagekit.org) often provides the update details in\n   [Markdown](https://en.wikipedia.org/wiki/Markdown) format. This now gets\n   rendered properly instead of shown verbatim in text.\n\n![Software Updates markdown](/images/packagekit-markdown.png)\n\n### AppStream handling on Apps page\n\nOn Fedora, the Apps page now installs the `appstream-data` package when\nchecking for new applications, which ships the\n[AppStream](https://www.freedesktop.org/wiki/Distributions/AppStream/) metadata\nfor discovering new Cockpit applications.\n\nThis Cockpit version also adds AppStream metadata for its own\n`cockpit-sosreport` package (which is not installed by default). Once\n`appstream-data` gets updated again in Fedora, cockpit-sosreport will appear on\nthe Apps page as an available extension.\n\n### Change CPU graphs to use \"100%\" for a fully loaded multi-processor system\n\nPreviously, the CPU graphs on the System, Dashboard, and Containers pages were\ncalibrated to 100% for a single CPU core, so that the graph maxed out at e. g.\n400% for a system with four busy CPU cores. Now it gets scaled so that \"100%\"\nmeans \"all cores are fully busy\", which is the behaviour of command line\ntools like `top`.\n\n### Show storage, network, and other numbers with 3 digits of precision\n\nPreviously numbers like the free space on a storage device were shown with one\nfractional digit only, which led to overly imprecise numbers like \"0.1 GiB\".\nThe new behaviour provices a more consistent accuracy regardless of the\nnumber's magnitude.\n\n### Add an example bastion container\n\nA [bastion container](https://github.com/cockpit-project/cockpit/tree/master/containers/bastion)\nprovides Cockpit's web service without actually logging in to the machine on\nwhich it runs, but only connects to remote hosts via ssh.\n\nThis is not a ready-to-use product for now, but we encourage you to experiment\nwith the example and give us feedback if you have such a use case.\n\n### Try it out\n\nCockpit 160 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/160)\n * [Fedora 27](https://bodhi.fedoraproject.org/updates/cockpit-160-1.fc27)\n"
  },
  {
    "path": "_posts/2018-02-07-cockpit-161.md",
    "content": "---\ntitle: Cockpit 161\nauthor: pitti\ndate: 2018-02-07 10:00\ntags: cockpit linux\nslug: cockpit-161\ncategory: release\nsummary: Cockpit with Virtual Machines, LVM, and Hardware Information improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 161.\n\n### New VMs can be created on Machines page\n\nThe Machines page now has a \"Create New VM\" button for installing a new libvirt\nvirtual machine from a local or remote ISO image. It allows the user to set\nsome basic properties such as memory and storage sizes.\n\n![Machines Create new VM](/images/machines-create-iso.png)\n\nThanks to Dominik Perpeet and suomiy for this feature!\n\n### VMs running in Kubernetes can now be deleted\n\n[Cockpit 160](https://cockpit-project.org/blog/cockpit-160.html) added an\ninitial overview of kubevirt Virtual Machines. This page now got a first action\nto delete a running VM.\n\n![kubevirt Delete](/images/kubernetes-kubevirt-delete.png)\n\nThanks to Marek Libra for this feature!\n\n### Improve LVM volume resizing\n\nCockpit now knows upfront whether shrinking or growing an LVM logical volume is\npossible, and whether the filesystem needs to be unmounted.  Since shrinking\nand growing are quite different in practice, the Storage page now shows\nseparate \"Shrink\" and \"Grow\" buttons. See it in action:\n\n<iframe width=\"960\" height=\"720\" src=\"//youtube.com/embed/M43yTrJ0jzc?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Add new Hardware Information page\n\nOn the System page the \"Hardware\" name is now a link to a new \"Hardware\ninformation\" page. For now this shows information about the system name, form\nfactor, CPU, BIOS, and PCI devices. Other types of hardware will be added in\nfuture versions.\n\n![System Hardware Info](/images/system-hwinfo.png)\n\n### Rename cockpit-ovirt package to cockpit-machines-ovirt\n\nThe previous package name collided with a package that is already available in\nRed Hat Virtualization Host. This only affects Fedora, as other operating systems\ndo not ship the Cockpit ovirt extension.\n\n### Stop advertising and supporting cockpit-bundled jQuery library\n\nCockpit's [JavaScript API documentation](https://cockpit-project.org/guide/latest/api-base1-jquery.html)\npreviously had some outdated information about jQuery, suggesting that users of\nthe Cockpit API should always load jQuery, and use the one bundled with `cockpit.js`.\nThis has not been true for a long time, and was just forgotten to be cleaned up.\nPreviously the Cockpit code examples also did that, misleading developers who\nused them as a starting point for their own modules.\n\nBoth the documentation and the examples got cleaned up now, and issues got\nfiled on affected GitHub projects. From now on, please use your own jQuery\nmodule for your projects instead of cockpit's bundled one. This avoids breaking\nyour project when cockpit's jQuery version gets updated.\n\n### Try it out\n\nCockpit 161 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/161)\n * [Fedora 27](https://bodhi.fedoraproject.org/updates/cockpit-161-1.fc27)\n"
  },
  {
    "path": "_posts/2018-02-21-cockpit-162.md",
    "content": "---\ntitle: Cockpit 162\nauthor: pitti\ndate: 2018-02-21 10:30\ntags: cockpit linux\nslug: cockpit-162\ncategory: release\nsummary: Cockpit with Virtual Machines improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 162.\n\n### Show pod name and disks of VMs running in Kubernetes\n\nThe KubeVirt Virtual Machines overview now shows the pod of running VMs.\nClicking on the name navigates to the pod's detail page.\n\nThe new \"Disks\" tab shows information about the emulated QEMU storage devices\nin the VM, similar to the Machines page.\n\n![KubeVirt pod name](/images/kubernetes-kubevirt-podname.png)\n\n![KubeVirt Disks](/images/kubernetes-kubevirt-disks.png)\n\nThanks to Marek Libra for this feature!\n\n### Tighten up the default Content-Security-Policy\n\nCockpit's pages now further restrict their\n[Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)\nto prevent forms and links from accidentally leaking data off-host.\n\nAn additional benefit is improved privacy, as `Referrer:` headers are no longer\nsent when following a link in Cockpit to an external site. (One common place\nwhere Cockpit links externally is on changelogs in the Software Updates page.)\n\nNote that this is *not* an actual security device - once a malicious page runs\nin Cockpit, it can use the Cockpit API to run arbitrary code on the host. This\nchange is intended as a defense against programming errors.\n\n### Drop cockpit-subscriptions and cockpit-integration-tests on Fedora\n\nThere is a new package \"subscription-manager-cockpit\" now which supersedes the\n\"cockpit-subscriptions\" package that was previously shipped by Cockpit.\n\nThe cockpit-integration-tests package had been an experiment, was never used\nin Fedora CI, and requires additional files from Cockpit's upstream git tree to\nwork.\n\n### Try it out\n\nCockpit 162 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/162)\n * [Fedora 27](https://bodhi.fedoraproject.org/updates/cockpit-162-1.fc27)\n"
  },
  {
    "path": "_posts/2018-03-07-cockpit-163.md",
    "content": "---\ntitle: Cockpit 163\nauthor: pitti\ndate: 2018-03-07 11:00\ntags: cockpit linux\nslug: cockpit-163\ncategory: release\nsummary: Cockpit with various bug fixes\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 163.\n\n### Hide Docker storage pool reset button when it cannot work properly\n\nFedora Atomic used to configure a separate logical volume called\n`docker-root-lv` as a Docker storage pool. Recently, Fedora Atomic switched to\nusing one large volume for both the root partition and Docker.\n\nDue to this change in Fedora Atomic, Cockpit can no longer remove and free\npreviously added storage devices. As a result, we have removed the “Reset”\nbutton on the storage pool page under these circumstances.\n\n### Drop \"Transfer data asynchronously\" VDO option on Storage page\n\nRecent versions of [VDO](https://github.com/dm-vdo/vdo) now automatically detect\nthe correct setting for asynchronous data transfer, so this option is no longer\nneeded.\n\nManually setting the option may also lead to unsupported configurations in the\nfuture.\n\n*[VDO]: virtual data optimizer\n\n### Update jQuery to version 3.3.1\n\nCockpit updated jQuery from 2.2 to 3.3.1.\n\nThird party projects should no longer use Cockpit’s bundled jQuery, as\nannounced in [Cockpit 161](https://cockpit-project.org/blog/cockpit-161.html).\nAll known consumers of this deprecated usage have been updated.\n\nIf you have a private cockpit extension that currently includes\n`\"../base1/jquery.js\"`, please verify that your project still works, remove the\nreference to Cockpit’s bundled jQuery, and include your own copy of jQuery\nthrough [NPM](https://www.npmjs.com/) or a [CDN](https://code.jquery.com/).\n\n*[NPM]: Node Package Manager\n*[CDN]: Content Delivery Network\n\n([More information](https://lists.fedorahosted.org/archives/list/cockpit-devel@lists.fedorahosted.org/thread/TDBKI4372I4ZPGQFCZB377DX2QG2YDDY/))\n\n### Try it out\n\nCockpit 163 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/163)\n * [Fedora 27](https://bodhi.fedoraproject.org/updates/cockpit-163-1.fc27)\n"
  },
  {
    "path": "_posts/2018-03-09-starter-kit.md",
    "content": "---\ntitle: Starter Kit - the turn-key template for your own pages\nauthor: pitti\ndate: 2018-03-09\ncategory: tutorial\ntags: cockpit starter-kit\nslug: cockpit-starter-kit\ncomments: true\n---\n\n## The bare minimum\n\n[Cockpit's API](https://cockpit-project.org/guide/latest/development.html) makes it easy to create your own pages (or\n\"extensions\" if you will) that appear in Cockpit's menu and interact with your system in any way you like. Our pet\nexample is the [Pinger](https://github.com/cockpit-project/cockpit/tree/master/examples/pinger) which is just the bare\nminimum: a [HTML file](https://github.com/cockpit-project/cockpit/blob/master/examples/pinger/ping.html) with a form to\nenter an IP, a small [piece of JavaScript](https://github.com/cockpit-project/cockpit/blob/master/examples/pinger/pinger.js)\nto call the `ping` Linux command  through Cockpit [spawn()](https://cockpit-project.org/guide/latest/cockpit-spawn.html)\nand capture its output; and a\n[manifest file](https://github.com/cockpit-project/cockpit/blob/master/examples/pinger/manifest.json) which tells\ncockpit how to add it to the menu and where the entry point is.\n\nThere is a rather old [blog post](https://cockpit-project.org/blog/creating-plugins-for-the-cockpit-user-interface.html)\nwhich explains the Pinger example in detail. Cockpit changed its visual design quite dramatically since then, Pinger's\nJavaScript got split into a separate file and does not use jQuery any more, but aside from these details that post is\nstill generally applicable.\n\n## Requirements for real projects\n\nPinger is great for explaining and understanding the gist of how Cockpit works. But an actual production-ready project\nrequires a lot more:\n\n * Separation of HTML, CSS, and JavaScript code: This ensures that your code can use a safe\n   [Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) and does not have to use e. g.\n   `unsafe-inline`.  We *strongly* recommend this for third-party pages, and absolutely require this for Cockpit's own\n   pages.\n\n * Modern frameworks for creating page contents. For any non-trivial page you really don't want to dabble with piecing\n   together `myelement.innerHTML = …` strings, but use something like [React](https://reactjs.org/) to build page\n   contents and [PatternFly](http://www.patternfly.org/) so that your page fits into Cockpit's design.\n\n * Use [Babel](https://babeljs.io/) to write your code in modern [ES6 JavaScript](http://es6-features.org/).\n\n * Use [ESLint](https://eslint.org/) to spot functional and legibility errors in your code.\n\n * A build system like [webpack](https://webpack.js.org/) to drive all of the above and build blobs (\"minified\n   Javascript in a single file\") that are efficiently consumable by browsers.\n\n * Building of release tarballs, source and binary RPMs for testing and distribution.\n\n * Tests to make sure your code keeps working, new features work on all supported operating systems, and changes (pull\n   requests) get validated.\n\n * As a bonus, easy and safe testing of your page in a [Vagrant virtual machine](https://www.vagrantup.com/).\n\nSounds complex? It indeed is for someone who is not familiar with the ever-changing \"modern\" JavaScript world, and\ndoesn't want to learn the details of all of these before you can even begin working on your code. This is where the\nStarter Kit comes in!\n\n## Bootstrapping your way from zero to \"works!\"\n\nThe [Cockpit Starter Kit](https://github.com/cockpit-project/starter-kit/) is an example project which provides all of\nthe above requirements. It provides a simple\n[React page](https://github.com/cockpit-project/starter-kit/blob/master/src/starter-kit.jsx)\nthat uses the [cockpit.file() API](https://cockpit-project.org/guide/latest/cockpit-file.html) to read `/etc/hostname`\nand show it. There is also an accompanying\n[test](https://github.com/cockpit-project/starter-kit/blob/master/test/check-starter-kit) that verifies this page. The\nother files are mostly build system boilerplate, i. e. the things you don't want to worry about as the first thing when\nyou start a project.\n\nSo, how to get this? Make sure you have the `npm` package installed. Then check out the repository and build it:\n```\ngit clone https://github.com/cockpit-project/starter-kit.git\ncd starter-kit\nmake\n```\n\nAfter that, install (or rather, symlink) the webpack-generated output page in `dist/` to where cockpit can see it:\n\n```\nmkdir -p ~/.local/share/cockpit\nln -s `pwd`/dist ~/.local/share/cockpit/starter-kit\n```\nNow you should be able to log into <https://localhost:9090> and see the \"Starter Kit\" menu entry:\n\n![starter kit](/images/starter-kit.png)\n\nThe symlink into your source code checkout is a very convenient and efficient way of development as you can just type\n`make` after changing code and directly see the effect in Cockpit after a page reload.\n\nYou should now play around with this a little by hacking src/starter-kit.jsx, running `make`, and reloading the page.\nFor example, try to read and show another file, run a program and show its output, or use\n[cockpit.file(\"/etc/hostname\").watch(callback)](https://cockpit-project.org/guide/latest/cockpit-file.html)\nto react to changes of /etc/hostname and immediately update the page.\n\n## Testing\n\nUntested code is broken code. If not here and now, then in the future or some other operating system. This is why\nCockpit has a rather complex machinery of regularly building 26 (!) VM images ranging from RHEL-7 and Fedora 27 over\nvarious releases of Debian and Ubuntu to OpenShift and Windows 8, and running hundreds of integration tests on each of\nthem for every PR in an OpenShift cluster.\n\nReplicating this for other projects isn't easy, and this has been one, if not *the* major reason why there aren't many\nthird-party Cockpit projects yet. So we now made it possible for third-party GitHub projects to use Cockpit's CI\nenvironment, test VM images, and (independently) Cockpit's browser test abstraction API.\n\nstarter-kit uses all three of those: When you run `make check`, it will:\n\n * build an RPM out of your current code\n * check out cockpit's [bots/ directory](https://github.com/cockpit-project/cockpit/tree/master/bots/) that has the\n   current image symlinks and tools to download, customize and run VM images\n * check out cockpit's [tests/common directory](https://github.com/cockpit-project/cockpit/tree/master/test/common) from\n   a stable Cockpit release (as the API is not guaranteed to be stable)\n   which provides a convenient Python API for the [Chrome DevTools protocol](https://chromedevtools.github.io/devtools-protocol/)\n * download Cockpit's current CentOS-7 VM image; you can test on a different operating system by setting the environment\n   variable `TEST_OS=fedora-27` (or a different operating system - but note that starter-kit does not currently build\n   debs)\n * create an overlay on that pristine centos-7 image with the operating system's standard \"cockpit\" package and your\n   locally built starter-kit RPM installed\n * run a VM with that overlay image with libvirt and QEMU\n * launch a chromium (or chromium-headless) browser\n * Run the actual [check-starter-kit](https://github.com/cockpit-project/starter-kit/blob/master/test/check-starter-kit)\n   test which instructs the web browser what to do and which assertions to make\n\n```\n[starter-kit] $ make check\n[...]\nrpmbuild -bb [...] cockpit-starter-kit.spec\n[...]\ngit fetch --depth=1 https://github.com/cockpit-project/cockpit.git\nFrom https://github.com/cockpit-project/cockpit\n * branch            HEAD       -> FETCH_HEAD\ngit checkout --force FETCH_HEAD -- bots/\n[...]\nbots/image-customize -v -r 'rpm -e cockpit-starter-kit || true' -i cockpit -i `pwd`/cockpit-starter-kit-*.noarch.rpm -s /home/martin/upstream/starter-kit/test/vm.install centos-7\n[...]\nTEST_AUDIT_NO_SELINUX=1 test/check-starter-kit\n1..1\n# ----------------------------------------------------------------------\n# testBasic (__main__.TestStarterKit)\n#\n\nok 1 testBasic (__main__.TestStarterKit) # duration: 21s\n# TESTS PASSED [22s on donald]\n```\n\nNote that the first time you run this will take a long time due to the rather large VM image download. But it will be\nreused for further tests.\n\nFor writing your own tests with the Cockpit Python API, have a look at the `Browser` and `MachineCase` classes in\n[testlib.py](https://github.com/cockpit-project/cockpit/blob/master/test/common/testlib.py). These provide both\nlow-level (like `click()` or `key_press()`) and high-level (like `login_and_go()`) methods for writing test cases. And\nof course you  have a wealth of [Cockpit tests](https://github.com/cockpit-project/cockpit/tree/master/test/verify) for\ngetting inspiration.\n\nstarter-kit itself is also covered by Cockpit's CI, i. e. pull requests will run tests on CentOS 7 and Fedora 27\n([example](https://github.com/cockpit-project/starter-kit/pull/17), click on \"View Details\"). Please come and talk to us\nonce your project is mature enough to do the same, then we can enable automatic pull request testing on your project as well.\n\n## Using different technologies\n\nstarter-kit makes opinionated choices like using React, webpack, and Cockpit's testing framework.  These are the\ntechnologies that we use for developing Cockpit itself, so if you use them you have the best chance that the Cockpit\nteam can help you with problems. Of course you are free to replace any of these, especially if you have already existing\ncode/tests or a build system.\n\nFor example, it is straightforward to just use Cockpit's test images with the `image-customize` tool and running these\nas ephemeral VMs with [testvm.py](https://github.com/cockpit-project/cockpit/blob/master/bots/machine/testvm.py), but\nnot use Cockpit's `test/common`. Tests can also be written with e. g. [puppeteer](https://github.com/GoogleChrome/puppeteer)\nor [nightmare](https://github.com/segmentio/nightmare). I will write about that separately.\n\n## Feedback\n\nstarter-kit is still fairly new, so there are for sure things that could work more robustly, easier, more flexibly, or\njust have better documentation. If you run into trouble, please don't hesitate telling us about it, preferably by\n[filing an issue](https://github.com/cockpit-project/starter-kit/issues).\n\nHappy hacking!\n\nThe Cockpit Development Team\n"
  },
  {
    "path": "_posts/2018-03-21-cockpit-164.md",
    "content": "---\ntitle: Cockpit 164\nauthor: pitti\ndate: 2018-03-21 13:00\ntags: cockpit linux\nslug: cockpit-164\ncategory: release\nsummary: Cockpit with usability and accessibility improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 164.\n\n### Storage: Usability improvements\n\nWe recently ran a usability study targeting the storage area. Based on the\nfindings, we redesigned and adjusted the NFS, VDO, and RAID storage devices.\n\nPreviously, Cockpit used checkbox \"arming\" and drop-down buttons to reveal\navailable actions. Usability tests indicated these interface elements\nwere too hard and unintuitive to discover. Cockpit now expresses these\nconcepts in a more straightforward way.\n\nAvailable RAID and VDO actions are now directly shown next to the\ncorresponding device:\n\n![Storage RAID action buttons](/images/storage-raid-action-buttons.png)\n\nNFS mounts are now clickable:\n\n![Storage NFS list](/images/storage-nfs-list.png)\n\nClicking an NFS mount now shows a new details page with directly\navailable actions:\n\n![Storage NFS list](/images/storage-nfs-details.png)\n\n### System: Show available package updates and missing registration\n\nThe System overview page now shows pending enhancements, bug fixes, and\nsecurity updates when they are available:\n\n![System available security updates](/images/system-security-updates.png)\n\nAs unregistered RHEL systems cannot receive updates they now display a warning:\n\n![System unregistered](/images/system-unregistered.png)\n\n### System: Fix inconsistent tooltips\n\nBefore this release, the System page had three different styles of tool tips.\nThee have been unified to use the standard\n[Bootstrap tooltips](https://getbootstrap.com/docs/4.0/components/tooltips/)\nlike other Cockpit pages. Relatedly, the performance profile used a static blue\n\"i\" for additional information. We removed the icon and attached the tooltip\ndirectly to the profile name.\n\n![System tuned profile](/images/system-tuned-profile.png)\n\nThe navigation redesign in\n[Cockpit 156](https://martinpitt.github.io/cockpit-project.github.io/blog/cockpit-156.html)\nincreased the width of host navigation items. As the navigation labels are no\nlonger truncated, their corresponding tooltips have been removed.\n\n### Logs: Change severities\n\nOn the Logs page, the severity filter now displays the officially defined\n[syslog(3) levels](https://linux.die.net/man/3/syslog) instead of the previous\nCockpit-specific names:\n\n![Log severity levels](/images/logs-syslog-severity-levels.png)\n\n_Thanks to Kirill Glebov for this improvement!_\n\n### Machines: Add error notifications\n\nThe Machines page now shows individual and dismissable error notifications for\nall virtual machines:\n\n![Machines error notifications](/images/machines-error-notifications.png)\n\n_Thanks to suomiy for this  improvement!_\n\n### Accessibility improvements\n\nThis Cockpit release includes several accessibility fixes. Notably,\n[ARIA markers](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA),\nrole tags, tabindex fixes, and several other improvements should help with\nkeyboard navigation and screen reader support.\n\nThere's still more accessibility related work to do, but these changes are\na step in the right direction.\n\n### Reloading the page in the browser now reloads Cockpit package manifests\n\nCockpit now refreshes the navigation menu on a browser reload. Installing,\nremoving, or updating Cockpit-related packages previously required logging\nout and back in to see the changes.\n\n### Try it out\n\nCockpit 164 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/164)\n * [Fedora 27](https://bodhi.fedoraproject.org/updates/cockpit-164-1.fc27)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-164-1.fc28)\n\n*[RHEL]: Red Hat Enterprise Linux\n*[NFS]: Network File System\n*[VDO]: Virtual Data Optimizer\n*[RAID]: Redundant Array of Inexpensive Disks\n*[ARIA]: Accessible Rich Internet Applications\n\n"
  },
  {
    "path": "_posts/2018-03-28-puppeteer-tests.md",
    "content": "---\ntitle: Using Cockpit test VMs with your own test framework\nauthor: pitti\ndate: 2018-03-28\ncategory: tutorial\ntags: cockpit starter-kit tests puppeteer\nslug: cockpit-custom-test-framework\ncomments: true\n---\n\nThe [Cockpit Starter Kit](https://github.com/cockpit-project/starter-kit/) provides the scaffolding for your own Cockpit\nextensions: a simple page (in React), build system (webpack, babel, eslint, etc.), and an integration test using\nCockpit's own Python test API on top of the\n[Chromium DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/).  See the recent\n[introduction](https://cockpit-project.org/blog/cockpit-starter-kit.html) for details.\n\nBut in some cases you want to use a different testing framework; perhaps you have an already existing project and tests.\nThen it is convenient and recommended to still using Cockpit's test VM images: they provide an easy way to test your\nproject on various Fedora/Red Hat/Debian/Ubuntu flavors; and they take quite a lot of effort to maintain! Quite\nfortunately, using the test images is not tightly bound to using Cockpit's test API, and not even to tests being written\nPython. They can be built and used entirely through command line tools from Cockpit's [bots/\ndirectory](https://github.com/cockpit-project/cockpit/tree/master/bots/), so you can use those with any programming\nlanguage and test framework.\n\n## Building and interacting with a test VM\n\nTo illustrate this, let's check out the Starter Kit and build a CentOS 7 based VM with cockpit and the starter kit\ninstalled:\n\n```sh\n$ git clone https://github.com/cockpit-project/starter-kit.git\n$ cd starter-kit\n$ make vm\n```\n\nOrdinarily, the generated `test/images/centos-7.qcow2` would be used by\n[test/check-starter-kit](https://github.com/cockpit-project/starter-kit/blob/master/test/check-starter-kit). But let's\ntinker around with the VM image manually. Cockpit's\n[testvm.py](https://github.com/cockpit-project/cockpit/blob/master/bots/machine/testvm.py) module for using these VMs\ncan be used as a command line program:\n\n```sh\n$ bots/machine/testvm.py centos-7\nssh -o ControlPath=/tmp/ssh-%h-%p-%r-23253 -p 2201 root@127.0.0.2\nhttp://127.0.0.2:9091\nRUNNING\n```\n\nIt takes a few seconds to boot the VM, then it prints three lines:\n\n * The SSH command to run something inside the VM\n * The URL for the forwarded Cockpit port 9090\n * A constant `RUNNING` flag that test suites can poll for to know when to proceed.\n\nYou can now open that URL in your browser to log into Cockpit (user \"admin\", password \"foobar\") and see the installed\nStarter Kit page, or run a command in the VM through the given SSH command:\n\n```sh\n$ ssh -o ControlPath=/tmp/ssh-%h-%p-%r-23253 -p 2202 root@127.0.0.2 head -n2 /etc/os-release\nNAME=\"CentOS Linux\"\nVERSION=\"7 (Core)\"\n```\n\nThe VM gets shut down once the `testvm.py` process gets a `SIGTERM` (useful for test suites) or `SIGINT` (useful for\njust pressing Control-C when interactively starting this in a shell).\n\n## Using testvm.py in your test suite\n\nLet's use the above in a [Puppeteer](https://github.com/GoogleChrome/puppeteer) test.\n[check-puppeteer.js](../files/starter-kit/check-puppeteer.js) is a straight port of\n[check-starter-kit](https://github.com/cockpit-project/starter-kit/blob/master/test/check-starter-kit); of course it is\na little longer than the original as we don't have the convenience functions of\n[testlib.py](https://github.com/cockpit-project/cockpit/blob/master/test/common/testlib.py) to automatically start and\ntear down VMs or do actions like \"log into Cockpit\", but it is still fairly comprehensible. Download it into the tests/ directory of\nyour starter-kit checkout, then install puppeteer:\n\n```sh\n$ PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 npm install puppeteer@0.12.0\n```\n\nThis will avoid downloading an entire private copy of chromium-browser and use the system-installed one. (Of course you\ncan also just call `npm install puppeteer` if you don't care about the overhead). Now run the tests:\n\n```sh\n$ DEBUG=\"puppeteer:page,puppeteer:frame\" PYTHONPATH=bots/machine test/check-puppeteer.js\n```\n\nThis will run them in a verbose mode where you can follow the browser queries and events.\n\nLet's walk through some of the code:\n\n```js\nfunction startVm() {\n    return new Promise((resolve, reject) => {\n        let proc = child_process.spawn(\"bots/machine/testvm.py\", [testOS], { stdio: [\"pipe\", \"pipe\", \"inherit\"] });\n        let buf = \"\";\n        proc.stdout.on(\"data\", data => {\n            buf += data.toString();\n            if (buf.indexOf(\"\\nRUNNING\\n\") > 0) {\n                let lines = buf.split(\"\\n\");\n                resolve({ proc: proc, ssh: lines[0], cockpit: lines[1] });\n            }\n        });\n        proc.on(\"error\", err => { throw `Failed to start vm-run: ${err}` });\n    });\n}\n```\n\nThis uses `testvm.py` as above to launch the VM. In a \"real\" test suite this would go into the per-test setup code.\n`check-puppeteer.js` does not use any test case organization framework (like [jest](https://www.npmjs.com/package/jest)\nor [QUnit](https://qunitjs.com/)), but if you have more than two or three test cases it's recommended to use one.\n\n\n```js\nasync function testStarterKit() {\n    const vm = await startVm();\n\n    const browser = await puppeteer.launch(\n        // disable sandboxing to also work in docker\n        { headless: true, executablePath: 'chromium-browser', args: [ \"--no-sandbox\" ] });\n```\n\nThis is the actual test case. Here we start Puppeteer, and here you can change various\n[options](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#puppeteerlaunchoptions)\nto influence the test. For example, set `headless: false` to get a visible Chomium window and follow live what the test\ndoes (or where it hangs).\n\n```js\n    const page = await browser.newPage();\n\n    try {\n        // log in\n        await page.goto(vm.cockpit);\n        await page.type('#login-user-input', 'admin');\n        await page.type('#login-password-input', 'foobar');\n        await page.click('#login-button');\n```\n\nThis is the equivalent of Cockpit test's `Browser.login_and_go()`. In a real test you would probably factorize this into\na helper function.\n\n```js\n        await page.waitFor('#host-nav a[title=\"Starter Kit\"]');\n        await page.goto(vm.cockpit + \"/starter-kit\");\n        let frame = getFrame(page, 'cockpit1:localhost/starter-kit');\n\n        // verify expected heading\n        await frame.waitFor('.container-fluid h2');\n        await frame.waitForFunction(() => document.querySelector(\".container-fluid h2\").innerHTML == \"Starter Kit\");\n\n        // verify expected host name\n        let hostname = vmExecute(vm, \"cat /etc/hostname\").trim();\n        await frame.waitFor('.container-fluid span');\n        await frame.waitForFunction(\n            h => document.querySelector(\".container-fluid span\").innerHTML == (\"Running on \" + h),\n            {}, hostname);\n    }\n```\n\nThis is a direct translation of what check-starter-kit does: Assert the expected heading and host name message.\n\n```js\n    catch (err) {\n        const attachments = process.env[\"TEST_ATTACHMENTS\"];\n        if (attachments) {\n            console.error(\"Test failed, taking screenshot...\");\n            await page.screenshot({ path: attachments + \"/testStarterKit-FAIL.png\"});\n        }\n        throw err;\n    }\n```\n\nThis part is optional, but very useful for debugging failed tests. If any assertion fails, this creates a PNG screenshot\nfrom the current browser page state. Run the test with `TEST_ATTACHMENTS=/some/existing/directory` to enable this. The\nCockpit CI machinery will export any files in this directory to the http browsable test results directory.\n\n```js\n     finally {\n        await browser.close();\n        vm.proc.kill();\n    }\n};\n```\n\nThis is a poor man's \"test teardown\" which closes the browser and VM.\n\n## Feedback\n\nstarter-kit and external Cockpit project tests are still fairly new, so there are for sure things that could work more\nrobustly, easier, more flexibly, or just have better documentation. If you run into trouble, please don't hesitate\ntelling us about it, preferably by [filing an issue](https://github.com/cockpit-project/starter-kit/issues).\n\nHappy hacking!\n\nThe Cockpit Development Team\n"
  },
  {
    "path": "_posts/2018-04-04-cockpit-165.md",
    "content": "---\ntitle: Cockpit 165\nauthor: pitti\ndate: 2018-04-04 12:00\ntags: cockpit linux\nslug: cockpit-165\ncategory: release\nsummary: Cockpit with NFS and VM improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 165.\n\n### Storage: Show more details of sessions and services that keep NFS busy\n\nWhen trying to unmount an NFS share that is currently in use, Cockpit offers a\ndialog to terminate the processes that keep it busy. That dialog now shows the\nsystemd service names, process command lines, and since when these have been\nactive. This allows the administrator a more informed decision whether it is\nokay to forcefully terminate these.\n\n![Storage NFS busy details](/images/storage-nfs-busy-details.png)\n\n### Machines: Detect if libvirtd is not running\n\nThe Virtual Machines page now detects if libvirtd.service is running. It offers\nto start and optionally enable the unit if it is not currently running:\n\n![Machines libvirt not running](/images/machines-libvirt-not-running.png)\n\nPreviously it just showed that \"no VMs are running\", which was misleading.\n\n_Thanks to suomiy for this improvement!_\n\n### Machines: Show virtual machines that are being created\n\nWhen creating a new virtual machine it takes a while to allocate and create the\ndisk image. During that time the new VM was not visible anywhere, which caused\nthe impression that the creation failed. Now the VM overview lists it\nimmediately with state \"creating VM installation\":\n\n![Machines VM creating](/images/machines-vm-creating.png)\n\n_Thanks to suomiy for this improvement!_\n\n### Try it out\n\nCockpit 165 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/165)\n * [Fedora 27](https://bodhi.fedoraproject.org/updates/cockpit-165-1.fc27)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-165-1.fc28)\n"
  },
  {
    "path": "_posts/2018-04-11-making-a-cockpit-application.md",
    "content": "---\ntitle: Make your Cockpit page easily installable\nauthor: mvo\ndate: 2018-04-09 10:00\ntags: cockpit\nslug: making-a-cockpit-application\ncategory: tutorial\ncomments: 'true'\n---\n\nSince version 152, Cockpit can discover and install packages that add\npages to Cockpit.  We call them \"Applications\" and as of now, only two\nof them exist: We have Fleet Commander and Cockpit's own Diagnostic\nReports in Fedora.  You might have seen them on the Applications page:\n\n![Two Cockpit Applications](/images/cockpit-two-apps.png)\n\nIf you want your own page to appear there, you have to add suitable\n[AppStream](https://www.freedesktop.org/wiki/Distributions/AppStream/)\ndata to your package in the right location.\n\nWhen your package is included in a distribution repository, the\nrepository machinery will find the data in your package and make it\navailable to software managers, such as the Cockpit \"Applications\"\npage.\n\n\nFor a Cockpit component, the AppStream data looks like this:\n```xml\n<component type=\"addon\">\n  <id>org.cockpit_project.demo-app</id>\n  <metadata_license>CC0-1.0</metadata_license>\n  <name>Demo Application</name>\n  <summary>\n    A demo add-on application for Cockpit\n  </summary>\n  <description>\n    <p>This is a demo application</p>\n  </description>\n  <extends>org.cockpit_project.cockpit</extends>\n  <launchable type=\"cockpit-manifest\">demo-app</launchable>\n</component>\n```\n\nThis would be placed at\n`/usr/share/metainfo/org.cockpit_project.demo-app.metainfo.xml` in\nyour package.\n\nThe important bit is the `launchable` element with type\n`cockpit-manifest`.  Any such AppStream component will be offered for\ninstallation by Cockpit.  The value is the name of the [Cockpit\npackage](https://cockpit-project.org/guide/latest/packages.html) for\nyour page.\n\nUse the component type `addon` and add an `extends` element for\n`org.cockpit_project.cockpit`.\n\nYou should of course come up with your own value for the `id` element,\nin the usual reverse-DNS style, and adjust the filename accordingly.\n"
  },
  {
    "path": "_posts/2018-04-18-cockpit-166.md",
    "content": "---\ntitle: Cockpit 166\nauthor: pitti\ndate: 2018-04-18 10:30\ntags: cockpit linux\nslug: cockpit-166\ncategory: release\nsummary: Cockpit with KubeVirt and FreeIPA improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 166.\n\n### Kubernetes: Add creation of Virtual Machines\n\nThe KubeVirt Virtual Machines page now offers a \"Create\" button for defining a\nnew virtual machine. The JSON definition can be provided with a file upload,\nwith drag & drop, or by copy & pasting. See it in action:\n\n<iframe width=\"960\" height=\"720\" src=\"//youtube.com/embed/J07dW5VZJtg?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n_Thanks to suomiy for this improvement!_\n\n### Realms: Automatically set up Kerberos keytab for Cockpit web server\n\nWhen joining a FreeIPA domain, Cockpit now automatically sets up Kerberos\n[Single Sign-On](https://cockpit-project.org/guide/latest/sso.html) for its web\nserver. With that, users with a valid kerberos ticket (from `kinit`) will be\nlogged into Cockpit without having to go through the login page.\n\n### Numbers now get formatted correctly for the selected language\n\nNumbers like disk sizes or network bandwidth usages are now shown with the\ncorrect decimal separator for the current browser language.\n\n### Try it out\n\nCockpit 166 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/166)\n * [Fedora 27](https://bodhi.fedoraproject.org/updates/cockpit-166-1.fc27)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-166-1.fc28)\n"
  },
  {
    "path": "_posts/2018-05-02-cockpit-167.md",
    "content": "---\ntitle: Cockpit 167\nauthor: pitti\ndate: 2018-05-02 14:00\ntags: cockpit linux\nslug: cockpit-167\ncategory: release\nsummary: Cockpit with new Firewall UI\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 167.\n\n### Networking: Add Firewall Configuration\n\nThe Networking page now displays the firewall status using\n[firewalld](https://www.firewalld.org/). Services and ports can be configured\non the new new \"Allowed Services\" details page.\n\nSee it in action:\n\n<iframe width=\"960\" height=\"720\" src=\"https://www.youtube.com/embed/yR5riNcIDbc?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Kubernetes: Show KubeVirt Registry Disks\n\n[Registry Disks](https://github.com/kubevirt/kubevirt/blob/master/docs/container-register-disks.md) are a new feature of\n[KubeVirt](http://www.kubevirt.io/) to distribute Virtual Machine disk images\nthrough a container registry. The \"Disks\" tab in the Kubernetes cluster's\n\"Virtual Machines\" overview now shows these:\n\n![KubeVirt Registry Disks](/images/kubernetes-registry-disks.png)\n\n_Thanks to Marek Libra for this improvement!_\n\n### Try it out\n\nCockpit 167 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/167)\n * [Fedora 27](https://bodhi.fedoraproject.org/updates/cockpit-167-1.fc27)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-167-1.fc28)\n"
  },
  {
    "path": "_posts/2018-05-16-cockpit-168.md",
    "content": "---\ntitle: Cockpit 168\nauthor: pitti\ndate: 2018-05-16 11:00\ntags: cockpit linux\nslug: cockpit-168\ncategory: release\nsummary: Cockpit with improved root privilege check\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 168.\n\n### Improve checks for root privilege availability\n\nMany actions, like joining an IPA domain or rebooting, can only be performed by\nan administrator (`root` user).\n\nCockpit previously checked if the user was a member of the `wheel` (used in\nRed Hat Enterprise Linux, CentOS, and Fedora) or `sudo` (used in Debian and\nUbuntu) groups to enable these actions. Simple group checking was insufficient,\nas different group names are used by other operating systems and configurations,\nor a system might be set up to rely on custom user-based sudo rules.\n\nCockpit no longer makes assumptions about special groups. Now, Cockpit simply\nchecks if the user is capable of running commands as `root`.\n\nAs a result of this fix, privileged operations now work by default with\n[FreeIPA](https://freeipa.org/), which uses the `admins@domain.name` group.\n\n### Try it out\n\nCockpit 168 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/168)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-168-1.fc28)\n\n*[IPA]: identity management system (\"Identity, Policy, Audit\")\n"
  },
  {
    "path": "_posts/2018-05-28-sso-oauth.md",
    "content": "---\ntitle: Seamless single-sign-on\nauthor: mvo\ndate: 2018-05-28 10:00\ntags: cockpit\nslug: sso-oauth\ncategory: blog\n---\n\n## Beyond a \"single pane of glass\"\n\nOrganizations who use several machines often run management display software in an attempt to integrate all infrastructure. [ManageIQ](http://manageiq.org/) and [Foreman](https://www.theforeman.org/) are great examples of this kind of software.\n\nManaging machines from the outside is usually adequate, but sometimes it's best to log into the machine itself and have a look around. Cockpit excels in this task. In fact, both ManageIQ and Foreman have Cockpit integration built-in.\n\n\n## Seamless single-sign-on\n\nMachine management software already has administrative access over the machines (both virtual and on bare metal), so there should not be a need to type credentials a second time.\n\nIndeed, ManageIQ currently opens Cockpit in a seamless manner, using [OAuth](https://en.wikipedia.org/wiki/OAuth) and external authentication helpers, all without requiring additional username and passwords.\n\nForeman currently does not have a seamless handover; it simply provides a standard link. As a result, when Foreman opens Cockpit, you're greeted with the log in page.\n\n## How can we improve Foreman?\n\nIt would be ideal for Foreman to also have seamless Cockpit integration.\n\n- As a first step, I have written a prototype based on what I have figured out so far in [a `seamless-cockpit` git repo](https://github.com/mvollmer/seamless-cockpit).\n- Additionally, I have also written a version that uses a reverse proxy on [the `nginxed` branch](https://github.com/mvollmer/seamless-cockpit/tree/nginxed). This approach is altogether nicer &mdash; but, before it works, we need to [fix a Cockpit bug (#9237)](https://github.com/cockpit-project/cockpit/pull/9237){:title=\"ws: Also strip query from original_path\"}.\n\n## Test it out\n\nIf you are using Foreman to manage your machines and would seamless credentials handover, we welcome you to try out the above code &mdash; and please let us know how it works for you!\n\n*[single pane of glass]: console that provides high-level management of multiple machines, also known as a \"single-pane view\"\n*[repo]: repository\n"
  },
  {
    "path": "_posts/2018-05-30-cockpit-169.md",
    "content": "---\ntitle: Cockpit 169\nauthor: pitti\ndate: 2018-05-30\ntags: cockpit linux\nslug: cockpit-169\ncategory: release\nsummary: Cockpit with NFS, FreeIPA, and systemd improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 169.\n\n### Storage: Offer installation of NFS client support\n\nThe \"NFS Mounts\" pane on the Storage page now shows an \"Install NFS Support\"\nbutton if the necessary packages are not already available:\n\n<iframe width=\"960\" height=\"720\" src=\"https://www.youtube.com/embed/Gaioqm7sLEo?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### System: Request FreeIPA SSL certificate for Cockpit's web server\n\nWhen enrolling into a [FreeIPA](https://freeipa.org/) domain, an SSL\ncertificate is requested from the IPA server and stored in\n`/etc/cockpit/ws-certs.d/10-ipa.cert`. Cockpit's web server will then use that\ncertificate instead of the default self-signed one.  The IPA server's\ncertificate authority is trusted by default and accepted by web browsers,\nOpenSSL, curl, and other network clients.\n\n### Services: Show unit relationships\n\nThe details of a systemd service now shows dependency, ordering, and other\nrelationships to units:\n\n![Services relationships](/images/services-relationships.png)\n\n### Provide motd help about how to access cockpit\n\nCockpit now provides an `/etc/motd.d/cockpit`\n[motd](https://linux.die.net/man/5/motd) message that explains how to enable\nand start Cockpit if it's not running, or how to access it if it is running.\n\nThis requires [PAM 1.3.1](https://github.com/linux-pam/linux-pam/releases/tag/v1.3.1)\nand enabling the `pam_motd` module:\n\n    session     optional      pam_motd.so\n\n### Try it out\n\nCockpit 169 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/169)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-169-1.fc28)\n\n*[NFS]: Network File System\n*[IPA]: identity management system (\"Identity, Policy, Audit\")\n*[motd]: message of the day\n"
  },
  {
    "path": "_posts/2018-06-13-cockpit-170.md",
    "content": "---\ntitle: Cockpit 170\nauthor: pitti\ndate: 2018-06-13\ntags: cockpit linux\nslug: cockpit-170\ncategory: release\nsummary: Cockpit with many bug fixes\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 170.\n\n### Software Updates: Layout rework\n\nThe Software Updates page has improved mobile browser support.\n\n![Updates Mobile](/images/updates-mobile.png)\n\nOn desktop browsers, the updates list avoids line breaks in the version column.\nVersions become truncated when there's not enough room to display the complete\nstring. Hovering over the shortened string shows the complete version.\n\n![Updates Truncating Version](/images/updates-version-truncated.png)\n\n### oVirt: Use authenticated libvirt connection by default\n\nThe [oVirt](https://www.ovirt.org/) version of the Machines page now uses a\nTLS-enabled libvirt connection URI instead of `qemu:///`. This enables libvirt\noperations that require authentication. One common example is sending an NMI.\n\nA machines-ovirt.config file with a `VIRSH_CONNECTION_URI` option may override\nthe connection address.\n\n_Thanks to Sharon Gratch for this improvement!_\n\n### Try it out\n\nCockpit 170 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/170)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-170-1.fc28)\n\n*[TLS]: Transport Layer Security\n*[NMI]: Non-Maskable Interrupt\n"
  },
  {
    "path": "_posts/2018-06-27-cockpit-171.md",
    "content": "---\ntitle: Cockpit 171\nauthor: pitti\ndate: 2018-06-27\ntags: cockpit linux\nslug: cockpit-171\ncategory: release\nsummary: Cockpit with VM/Kubevirt improvements, permission checks, and time localization\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 171.\n\n### Machines: Add virtual CPU configuration\n\nThe Machines page can now flexibly configure the number and layout of virtual CPUs:\n\n![Machines vCPU](/images/machines-vcpu-config.png)\n\nWhen changing the values for an already running VM, they become effective after\nstopping and restarting it.\n\n_Thanks to Bohdan Iakymets!_\n\n### Kubernetes: Add KubeVirt pod metrics\n\nThe details page of a KubeVirt VM now shows the current CPU, memory, and\nnetwork usage. This is similar to the libvirt VM on the Machines page.\n\n![Kubevirt Pod Metrics](/images/kubernetes-kubevirt-pod-metrics.png)\n\n_Thanks to suomiy_!\n\n### Docker: Show container volumes\n\nThe details page of a running Docker container now shows its volumes and their\nmode (like \"read only\"):\n\n![Docker Volumes](/images/docker-volumes-list.png)\n\n_Thanks to Katerina Koukiou!_\n\n### Fix broken actions for non-administrators\n\nThe tuned, system time, and host name links on the System page, as well as the\nunit and service buttons on the Services page now check if the user is actually\nallowed to carry out the action. If not, the elements now get disabled and show\na proper tooltip.\n\n![System tuned permission check](/images/system-tuned-permission.png)\n\n### Networking: Handle non-running NetworkManager\n\nThe Networking page now hides the non-functional network graphs and action\nbuttons while NetworkManager is not running, and shows an appropriate\nnotification. If NetworkManager is enabled, this usually indicates a crash or\notherwise unexpected situation:\n\n![Enabled stopped NetworkManager](/images/network-nm-stopped-enabled.png)\n\nIf NetworkManager is disabled, this usually just means that some other\nsoftware manages the network, or that this might be a fresh installation where\nNetworkManager is not configured yet:\n\n![Disabled stopped NetworkManager](/images/network-nm-stopped-disabled.png)\n\n### Accounts: User role improvements\n\nThe Accounts page now offers adding an \"Image Builder\" role to a user, which\nputs that user into the [weldr](http://weldr.io/) Unix group. It also points\nout that this does not become immediately effective but only applies to new\nlogins:\n\n![Account roles](/images/accounts-weldr-notification.png)\n\n### Localize times\n\nDates and times on all affected pages (System, Storage, and Docker) now use the\nformat matching the selected Display Language instead of the U.S.format.\n\n![Time stamp localization](/images/moment-i18n.png)\n\n### Try it out\n\nCockpit 171 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/171)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-171-1.fc28)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2018-07-11-cockpit-172.md",
    "content": "---\ntitle: Cockpit 172\nauthor: pitti\ndate: 2018-07-11\ntags: cockpit linux\nslug: cockpit-172\ncategory: release\nsummary: Cockpit with on-demand PCP install, flow control, and Python 3 support\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 172.\n\n### System: Offer installation of PCP\n\nThe System page now shows an \"Enable persistent metrics…\" link if the\n[PCP](https://pcp.io/) package is not installed. This is similar to the\non-demand installation of the NFS client packages in\n[Cockpit 169](https://cockpit-project.org/blog/cockpit-169.html).\n\n![Install PCP on demand](/images/pcp-install-on-demand.png)\n\n### Software Updates: Improve layout in mobile mode\n\nThe Software Updates page improves spacing and layout in small browser windows\nand mobile browsers:\n\n![PackageKit mobile mode](/images/packagekit-mobile-optimization.png)\n\n\n### Remove ability to drop privileges from navigation bar\n\nBefore this release, Cockpit showed a “Locked” or “Unlocked” status in the\nnavigation bar. It reflected the “Reuse my password for privileged tasks”\ncheckbox on the login page. Clicking on “Unlocked” would lock the interface and\ndrop administrator capabilities.\n\nIn general, the capability downgrade feature is not well supported across\nCockpit. Most pages do not respond well to privilege changes.\n\nA non-clickable administrative privilege badge (“Privileged”) replaces the old\ninteractive locked/unlocked status.\n\nThe ability to start cockpit without escalating privileges remains on the login\nscreen. Dropping privileges at runtime is still available in the user menu,\nunder \"Authentication\".\n\n![Privilege status](/images/cockpit-drop-privileges.png)\n\n### Introduce flow control for all channels\n\nThe Cockpit API now has flow control to reduce buffering, improve memory usage,\nand make the user interface more responsive.\n\nThird-party Cockpit extensions may use the API to transfer large amounts of\ndata.\n\nA notable example: [Welder](https://github.com/weldr/welder-web) downloads\ncustomized operating system from remote machines. Without flow control, Welder\nwould become unresponsive and use large amounts of memory.\n\n### Python 3 support\n\nCockpit, along with all unit tests and most integration tests, now supports\nPython 3. Building with Python 2 still works, but it is now deprecated.\n\n### Try it out\n\nCockpit 172 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/172)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-172-1.fc28)\n\n*[PCP]: Performance Co-Pilot\n*[API]: Application Programming Interface\n"
  },
  {
    "path": "_posts/2018-07-25-cockpit-173.md",
    "content": "---\ntitle: Cockpit 173\nauthor: pitti\ndate: 2018-07-25\ntags: cockpit linux\nslug: cockpit-173\ncategory: release\nsummary: Cockpit with on-demand VDO install and VM disk creation\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 173.\n\n### Storage: Offer installation of VDO\n\nThe Storage page now shows an \"Install VDO support\" link if the\n[VDO](https://github.com/dm-vdo/vdo) package is not installed. This is similar\nto the on-demand installation of the NFS client packages in\n[Cockpit 169](https://cockpit-project.org/blog/cockpit-169.html).\n\n![Install VDO on demand](/images/vdo-install-on-demand.png)\n\n### Machines: Add disks to a virtual machine\n\nThe \"Disks\" tab of a virtual machine now has an \"Add Disk\" button. Using\nthis new feature, it's possible to create a virtual disk in a\n[libvirt storage pool](https://libvirt.org/storage.html) or attach an existing disk.\n\n![Machines Add Disk](/images/machines-add-disk.png)\n\n_Thanks to Marek Libra!_\n\n### Try it out\n\nCockpit 173 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/173)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-173-1.fc28)\n\n*[VDO]: Virtual Data Optimizer\n"
  },
  {
    "path": "_posts/2018-08-01-cockpit-174.md",
    "content": "---\ntitle: Cockpit 174\nauthor: Gundersanne\ndate: 2018-08-01\ntags: cockpit linux\nslug: cockpit-174\ncategory: release\nsummary: VM detail page for kubernetes, realmd install on demand\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 174.\n\n### Kubernetes: VM detail page\n\nVirtual machines now have a details page. On the Machines page, click a VM to\nsee extended information.\n\n![Kubernets VM detail](/images/kubernetes-vm-detail.png)\n\n_Thanks to suomiy!_\n\n### Realmd: Install on demand\n\nThe [realmd](https://www.freedesktop.org/software/realmd/) system service\nprovides network authentication and domain membership. If realmd is not already\ninstalled, the System page now shows a link for an on-demand installation,\nsimilar to NFS support in [Cockpit\n169](https://cockpit-project.org/blog/cockpit-169.html).\n\n![Install realmd on demand](/images/realmd-install-on-demand.png)\n\n### Try it out\n\nCockpit 174 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/174)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-174-1.fc28)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2018-08-08-cockpit-175.md",
    "content": "---\ntitle: Cockpit 175\nauthor: mvo\ndate: 2018-08-08\ntags: cockpit linux\nslug: cockpit-175\ncategory: release\nsummary: Key management for encrypted devices\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 175.\n\n### Storage: Key management for encrypted devices\n\nThis release adds encrypted storage support for passphrases and\nnetwork keyservers.\n\nUnder the hood, LUKSv1 manages encrypted devices, allowing up to 8\ndifferent key \"slots\". Each slot may contain a passphrase or can\nprovide NBDE by binding to a [Tang](https://github.com/latchset/tang)\nserver using [Clevis](https://github.com/latchset/clevis).\n\nIn a future release, we're planning to add key groups and more\nauthentication types. Key groups bypass the 8 slot limitation and\nprovide complex authentication rules. Stay tuned!\n\n<iframe width=\"960\" height=\"720\" src=\"https://www.youtube.com/embed/GAPJVN6EEz4?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Try it out\n\nCockpit 175 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/175)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-175-1.fc28)\n\n*[NBDE]: network-bound disk encryption\n"
  },
  {
    "path": "_posts/2018-08-22-cockpit-176.md",
    "content": "---\ntitle: Cockpit 176\nauthor: Gundersanne\ndate: 2018-08-22\ntags: cockpit linux\nslug: cockpit-176\ncategory: release\nsummary: suggest browsers when browser is unsupported, auto-update backend install on demand\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly. Here are the release notes from version 176.\n\n### Login: Suggest other browser when browser is unsupported\n\nSome browsers are not supported, for instance because they don't support\nWebSockets. Cockpit now shows a list of browsers which are known to work.\n\n![Suggest other browser when browser is\nunsupported](/images/login-suggest-browser-when-unsupported.png)\n\n### PackageKit: Install auto-updates backend on demand\n\nIf no auto-update backend is installed, the user will be prompted for\ninstallation when enabling auto-updates. Only systems where dnf-automatic is\navailable are currently supported.\n\n![Install auto-update backend on\ndemand](/images/packagekit-auto-updates-install-on-demand.png)\n\n### Try it out\n\nCockpit 176 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/176)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-176-1.fc28)\n"
  },
  {
    "path": "_posts/2018-09-05-cockpit-177.md",
    "content": "---\ntitle: Cockpit 177\nauthor: pitti\ndate: 2018-09-05\ntags: cockpit linux\nslug: cockpit-177\ncategory: release\nsummary: Cockpit with LUKSv2 support and FreeIPA ssh known hosts integration\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly. Here are the release notes from version 177.\n\n### Storage: Support LUKS v2\n\nCockpit's Storage page can now create, lock, unlock, resize, and otherwise\nconfigure encrypted devices using the [LUKS\nv2](https://www.saout.de/pipermail/dm-crypt/2017-December/005771.html) format.\nThis includes support for LUKS v2 based Network Bound Disk Encryption (NBDE)\nthrough Clevis and Tang.\n\nThis new version of LUKS offers more flexible unlocking policies, stronger\ncryptography, and better compatibility with future changes.\n\n### Support centrally-managed SSH known hosts\n\n[FreeIPA](https://www.freeipa.org/) centrally manages the list and fingerprints\nof known SSH hosts. Cockpit now queries FreeIPA when to avoid fingerprint\nverification prompts of already-known hosts. This new flow now matches the\nbehavior of the `ssh` command line client.\n\nSSSD version 1.16.3 or 2.0 is required for improved remote host verification.\nWhen using earlier versions of SSSD, Cockpit will still not consider\ncentrally-managed known hosts.\n\n### Drop support for Internet Explorer\n\nOpening Cockpit in Microsoft Internet Explorer now shows the \"Unsupported\nBrowser\" page.\n\nFeature detection is used to determine if a browser is supported. Cockpit now\nrequires additional web technologies introduced in all modern browsers between\n2012 - 2015.\n\nWhen using Windows, please use Edge, the direct successor to Internet Explorer,\nor any other modern browser to use Cockpit.\n\nSpecific minimum versions of Firefox, Chrome, Edge, Safari, and Opera are\nlisted on [the running page of the Cockpit website](https://cockpit-project.org/running.html).\nAny browser with modern web support released in the past several years should\nwork well with Cockpit.\n\n### Try it out\n\nCockpit 177 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/177)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-177-1.fc28)\n"
  },
  {
    "path": "_posts/2018-09-13-is-cockpit-secure.md",
    "content": "---\ntitle: Is Cockpit Secure?\ndate: 2018-09-13 10:00\ncategory: blog\ntags: cockpit\nslug: is-cockpit-secure\n---\n\nSecurity is vital to your Linux systems. It's not a binary thing though.\nDepending on your requirements you end up choosing a level of security that\nstill allows you and your systems to accomplish what they need to do.\n\nHere's info about [Cockpit's](http://cockpit-project.org/) security, to help\nyou make those choices. You'll find not only has Cockpit got a solid security\nstory, but you can use it in all sorts of different ways depending on what\nkind of security your systems need.\n\n## Cockpit is a Linux session in your browser\n\nLet's start by stacking the deck against Cockpit. First off it's important to\nremember that Cockpit is actually an alternative Linux session ... along side X11,\nSSH and VT logins. It's a session in the [PAM](http://www.linux-pam.org/),\n[logind](https://www.freedesktop.org/wiki/Software/systemd/logind/), TTY,\n[SELinux](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Security-Enhanced_Linux/sect-Security-Enhanced_Linux-Confining_Users-Confining_Existing_Linux_Users_semanage_login.html)\n and other senses.\nThe logged in browser and the javascript code it is running can interact directly\nwith the system as part of that session.\n\nTry this out if you want. [Log into Cockpit](http://cockpit-project.org/running.html),\nand pop up the Javascript console by pressing *Ctrl-Shift-J* in your browser. Now type\ncommands like the following:\n\n    > zz = cockpit.spawn([\"id\"])\n    > proxy = cockpit.dbus(\"org.freedesktop.hostname1\").proxy()\n    > proxy.KernelName\n\nPretty cool, huh. And that's why Cockpit can be such a powerful and quick way to build\nLinux system admin interfaces.\n\n## But are browsers secure?\n\nBut can we trust browsers with your security? Firefox is about\n[15 million lines of code](https://www.openhub.net/p/firefox/analyses/latest/languages_summary)\nthat all have to work together, and after looking at the list of\n[security updates](https://www.mozilla.org/en-US/security/known-vulnerabilities/firefox/)\nyou gotta think about what that means for your security.\n\nAny management system with a browser interface requires a secure browser.\nThat includes\n[Satellite](https://www.redhat.com/en/technologies/management/satellite),\n[Tower](https://www.ansible.com/tower),\n[Foreman](https://www.theforeman.org/),\n[Landscape](https://landscape.canonical.com/),\n[CloudForms](https://www.redhat.com/en/technologies/management/cloudforms),\n[cPanel](https://cpanel.com/) and more. If anything like this interacts with\nyour systems, then security bugs in browsers have a direct effect on your\nsystem security.\n\nSecondly take a look at any browser based tools that were involved in the\ncreation or curation of the software installed on your system, including\ntools used by your Linux distribution.\n\nIf your security requirements are strict and you must avoid browsers at all\ncosts, then be sure to audit all possible places that browsers were involved\nin what's running on your systems. It's harder than you think.\n\nUnless your system is extremely isolated and hand crafted, it turns out that\nbrowsers are already highly involved in many security paths for your systems.\nCockpit does not change this situation significantly.\n\n## Cockpit has no special privileges\n\nBack to Cockpit. What does that session look like? Cockpit itself has no\nspecial privileges. The credentials of the logged in user start a login\nsession, and Cockpit can perform exactly the tasks that the logged in user\nhas access to. It has no more or less permissions.\n\nYou can examine anything about Cockpit security. Log into Cockpit, open the\n*Terminal* page and run commands like the following:\n\n    $ id\n    uid=1000(stef) gid=1000(stef) groups=1000(stef),10(wheel)\n    $ cat /etc/shadow\n    cat: /etc/shadow: Permission denied\n\nIf you logged in as a non-root user, you'll find that Cockpit has no\nelevated privileges on the system. Try this out via Javascript by\npressing *Ctrl-Shift-J* in Cockpit. Now type commands like\nthe following:\n\n    > zz = cockpit.spawn([\"id\"])\n    > zz = cockpit.spawn([\"cat\", \"/etc/shadow\"])\n\n## Escalating privileges\n\nSo if Cockpit only has the privileges of the authenticated user, how does\nit perform admin tasks? Well obviously one could log in as root, and the logged\nin session would have all capabilities and access to the system.\n\nBut logging in directly as root is a poor security practice. Cockpit supports\nescalating privileges via [sudo](https://www.sudo.ws/) and/or\n[polkit](https://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html).\nIf, and only if, the logged in user has permission to use sudo or polkit to\nescalate privileges.\n\nOn the login screen you'll see a checkbox to enable privilege escalation:\n\n![Reuse my password for privileged tasks](/images/cockpit-reuse-password.png)\n\nThis checkbox allows Cockpit to use your login password to escalate\nprivileges via sudo and/or polkit when necessary to perform admin\ntasks. This is as if you log in with SSH and then used ```sudo -s```\nor similar to perform some admin tasks. Try the following command once\nyou've logged in with the checkbox:\n\n    $ pkexec bash\n    # id\n    # uid=0(root) gid=0(root) groups=0(root)\n\nYou can track the state of this privilege escalation in the upper right\ncorner of Cockpit:\n\n![Unlocked option](/images/cockpit-unlocked.png)\n\n## Principle of Least Privilege\n\nA good security practice is to run services, processes or tools with\nthe least amount of security privilege necessary to perform their task.\nTo accomplish this, Cockpit is split up in multiple components, each of\nwhich runs with as little access to the system as possible.\n\nOn RHEL, Fedora, Ubuntu, Debian and any other distro that we distribute\nCockpit for ... we test and make sure that this privilege separation is\nin effect: Including correct SELinux policies, and unprivileged unix users.\n\nHere's some of the privilege separation described:\n\n    stef        9690  ...  Sl  06:08  0:00 cockpit-bridge\n\nThe ```cockpit-bridge``` is the part of Cockpit that runs in the login session.\nIt is similar to a login shell, in that it runs with the privileges and security\ncontext of the logged in user. In the above case I logged in as the ```stef``` user.\nIf you checked the *Reuse my password for privileged tasks* option on the login\nscreen, you might also see this process running as ```root``` in which case\n```pkexec``` or ```sudo``` was used (see above) to escalate privileges.\n\n    root        9947  ...  S   06:10  0:00 /usr/libexec/cockpit-session\n\nThe ```cockpit-session``` part of Cockpit is a small binary that performs\nauthentication for the logged in user. It uses [PAM](http://www.linux-pam.org/)\nor [GSSAPI](https://web.mit.edu/kerberos/krb5-devel/doc/appdev/gssapi.html)\nto perform that authentication.  ```cockpit-session``` is installed setuid,\nin such a way that it can be launched by the unprivileged ```cockpit-ws``` user\n(see below) during user login. This process performs limited tasks, and has a\nrestrictive SELinux ```cockpit_session_t``` context. Lastly is a reasonably short\nprogram written in plain C so it is easier to audit.\n\n    cockpit-ws 11295  ...  Ssl 06:14  0:00 /usr/libexec/cockpit-ws\n\nThis is the component that listens on the network. It hands off\nauthentication information to the ```cockpit-session``` to perform a login\nand launch cockpit-bridge. The ```cockpit-ws``` binary runs as an\nunprivileged unix ```cockpit-ws``` user, with a restrictive\nSELinux ```cockpit_ws_t``` policy.\n\n## Security Policy within the browser\n\nCockpit runs javascript code from the system it's logged into. Obviously that\ncode is protected by the standard\n[Same Origin Policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy)\nthat web browsers adhere to.\n\nBut how does Cockpit protect against bugs in the code. How can we be sure that\nonly the javascript code installed on the system is run, and bugs are not\nexploited to run code trojaned into logs or other data loaded by Cockpit?\n\nBrowsers have a security technology called\n[Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)\nwhich is sorta like SELinux or Apparmor in your browser. The policy describes\nexactly where code can be loaded, what can be run, and what sorts of connections\ncan be made by the browser.\n\nIn Cockpit's case we send a strict ```Content-Security-Policy``` header that\nonly allows code installed in Cockpit packages on the logged into system to be run.\nAlthough individual parts of Cockpit can\n[override this default](http://cockpit-project.org/guide/latest/packages.html#package-manifest),\nit's rarely done. The default security policy looks like this:\n\n     Content-Security-Policy: default-src 'self' connect-src 'self' ws: wss:\n\nA failure of *Content Security Policy* will look something like this in your browser's\njavascript console:\n\n![Content Security Policy denial](/images/csp-denied.png)\n\n## Security of the network facing TCP port\n\nCockpit typically listens on TCP port 9090 on a host. This is the\n[websm or \"Web Systems Manager\" network port](https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.txt).\nOpening a network facing port has security risks. Both the exposed surface\narea and stuff listening on that port, in this case ```cockpit-ws```, are risky.\n\nIf this is an issue for your systems, you can use Cockpit over the SSH port\nalready have open. But wait, how does that work? Browsers don't natively speak\nthe SSH protocol, and getting a browser to do so would be an impressive party trick.\n\nTo use Cockpit over SSH, use a *bastion host model*: Start ```cockpit-ws``` on port 9090\non a single host, perhaps even your localhost. Connect to that with your\nbrowser and use that first Cockpit instance to log into to Cockpit on other machines\nothers over SSH. If you draw it up, it looks something like this:\n\n![Multi-host Transport](/images/transport-multi-small.png)\n\n[Atomic Host includes Cockpit by default](http://www.projectatomic.io/docs/cockpit/),\nin this way. Atomic Host doesn't include ```cockpit-ws``` or open port 9090 by default,\nbut expects you to connect from another running Cockpit instance over port 22. There's\nalso the possibility to run ```cockpit-ws``` as a container to accomplish this.\n\nWhen you're trying this out in real life, specify an alternate server on the Cockpit\nlogin screen. The SSH protocol will be used to connect to it:\n\n![Login Alternate Server](/images/cockpit-login-alternate.png)\n\nOr you can add other machines to a local dashboard, and Cockpit will connect to\nthem via SSH. Even usage of SSH key based authentication works great:\n\n<iframe width=\"853\" height=\"480\" src=\"https://www.youtube.com/embed/Ye5YlVNXC9w\" frameborder=\"0\" allowfullscreen></iframe>\n\nObviously, when you use Cockpit over SSH, it's not just a real Linux session,\nit's also an SSH session in every way. Try it out.\n\n## But what about the Web Server\n\nCockpit doesn't use a web server like Apache, NGINX or Lightttp. It doesn't use an\napplication server like Tomcat. So by and large the security concerns related to\ndeploying those projects do not apply here. Cockpit implements just enough of an HTTP\nserver to serve the Cockpit application to your browser.\n\nThis tiny HTTP server is included in the ```cockpit-ws``` process, and protected\nvia strong SELinux and unix privilege separation.\n\nBut if you're environment is uncomfortable with use of the Cockpit built-in HTTP server,\nenvironments use Cockpit over SSH as seen in the section above.\n\n## In conclusion\n\nI could go further about how Cockpit uses\n[Kerberos to do single sign on](http://cockpit-project.org/guide/latest/sso.html)\nor [how it works with certificates](http://cockpit-project.org/guide/latest/https.html)\nor how you can even bring\n[your own authentication tool](https://raw.githubusercontent.com/cockpit-project/cockpit/master/doc/authentication.md)\nto replace ```cockpit-session```. and much, much more.\n\nBut suffice it to say, that Cockpit's security is well thought out, layered and\nmatches that of Linux in general.\n"
  },
  {
    "path": "_posts/2018-09-19-cockpit-178.md",
    "content": "---\ntitle: Cockpit 178\nauthor: mvo\ndate: 2018-09-19\ntags: cockpit linux\nslug: cockpit-178\ncategory: release\nsummary: Fixed crashers and dropped KubeVirt support\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 178.\n\n### KubeVirt support has been removed\n\nCockpit ships `cockpit-kubernetes` for managing Kubernetes and\nOpenShift deployments. Since its introduction, important points have\ncome to light:\n\n- The OpenShift Console is adding support for\n[KubeVirt](http://kubevirt.io/). It will become _the_ place for\nmanaging KubeVirt-based VMs that run in OpenShift.\n\n- `cockpit-kubernetes` has been in maintenance mode for a while. It\nis difficult to support, as it uses a very old version of Angular.\n\n- We haven't been able to build a recent kubevirt-enabled OpenShift image in four months. (Issues [#9479](https://github.com/cockpit-project/cockpit/issues/9479) & [#9638](https://github.com/cockpit-project/cockpit/pull/9638).) As a result, it is impossible to test recent KubeVirt versions.\n\n- Community interest has waned on KubeVirt support in Cockpit.\n\nAs a result, we have removed KubeVirt support from\n`cockpit-kubernetes` in this release.  In the future, we will likely\nremove all of `cockpit-kubernetes`.\n\n#### Migration path\n\nFedora 29 will keep `cockpit-kubernetes`, but it will be dropped from the \"rawhide\" rolling release. (Rawhide is the name of the unstable version of Fedora. For the immediate future, it is currently what will become Fedora 30). Thus, `cockpit-kubernetes` will still be supported for approximately the next year-and-a-half.\n\nDuring this time, the Cockpit team suggests migrating to [OpenShift Console's native KubeVirt support](https://blog.openshift.com/a-first-look-at-kubevirt/).\n\n### Stabilization & security fixes\n\nCockpit 178 also includes several minor stabilization improvements and [a denial of service security fix](https://github.com/cockpit-project/cockpit/issues/10003).\n\n### Try it out\n\nCockpit 178 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/178)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-178-1.fc28)\n"
  },
  {
    "path": "_posts/2018-10-04-cockpit-179.md",
    "content": "---\ntitle: Cockpit 179\nauthor: Gundersanne\ndate: 2018-10-04\ntags: cockpit linux\nslug: cockpit-179\ncategory: release\nsummary: Cockpit with Machines improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 179.\n\n### Machines: Detach disk support\n\nWhen using the libvirt D-Bus provider, the Machines page now supports detaching\na disk from VMs.\n\n![Detach disk](/images/machines-detach-disk.png)\n\n_Thanks to Katerina Koukiou for this improvement!_\n\n### Machines: Offer cockpit-machines as Application\n\nThis Cockpit version adds AppStream metadata for its own `cockpit-machines`\npackage (which is not installed by default). Once `appstream-data` gets updated\nagain in Fedora, cockpit-machines will appear on the Applications page as an available\nextension.\n\n![Cockpit-machines app](/images/apps-cockpit-machines.png)\n\n### Try it out\n\nCockpit 179 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/179)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-179-1.fc28)\n\n*[VM]: virtual machine\n*[VMs]: virtual machines\n"
  },
  {
    "path": "_posts/2018-10-04-cockpit-180.md",
    "content": "---\ntitle: Cockpit 180\nauthor: pitti\ndate: 2018-10-04\ntags: cockpit linux\nslug: cockpit-180\ncategory: release\nsummary: Cockpit with ssh and virtual machines improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 180.\n\n### Move to ssh SHA256 fingerprints\n\nUntil version 179, Cockpit has shown MD5 based SSH host key fingerprints when\nconnecting to unknown remote machines.\n\nThe \"ssh\" command line program hasn't shown MD5 fingerprints in a long time,\nbut uses SHA1 and SHA256. MD5 and SHA1 are cryptographically weak, and using\nthem is not allowed when running in [FIPS mode](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/security_guide/sect-security_guide-federal_standards_and_regulations-federal_information_processing_standard).\n\nCockpit will now show SHA256 fingerprints when available:\n\n![ssh SHA256 fingerprints](/images/ssh-sha256-fingerprints.png)\n\nThis feature requires libssh 0.8, so it is only available on more recent\noperating system releases. MD5 fingerprints are being used on older ones.\n\n### Machines: Show error messages in the correct place\n\nIf there is an error with applying changes to a VM's networking configuration,\nthe error message is now shown in the correct (\"Networking\") tab:\n\n![Detach disk](/images/machines-network-errors.png)\n\nPreviously it was only shown in the \"Overview\" tab, and thus not immediately\nvisible.\n\n_Thanks to Katerina Koukiou for this improvement!_\n\n### Try it out\n\nCockpit 180 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/180)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-180-1.fc28)\n\n*[VM]: virtual machine\n*[FIPS]: Federal Information Processing Standard\n"
  },
  {
    "path": "_posts/2018-10-31-cockpit-181.md",
    "content": "---\ntitle: Cockpit 181\nauthor: mvo\ndate: 2018-10-31\ntags: cockpit linux\nslug: cockpit-181\ncategory: release\nsummary: ...\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 181.\n\n### System: Memory graph improvements\n\nThe appearance of memory and CPU graphs has been improved, and their\ncolors are more accessible.\n\n![Screenshot of the new memory graph](/images/memory-graph.png)\n\nMemory on Linux is often hard to understand and usually presented\nincorrectly in most tools, including Cockpit's memory graphs.\n\nThe new presentation of memory in Cockpit is aligned with the way\npeople think about how RAM is used. It now shows:\n\n1. the amount of RAM actively used by software\n2. the amount of RAM used for cache\n3. unused RAM\n4. swap\n\nOn Cockpit's overview, the memory graph displays only the value of\nactive RAM and has a separate, small area to indicate swap usage. The\ndetailed memory view also shows cache.\n\nWhy do we not show cache on the overview and de-emphaize it on the\ndetailed memory view? Linux stores often-used files in memory as cache\nto speed up performance. As cache is quickly reclaimed when needed,\nit's effectively available RAM. That's why Cockpit shows it a free\nspace, as Linux considers it free too.\n\nAdditional information on can be found on the website [Linux Ate My\nRAM](https://www.linuxatemyram.com/).\n\n### Machines: Edit network interfaces of virtual machines\n\nThe configuration of the network interfaces of a virtual machine can\nnow be changed in Cockpit.\n\n![screenshot of the NIC edit dialog](/images/nic-edit.png)\n\n### Update look of lists to match PatternFly\n\nLists have been refreshed to look and act more similarly to PatternFly,\ncomplete with a little animation when items are expanded.\n\n![animation of a PatternFly style list](/images/list-patternfly-update.gif)\n\n### Try it out\n\nCockpit 181 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/181)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-181-1.fc28)\n"
  },
  {
    "path": "_posts/2018-11-14-cockpit-182.md",
    "content": "---\ntitle: Cockpit 182\nauthor: Gundersanne\ndate: 2018-11-14\ntags: cockpit linux\nslug: cockpit-182\ncategory: release\nsummary: Cockpit with libvirt connection choice in VM creation and Software Updates improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 182.\n\n### Machines: Add libvirt connection choice in VM creation dialog\n\nThe VM creation dialog now offers different connections to libvirt. The options\nresult in either a user session or system URI.\n\n![Creation dialog connection\nchoice](/images/machines-libvirt-create-connection-choice.png)\n\n_Thanks to Katerina Koukiou for this improvement!_\n\n### Software Updates page improvements\n\nUpdate severity icons now have tooltips. The severity shown is equal to the\nseverity of the update with the highest severity among the available updates for\na package.\n\n![Software Updates severity tooltip](/images/packagekit-severity-tooltips.png)\n\nIf the system is not registered, the Software Updates page now always points\nthis out. This avoids confusion if there are available updates from third-party\nrepositories, but the system as a whole still does not receive updates.\n\n![Software Updates unregistered\nsystem](/images/packagekit-unregistered-system.png)\n\n### Try it out\n\nCockpit 182 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/182)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-182-1.fc28)\n * [Fedora 29](https://bodhi.fedoraproject.org/updates/cockpit-182-1.fc29)\n\n*[VM]: virtual machine\n"
  },
  {
    "path": "_posts/2018-11-28-cockpit-183.md",
    "content": "---\ntitle: Cockpit 183\nauthor: pitti\ndate: 2018-11-28\ntags: cockpit linux\nslug: cockpit-183\ncategory: release\nsummary: Cockpit with Machines, Kdump, and SSH improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 183.\n\n### Machines: Manage storage pools\n\nThe Machines page now shows existing VM storage pools, and can also create new\npools.  This currently supports pools on the local file system and on an NFS\nvolume.\n\n<iframe width=\"960\" height=\"540\" src=\"https://www.youtube.com/embed/7Lhw3coi1qE?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n_Thanks to Katerina Koukiou for this feature!_\n\n### Kernel Dump: Support non-local targets\n\nThe Kernel Dump page now recognizes all possible types of kdump locations in\n`/etc/kdump.conf`, such as raw disk devices or ext4 file systems. It can now\ngraphically configure SSH and NFS targets:\n\n![kdump remote locations](/images/kdump-remote-locations.png)\n\n### Respect SSH configuration\n\nWhen connecting to remote machines on the Login page or on the Dashboard,\nCockpit now respects the global (`/etc/ssh/ssh_config`) and user's\n(`~/.ssh/config`) SSH configuration files. As a result, host name aliases,\ndifferent settings for ports, users, private keys, or `ProxyCommand` now take\neffect.\n\nNow Cockpit's SSH connections are consistent with the `ssh` command line\nprogram.\n\n### Never send Content-Length with chunked encoding\n\nFor some HTTP requests, Cockpit's web server previously sent replies using\nchunked transfer encoding that contained a `Content-Length:` header field. This\nis forbidden by the [HTTP specification](https://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4)\nand caused problems with some proxies (such as the [cypress.io](https://www.cypress.io/) test framework).\n\nIf you use Cockpit behind a proxy (forward or reverse) or any other non-trivial\nweb server setup, and notice regressions with this version, please\n[report an issue](https://github.com/cockpit-project/cockpit/issues/new).\n\n### Try it out\n\nCockpit 183 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/183)\n * [Fedora 28](https://bodhi.fedoraproject.org/updates/cockpit-183-1.fc28)\n * [Fedora 29](https://bodhi.fedoraproject.org/updates/cockpit-183-1.fc29)\n\n*[VM]: Virtual Machine\n*[NFS]: Network File System\n*[SSH]: Secure Shell\n*[NFS]: Network File System\n"
  },
  {
    "path": "_posts/2018-12-12-cockpit-184.md",
    "content": "---\ntitle: Cockpit 184\nauthor: mvollmer\ndate: 2018-12-12\ntags: cockpit linux\nslug: cockpit-184\ncategory: release\nsummary: Cockpit with machines and storage improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 184.\n\n### Machines: Dialog and tab layout is now responsive\n\nThese UI elements now adjust their layout to small and mobile browser\nwindows.  This improvement will come to all dialogs in the near\nfuture.\n\n![Responsive layout](/images/machines-responsive-layout.png)\n\n### Storage: Filesystem labels are validated upfront\n\nThe names one can give to filesystems have some limits put on them,\nand Cockpit now knows about them and tells you if you violate them.\n\n![Filesystem label validation](/images/storage-label-validation.png)\n\nThis prevents possibly confusing error messages from the underlying\ntools, and it also prevents silent truncation.\n\n### Storage: Some mount options are prefilled when needed\n\nWhen configuring a filesystem to be mounted at boot, one has to give\nit the special \"_netdev\" option if the block device only becomes\navailable when the network is up. Cockpit will now prefill this option\nwhen it detects this case.\n\n<iframe width=\"960\" height=\"540\" src=\"https://www.youtube.com/embed/rMW5--h2omk?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\nThis is also used to deploy the [recommended workaround for the VDO\nboot problems](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/storage_administration_guide/vdo-quick-start).\n\n### Integration of Cockpit pages on the desktop\n\nFor some use cases it may be desirable to use a particular Cockpit\npage on a desktop, if a native application does not exist. This can be\ndone with the new \"cockpit-desktop\" tool, which runs a Cockpit web\nserver and a web browser (Webkit, Firefox, or Chromium/Chrome) in an\nisolated network namespace. This avoids having to enable Cockpit\nsystem-wide and having to log into it through the web browser again.\n\nThe cockpit-desktop tool may be used by system integrators or local\nadministrators through a standard [desktop\nlauncher](https://standards.freedesktop.org/desktop-entry-spec/latest/). Cockpit\nships no pre-defined launchers by itself.\n\n### Try it out\n\nCockpit 184 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/184)\n * [Fedora 29](https://bodhi.fedoraproject.org/updates/cockpit-184-1.fc29)\n"
  },
  {
    "path": "_posts/2019-01-09-cockpit-185.md",
    "content": "---\ntitle: Cockpit 185\nauthor: Gundersanne\ndate: 2019-01-09\ntags: cockpit linux\nslug: cockpit-185\ncategory: release\nsummary: Responsive dialogs and kubernetes containers included in docker page graphs\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 185.\n\n### Responsive dialogs\n\nDialogs on the Networking and KDump pages, as well as the password dialogs on\nthe Accounts page are now responsive.\n\n{:.side-by-side}\n![network bridge dialog screenshot](/images/network-bridge-dialog-responsive.png)\n![kdump crash dialog screenshot](/images/kdump-crash-dialog-responsive.png)\n![user password dialog screenshot](/images/users-password-dialog-responsive.png)\n\n### Docker: Include kubernetes containers in graphs\n\nKubernetes containers will now also be present in CPU/memory graphs.\n\n![Kubernetes containers in graphs](/images/docker-kubernetes-in-graphs.png){:.screenshot}\n\n### Try it out\n\nCockpit 185 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/185)\n * [Fedora 29](https://bodhi.fedoraproject.org/updates/cockpit-185-1.fc29)\n"
  },
  {
    "path": "_posts/2019-01-23-cockpit-186.md",
    "content": "---\ntitle: Cockpit 186\nauthor: Katerina Koukiou\ndate: 2019-01-23\ntags: cockpit linux\nslug: cockpit-186\ncategory: release\nsummary: Responsive system page and improvement in services page\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly. Here are the release notes from version 186.\n\n### Services: Redesign Services page\n\nDuring usability testing, we discovered the Service Details page was hard to\nunderstand for administrators with a non-Linux background. The page now\nuses neutral, well-known terminology. Additionally, action buttons are now next to service status.\n\n![services screenshot](/images/services-relayout.png)\n\n### Responsive System Overview page\n\nThe overview page layout has been improved and includes fixes for mobile\ndevices. This is part of an ongoing process to improve layout across all of\nCockpit.\n\n![system page screenshot](/images/system-page-responsive.png)\n\n### Try it out\n\nCockpit 186 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/186)\n * [Fedora 29](https://bodhi.fedoraproject.org/updates/cockpit-186-1.fc29)\n"
  },
  {
    "path": "_posts/2019-02-06-cockpit-187.md",
    "content": "---\ntitle: Cockpit 187\nauthor: mvollmer\ndate: 2019-02-06\ntags: cockpit linux\nslug: cockpit-187\ncategory: release\nsummary: Cockpit with machines and storage improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 187.\n\n### Machines: More operations for Storage Pools\n\nYou can now activate, deactivate, and delete the storage pools for\nyour virtual machines.\n\n![Storage pool operation](/images/storage-pools.png)\n\n### Domains: More information about the joined domain\n\nClicking on the name of the joined domain will now open a dialog with\nmore information about that domain.\n\n![Domain information](/images/domain-leave.png)\n\nYou can also leave the domain from this dialog.\n\n### Storage: The options for VDO volumes are explained\n\nWhen creating a VDO volume, the options are now explained with\ntooltips.\n\n![VDO options explained](/images/vdo-option-explainer.png)\n\n### Machines: Support for oVirt will be dropped in the future\n\nThe oVirt project is mostly stalled and thus we don't plan to invest\nmuch in Cockpit's oVirt support either.  Cockpit will keep the current\nsupport for oVirt in stable distributions, but will no longer provide\nit from Fedora 30 and RHEL 8 on.\n\n### Try it out\n\nCockpit 187 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/187)\n * [Fedora 29](https://bodhi.fedoraproject.org/updates/cockpit-187-1.fc29)\n"
  },
  {
    "path": "_posts/2019-02-20-cockpit-188.md",
    "content": "---\ntitle: Cockpit 188\nauthor: pitti\ndate: 2019-02-20\ntags: cockpit linux\nslug: cockpit-188\ncategory: release\nsummary: Cockpit with Machines and Terminal improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 188.\n\n### Machines: Show Storage Volume user\n\nThe volume details on the \"Storage Pool\" page now show which libvirt domains\n(virtual machines) use that volume.\n\n![Storage Volume User](/images/machines-storage-volume-usedby.png)\n\n### Machines: Autostart configuration\n\nThe VM details now have a new check box for enabling or disabling automatic\nstartup when the host boots.\n\n![Machines Autostart configuration](/images/machines-autostart-checkbox.png)\n\n_Thanks to Simon Kobyda for this feature!_\n\n### Terminal: Themes and context menu\n\nThe Terminal can now copy and paste text via the new context menu or by using\nkey combinations (Ctrl+Insert and Shift+Insert).\n\nYou can now chose between four colour themes: white-on-black (the default),\nblack-on-white, and light or dark [Solarized](https://en.wikipedia.org/wiki/Solarized_(color_scheme)).\n\n![Terminal theme and context menu](/images/terminal-context-menu.png)\n\n### Storage: Responsive dialogs\n\nAll dialogs on the Storage page now adjust their layout to small and mobile\nbrowser windows. This is part of an ongoing process to improve layout across\nall of Cockpit.\n\n![Mobile NFS mount dialog](/images/storage-new-nfs-mount-mobile.png)\n\n### Software Updates: Show three most recent updates\n\nThe Update History was redesigned to show the three most recent updates and a\npackage count. This design allows other information and features (such as\nsnapshots) to be integrated in the future.\n\n![Update history table](/images/sw-updates-history-table.png)\n\n### Try it out\n\nCockpit 188 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/188)\n * [Fedora 29](https://bodhi.fedoraproject.org/updates/cockpit-188-1.fc29)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2019-03-06-cockpit-189.md",
    "content": "---\ntitle: Cockpit 189\nauthor: Gundersanne\ndate: 2019-03-06\ntags: cockpit linux\nslug: cockpit-189\ncategory: release\nsummary: Cockpit with Machines and Services improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 189.\n\n### Machines: Import existing image\n\nYou can now choose an existing qcow image when creating an new VM. This will not\nrun an installer, but just import it into libvirt.\n\n![Create VM with existing image](/images/machines-existing-disk-image.png)\n\n### Machines: Show virtual networks\n\nShow the details and properties of virtual networks.\n\n![Virtual networks in machines](/images/machines-virtual-networks.png)\n\n_Thanks to Simon Kobyda for this feature!_\n\n### Services: Filtering of services\n\nServices can now be filtered using text. Results can be filtered additionally by\nname, description, and state.\n\nIn addition, service states have been merged into one list. The switcher buttons\nat the top have also been changed to tabs to make switching more obvious.\n\n![Service filter cockpit](/images/services-filtering-cockpit.png)\n\n### Try it out\n\nCockpit 189 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/189)\n * [Fedora 29](https://bodhi.fedoraproject.org/updates/cockpit-189-1.fc29)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/cockpit-189-1.fc30)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2019-03-22-cockpit-190.md",
    "content": "---\ntitle: Cockpit 190\nauthor: kkoukiou\ndate: 2019-03-22\ntags: cockpit linux\nslug: cockpit-190\ncategory: release\nsummary: Cockpit with new features in logs and machines\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 190.\n\n### Logs: Filter log entries by service\n\n![Filtering logs by service](/images/logs-filter-service-name.png)\n\nThe Logs page now allows you to only view the logs for a specific service.\n\n### Machines: Support for Pausing/Resuming VMs\n\n![Pause and Resume operations for VMs](/images/machines-pause-resume.png)\n\nYou can now pause a running VM or resume a paused a VM.\n\n_Thanks to Simon Kobyda for this feature!_\n\n### Machines: Make Autostart property of a Virtual Network configurable\n\n![Autostart property for Virtual Networks](/images/machines-virtual-network-autostart.png)\n\n_Thanks to Simon Kobyda for this feature!_\n\n### Machines: Support for creating VM with option to boot from PXE\n\nYou can now choose Network boot when creating a new VM. Supported sources are\nlibvirt Virtual Networks and host network devices used with\n[direct assignment](https://libvirt.org/formatdomain.html#elementsNICSDirect).\n\n![Create VM with Network boot](/images/machines-pxe-boot.png)\n\n### Accessibility improvements\n\nDropdowns in all pages are now properly accessible and allow keyboard navigation.\n\n### Try it out\n\nCockpit 190 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/190)\n * [Fedora 29](https://bodhi.fedoraproject.org/updates/cockpit-190-1.fc29)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/cockpit-190-1.fc30)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2019-04-03-cockpit-191.md",
    "content": "---\ntitle: Cockpit 191\nauthor: mvo\ndate: 2019-04-03\ntags: cockpit linux\nslug: cockpit-191\ncategory: release\nsummary: Cockpit with Machines and Networking improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 191.\n\n### Machines: iSCSI storage pools\n\nYou can now add an iSCSI target as a storage pool for your virtual\nmachines.\n\n![iSCSI storage pool](/images/machines-iscsi.png)\n\n### Machines: Better notifications\n\nNotifications about virtual machines have been streamlined and use a\ncommon presentation now.\n\n![Notifications](/images/machines-notifications.gif)\n\n### Network: Firewall supports custom ports\n\nIn addition to services, which represent a predefined set of ports,\nyou now can now open individual ports in the firewall by directly\nspecifying their numbers.\n\n![Firewall ports](/images/networking-ports.png)\n\n### System: CPU security mitigation\n\nCockpit can now help you with enabling certain security vulnerability\nmitigations, starting with the [nosmt option](https://access.redhat.com/security/vulnerabilities/L1TF).\n\n### Try it out\n\nCockpit 191 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/191)\n * [Fedora 29](https://bodhi.fedoraproject.org/updates/cockpit-191-1.fc29)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/cockpit-191-1.fc30)\n"
  },
  {
    "path": "_posts/2019-04-17-cockpit-192.md",
    "content": "---\ntitle: Cockpit 192\nauthor: pitti\ndate: 2019-04-17\ntags: cockpit linux\nslug: cockpit-192\ncategory: release\nsummary: Cockpit with Machines and translation improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 192.\n\n### Machines: Auto-detect guest operating system\n\nWhen creating a new VM, the \"OS Vendor\" and \"Operating System\" fields are now\nset automatically after specifying the installation sources for many vendors.\nThis uses the libvirt [osinfo-detect](https://libosinfo.org/) utility.\n\n![Machines OS auto-detection](/images/machines-os-autodetect.png)\n\n### Translation cleanup\n\nInstead of showing just a predetermined set of languages, the language dialog\nnow offers all available translations, ordered alphabetically, in their native\ntranslations:\n\n![New language dialog](/images/language-dialog-translated.png)\n\nAlso, translations with less than 50% completion coverage were removed.\n\n### Allow accounts with non-standard shells\n\nPreviously, logging into Cockpit was restricted to users who have a shell\nspecified in [/etc/shells](https://linux.die.net/man/5/shells), enforced\nthrough [`pam_shells`](https://linux.die.net/man/8/pam_shells). This was found\nto be too strict, and excludes users with e. g. the `tlog-rec-session` shell for\n[session recording](https://github.com/Scribery/tlog).\n\n\nCockpit now accepts shells that are unchangeable by non-administrastors, yet\nstill allow a user to log in. However, shells which do not allow a user to log\nin, such as /sbin/nologin or /bin/false, may still be used to deny access to\nCockpit.\n\n### Try it out\n\nCockpit 192 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/192)\n * [Fedora 29](https://bodhi.fedoraproject.org/updates/cockpit-192-1.fc29)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/cockpit-192-1.fc30)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2019-05-02-cockpit-193.md",
    "content": "---\ntitle: Cockpit 193\nauthor: Gundersanne\ndate: 2019-05-02\ntags: cockpit linux\nslug: cockpit-193\ncategory: release\nsummary: Machine and storage page improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly. Here are the release notes from version 193.\n\n### Machines: iSCSI direct storage pools\n\nYou can now add an iSCSI direct target as a storage pool for your virtual\nmachines.\n\n![iSCSI direct storage pool](/images/machines-iscsi-direct.png)\n\n_Thanks to Han Han for this improvement!_\n\n### Storage: The \"Format\" button is no longer hidden\n\nThe button to format a block device used to be in the tab that describes the\ncurrent content of the device, such as in the \"Filesystem\" or \"Physical Volume\"\ntab. Now it is in the header row where it should be easier to find.\n\n![Storage format block device button](/images/storage-format-button.png)\n\n### Storage: Improve performance with many block devices\n\nCockpit now survives much better when there are thousands of block devices on\nthe Storage page.\n\n### Try it out\n\nCockpit 193 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/193)\n * [Fedora 29](https://bodhi.fedoraproject.org/updates/cockpit-193-1.fc29)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/cockpit-193-1.fc30)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2019-05-15-cockpit-194.md",
    "content": "---\ntitle: Cockpit 194\nauthor: lis\ndate: 2019-05-15\ntags: cockpit linux\nslug: cockpit-194\ncategory: release\nsummary: Firewall page improvements and a new switch\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly. Here are the release notes from version 194.\n\n### Firewall: Add services to a specific zone\n\nThe firewall page now supports zones.\n\n![Firewall zone list](/images/firewall-zone-list.png)\n\nServices can now be added to and removed from specific zones.\n\n![Adding services to zones](/images/firewall-add-services-to-zones.png)\n\nAdditionally, dialogs on the Firewall page now show error messages.\n\n![Firewall error message](/images/firewall-error-message.png)\n\n### Redesigned on/off switch\n\nThis release of Cockpit features a redesigned on/off switch.  Compared\nwith the old version, the new switch is easier to use (with a bigger\nclickable area), uses iconography to avoid translation problems, is\naccessible, and is keyboard-navigatable.  The new design corresponds\nto the design of the\n[switch from PatternFly 4](https://pf4.patternfly.org/components/Switch/examples/).\n\n![Switch On](/images/firewall-switch-on.png)\n\n![Switch On](/images/firewall-switch-off.png)\n\nThe switch also features a native-like keyboard focus indicator: a blue glow for\nChrome/WebKit-based browsers and a dotted outline for Firefox.\n\n![Switch with keyboard focus, Epiphany](/images/firewall-switch-on-epiphany-focus.png)\n\n![Switch with keyboard focus, Firefox](/images/firewall-switch-on-firefox-focus.png)\n\n### Try it out\n\nCockpit 194 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/194)\n * [Fedora 29](https://bodhi.fedoraproject.org/updates/cockpit-194-1.fc29)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/cockpit-194-1.fc30)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2019-05-29-cockpit-195.md",
    "content": "---\ntitle: Cockpit 195\nauthor: lis\ndate: 2019-05-29\ntags: cockpit linux\nslug: cockpit-195\ncategory: release\nsummary: Firewall, Storage and Machines improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly. Here are the release notes from version 195.\n\n### Simplified support for external TLS termination\n\nIt's now easier to configure Cockpit's web server `cockpit-ws` to run\nbehind a\n[TLS termination proxy](https://en.wikipedia.org/wiki/TLS_termination_proxy).\nIf the proxy runs on the same machine, then `cockpit-ws` can be run with\nthe new `--for-tls-proxy` option, which will adjust the allowed\n[Origins](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Origin)\nand\n[Content-Security-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP)\nto `https://` URLs. With this option, it's no longer necessary to\nexplicitly configure\n[cockpit.conf](https://cockpit-project.org/guide/latest/cockpit.conf.5.html).\n\n### Firewall: More support for zones\n\nIn addition to the support for adding services to specific zones in the\nlast release, the firewall page now allows adding and removing of the zones\nthemselves.\n\n![Adding firewall zones](/images/firewall-add-zone.png)\n\n### Machines: Additional storage options\n\nDuring virtual machine creation it is now possible to select the\nstorage pool to use for the machine.\n\n![Select storage pool during machine creation](/images/machines-select-storage-pool.png)\n\nIt is now also possible to create a storage pool using a physical disk\ndevice as the backing store.\n\n![Create storage pool on physical disk device](/images/machines-new-pool-physical-disk-device.png)\n\nFinally, it is now possible to configure the disk cache policy when\nadding storage devices to virtual machines.\n\n![Adjust virtual machine disk cache policy](/images/machines-disk-cache-policy.png)\n\n### Machines: Support for changing memory allocation\n\nThe Machines page also gained support for changing the current and\nmaximum memory allocations of a virtual machine.\n\n![Adjust virtual machine memory allocation](/images/machines-memory-allocation.png)\n\n### Storage: Select encryption type separately from filesystem\n\nThe selection of the filesystem type and filesystem encryption options\nhave been uncoupled on the storage page, allowing for the use of LUKS\nwith filesystems other than ext4 and xfs.\n\n![New encryption option](/images/storage-separate-encryption-option.png)\n\n### Try it out\n\nCockpit 195 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/195)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-553472e6c2)\n"
  },
  {
    "path": "_posts/2019-06-12-cockpit-196.md",
    "content": "---\ntitle: Cockpit 196\nauthor: mvo\ndate: 2019-06-12\ntags: cockpit linux\nslug: cockpit-196\ncategory: release\nsummary: Machines improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly. Here are the release notes from version 196.\n\n### Machines: Installation ISOs can be specified with a URL\n\nCockpit can now create a virtual machine from a ISO disc image URL.\n\n![Virtual machine from URL](/images/machines-from-url.png)\n\n### Machines: IP addresses for network interfaces\n\nThe information about network interfaces now includes their IP addresses.\n\n![Interface addresses](/images/machines-if-ip.png)\n\n### Try it out\n\nCockpit 196 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/196)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-07ec9aac9f)\n"
  },
  {
    "path": "_posts/2019-06-26-cockpit-197.md",
    "content": "---\ntitle: Cockpit 197\nauthor: kkoukiou\ndate: 2019-06-26\ntags: cockpit linux\nslug: cockpit-197\ncategory: release\nsummary: Machines new features\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly. Here are the release notes from version 197.\n\n### Machines: Support all storage pool types for new disks\n\nA cockpit user can now add a disk to a VM either by creating a new volume or\nby choosing an existing volume, which can now reside on [any libvirt-supported pool\ntype](https://libvirt.org/storage.html#StorageBackendDir).\n\n![Disk on NFS](/images/disk-on-nfs.png)\n\n![Disk on ISCSI](/images/disk-on-iscsi.png)\n\n### Machines: Show available space on host at VM creation\n\nWhen creating a new disk during VM creation, the dialog now has an indication\nof the available space on the destination storage.\nThis prevents the user from overallocating storage to VMs which would lead to\ninstallation failure.\n\n![Available storage for new VM](/images/available-storage-for-new-vm.png)\n\n### Try it out\n\nCockpit 197 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/197)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-07ec9aac9f)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2019-07-10-cockpit-198.md",
    "content": "---\ntitle: Cockpit 198\nauthor: pitti\ndate: 2019-07-10\ntags: cockpit linux\nslug: cockpit-198\ncategory: release\nsummary: Cockpit with PatternFly 4 user interface design update\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 198.\n\n### PatternFly4 user interface design\n\nCockpit has been restyled to match the\n[PatternFly 4](https://pf4.patternfly.org/components/Button/examples/)\nUser Interface design, including the\n[Red Hat Text and Display fonts](https://github.com/RedHatOfficial/RedHatFont).\n\nThis style refresh aligns Cockpit with other web user interfaces that use\n[PatternFly](https://www.patternfly.org/), such as\n[OpenShift 4](https://www.redhat.com/en/openshift-4).\n\nOver time, Cockpit will be ported to actually use PatternFly 4 widgets, but\nthis restyle allows us to change Cockpit gradually.\n\n![login page](/images/login-pf4.png)\n\n![system page](/images/system-pf4.png)\n\n### SELinux: Show changes\n\nThe SELinux page now has a new section \"System Modifications\" which shows all\npolicy settings that were made to the system (with Cockpit or otherwise):\n\n![SELinux modifications](/images/selinux-modifications.png)\n\nThe \"View Automation Script\" link will show a dialog with a shell script that\ncan be used to apply the same changes to other machines:\n\n![SELinux automation script](/images/selinux-autoscript.png)\n\n### Machines: Deletion of Virtual Networks\n\nThe Virtual Networks section of the Machines page now supports deleting networks.\n\n![delete virtual network](/images/machines-delete-network.png)\n\n### Machines: Support more disk types\n\nWhen creating a new VM, the disk can now be on a storage pool type other than a\nplain file. The newly supported types are iSCSI, LVM, and physical volumes.\n\n![VM creation with iSCSI pool](/images/machines-create-iscsi.png)\n\n### Docker: Change menu label\n\nThe menu label changed from \"Containers\" to \"Docker Containers\". This avoids\nconfusion with the \"Podman Containers\" page from\n[cockpit-podman](https://github.com/cockpit-project/cockpit-podman), and points\nout that this page really is about Docker only, not any other container\ntechnology.\n\n### Web server: More flexible https redirection for proxies\n\n[cockpit-ws](https://cockpit-project.org/guide/latest/cockpit-ws.8.html) now\nsupports redirecting unencrypted http to https (TLS) even when running in\n`--no-tls` mode. Use this when running cockpit-ws behind a reverse http proxy\nthat also supports https, but does not handle the redirection from http to\nhttps for itself. This is enabled with the new `--proxy-tls-redirect` option.\n\n### Try it out\n\nCockpit 198 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/198)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-2284294b43)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2019-07-24-cockpit-199.md",
    "content": "---\ntitle: Cockpit 199\nauthor: kkoukiou\ndate: 2019-07-24\ntags: cockpit linux\nslug: cockpit-199\ncategory: release\nsummary: Cockpit with Logs and Services and HWInfo design updates\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.  Here are the release notes from version 199.\n\n### Redesigned logs\n\nRestyled logs across all of Cockpit.\n\n![service-logs](/images/service-logs.png)\n\n### Services: Design and accessibility improvements\n\nServices and other systemd units now sport a simpler on/off state with a clear status overview.\n\n![service-details](/images/service-details.png)\n\nIn addition, the tabs in Service page are now accessible.\n\n### System: Show DIMM information on Hardware Info page\n\nThe Hardware Info page now displays memory-related information for DIMMs, such as: size, rank, speed, and other details.\n\n![dimm-memory](/images/dimm-hwinfo.png)\n\n_Thanks to Akshit Dua for this feature!_\n\n### Machines: VM creation dialog now shows the recommended memory for the selected OS\n\nDuring VM creation, memory fields are checked for validity. The Create VM dialog now displays a recommended RAM size for the selected OS and an error appears if memory is set too low.\n\n![memory-for-os](/images/recommended-memory-os.png)\n\n### Try it out\n\nCockpit 199 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/199)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-d73df27df4)\n\n*[VM]: Virtual Machine\n*[DIMM]: Dual Inline Memory Module\n*[RAM]: Random Access Memory\n*[OS]: Operating System\n"
  },
  {
    "path": "_posts/2019-08-07-cockpit-200.md",
    "content": "---\ntitle: Cockpit 200\nauthor: pitti\ndate: 2019-08-07\ntags: cockpit linux\nslug: cockpit-200\ncategory: release\nsummary: Cockpit with new TLS proxy, firewall, and Machines improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly. This is version Two Hundred, prepared for you live and in person from the Cockpit team sprint in Berlin!\n\n### Machines: Type-ahead OS selection\n\nIn the VM creation dialog, OS vendor and product dropdowns have been replaced by a singular \"Operating System\" selector. The new dropdown is keyboard-friendly and supports auto-completion.\n\n![Machines typeahead OS selection](/images/machines-os-typeahead.png)\n\n### Machines: Create LVM storage pools\n\nStorage pools using LVM can be created on the Machines page.\n\n![Machines LVM storage pools](/images/machines-lvm-pool.png)\n\n### Machines: Create virtual networks\n\n[Virtual networks](https://libvirt.org/formatdomain.html#elementsNICSVirtual) can now be created on the Virtual Machines page. These are used for connecting VMs with each other and/or to the host, or isolating different groups of VMs from each other.\n\n![Machines create network](/images/machines-create-network.png)\n\n### Networking: Show included firewalld services\n\n[firewalld 0.7.1](https://firewalld.org/2019/07/firewalld-0-7-1-release) introduces the concept of services that include other services. Cockpit's Firewall page shows these:\n\n![Firewall included services](/images/firewall-included-services.png)\n\n### Web server: Split out TLS handling\n\nThis release introduces [`cockpit-tls`](https://cockpit-project.org/guide/latest/cockpit-tls.8.html), a TLS terminating HTTP proxy that runs in front of [cockpit-ws](https://cockpit-project.org/guide/latest/cockpit-ws.8.html).\n\nAt the moment, `cockpit-tls` does not provide additional features over using `cockpit-ws` directly (other than better isolation), but it sets up a basis for future work, such as supporting smart card authentication.\n\nThis change is expected to be transparent to users. Please [report issues](https://github.com/cockpit-project/cockpit/issues/new?template=bug_report.md) if you encounter any page loading failures, stalls, or similar networking issues!\n\n### Try it out\n\nCockpit 200 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/200)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-d73df27df4)\n\n*[VM]: Virtual Machine\n*[OS]: Operating System\n"
  },
  {
    "path": "_posts/2019-08-21-cockpit-201.md",
    "content": "---\ntitle: Cockpit 201\nauthor: Gundersanne\ndate: 2019-08-21\ntags: cockpit linux\nslug: cockpit-201\ncategory: release\nsummary: Cockpit with Machines, services, and system improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.\n\n\n### Machines: VM creation changes\n\nCreating a VM by importing an existing disk has been moved to a separate dialog.\n\n![Machines creating a VM by importing an existing disk](/images/machines-create-importing-disk-separate-dialog.png){:.screenshot}\n\nThe Operating System input field is now mandatory; this allows the guest device\nassignment to be optimized, leading to better performance.\n\n![Machines OS mandatory input](/images/machines-os-input-mandatory.png){:.screenshot}\n\nThe storage size input field has to be at least the required minimum by the VM's\nOS.\n\n![Machines storage input lower\nlimit](/images/machines-storage-input-lower-limit.png){:.screenshot}\n\n### Machines: Enable interface type \"direct\" in NIC configuration\n\nIt's now possible to directly attach the VM's NIC to the specified physical\ninterface of the host.\n\n![Machines direct interface type](/images/machines-direct-interface-type.png){:.screenshot}\n\n### systemd: Add more actions to services\n\nIt's now again possible to stop a service, without disabling it. Reloading is now\navailable only when the service allows it.\n\nFurthermore, disabling or masking a service removes any lingering \"failed\" state,\nreducing noise.\n\n![Services more actions for services](/images/services-more-actions-services.png){:.screenshot}\n\n### Try it out\n\nCockpit 201 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/201)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-2ee93529c0)\n\n*[VM]: Virtual Machine\n*[LVM]: Logical Volume Manager\n*[OS]: Operating System\n*[TLS]: Transport Layer Security\n*[HTTP]: Hypertext Transport Protocol\n"
  },
  {
    "path": "_posts/2019-09-04-cockpit-202.md",
    "content": "---\ntitle: Cockpit 202\nauthor: kkoukiou\ndate: 2019-09-04\ntags: cockpit linux\nslug: cockpit-202\ncategory: release\nsummary: Cockpit with Machines improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.  Here are the release notes from version 202.\n\n### Machines: Creation of Storage Volumes\n\nCreation of Storage Volumes is now possible for a subset of the supported Storage Pool types.\nThe Storage Volumes can then be used as virtual disks for VMs.\n\n![VM Storage Volume creation](/images/create-storage-volume.png)\n\n### Improved component for selecting paths on the filesystem\n\nThe component used in dialogs for selecting paths on the filesystem was improved in order to be keyboard navigatable and accessible.\nMultiple dialogs such as SSH key authentication from the Shell, Create VM and Create Storage Pool from Machines Page benefit from this change.\n\n![SSH Key Add](/images/ssh-key-add.png)\n![Create VM source filesystem](/images/create-vm-source-filesystem.png)\n\n### Try it out\n\nCockpit 202 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/202)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-1446526b5e)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2019-cb9233ff6c)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2019-09-18-cockpit-203.md",
    "content": "---\ntitle: Cockpit 203\nauthor: mvo\ndate: 2019-09-18\ntags: cockpit linux\nslug: cockpit-203\ncategory: release\nsummary: Cockpit with Machines improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.  Here are the release notes from version 203.\n\n### Machines: Network Interfaces\n\nVirtual machines now support creation of virtual network interfaces.\n\n![VM Network Interface creation](/images/vm-network-interface.png)\n\n### Try it out\n\nCockpit 203 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/203)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-0db41ff415)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2019-82189ed15b)\n"
  },
  {
    "path": "_posts/2019-10-02-cockpit-204.md",
    "content": "---\ntitle: Cockpit 204\nauthor: pitti\ndate: 2019-10-02\ntags: cockpit linux\nslug: cockpit-204\ncategory: release\nsummary: Cockpit with Services and Machines improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.  Here are the release notes from version 204.\n\n### System: Highlight failed services\n\nA \"System Health\" entry on the System overview page shows failed services, if any exist:\n\n![Failed services on System page](/images/system-failed-services.png)\n\nFailed services also cause a warning to appear in the navigation, next to the \"Services\" entry.\n\nThe Services page now shows failed services at the top of the list, to make it easier to spot problems.\n\n### Machines: Configure read-only and shareable disks\n\nThe \"Disks\" tab now shows whether a disk is read-only or shareable between multiple VMs:\n\n![Show shareable option in VM list](/images/machines-shareable-disk-list.png)\n\nWith the new \"Edit\" button these properties can now be changed:\n\n![Edit shareable option](/images/machines-shareable-disk-edit.png)\n\nSharing is only supported for disks in raw format. Note that sharing writable disks can easily destroy data when multiple VMs write to the disk at the same time; so use this feature with caution.\n\nSharing will be enabled automatically when adding a disk to more than one VM.\n\n### Playground: Add index page\n\nVarious \"Playground\" pages are meant for developers to test internal features of Cockpit; they are shipped in the \"cockpit-tests\" package. All these pages are now subsumed in a single \"Development\" menu entry that shows an index page, instead of a lot of individual menu entries that cluttered up the menu too much.\n\nThat index page now also shows playground elements that weren't previously visible, such as the \"Speed Tests\" page.\n\n### Try it out\n\nCockpit 204 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/204)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-1da872f5fa)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2019-ddb9f2270b)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2019-10-16-cockpit-205.md",
    "content": "---\ntitle: Cockpit 205\nauthor: skobyda\ndate: 2019-10-16\ntags: cockpit linux\nslug: cockpit-205\ncategory: release\nsummary: Cockpit with Design updates, page notifications, and security hardening\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.\nHere are the release notes from version 205.\n\n### Firewall: UI restructuring\n\nThe firewall page was redesigned. Instead of having separate listings for services\nand zones, the services are now listed per zone. This aims to make the relationship\nbetween zones and services clearer.\n\n![Firewall Redesign](/images/firewall-ui-redesign.png)\n\n### Machines: Refactor Create VM dialog and introduce a download option\n\nA guest operating system can now be downloaded automatically by only\nselecting its name. Memory and storage size will default to recommended\nvalues for the selected OS.\n\n![Create VM dialog](/images/machines-create-vm-refactor.png)\n\n### Adjust menu to PatternFly's current navigation design\n\nThe pages menu now has a dark theme, the recommended current design from PatternFly after an\n[user study](https://blog.patternfly.org/patternfly/how-do-different-patternfly-visual-themes-affect-navigation-performance-perception-and-preference/).\n\n### Searching with keywords\n\nEnable searching by page names and keywords. Also works with translated page\nnames and translated keywords. Searching by page content is not available yet.\n\n![Dark navigation](/images/nav-dark-nav.png)\n\n### Software Updates: Use notifications for available updates info\n\nCockpit will notify you about available updates in the navigation menu.\n\n![Notify about available updates](/images/notify-available-updates.png)\n\n### Web server security hardening\n\nThe cockpit-tls proxy and the cockpit-ws instances now run as different system users,\nand the instances are controlled by systemd. This provides better isolation and robustness.\n\n### Try it out\n\nCockpit 205 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/205)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-077643f593)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2019-51df278ff3)\n\n*[VM]: Virtual Machine\n*[OS]: Operating System\n"
  },
  {
    "path": "_posts/2019-10-30-cockpit-206.md",
    "content": "---\ntitle: Cockpit 206 and Cockpit-podman 10\nauthor: Gundersanne\ndate: 2019-10-30\ntags: cockpit linux\nslug: cockpit-206\ncategory: release\nsummary: Cockpit with machines, firewall, and login page improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.\n\n### Machines: Network interface deletion\n\nNetwork interfaces can now be removed from virtual machines.\n\n![Machines NIC deletion](/images/machines-nic-deletion.png)\n\n### login: Reuse password by default\n\nFor operations that change system state and for troubleshouting Cockpit needs\nadministrative rights, so make reusing the password for privileged tasks the\ndefault.\n\n![login reuse password checkbox is checked](/images/login-reuse-password-checked.png)\n\n### Firewall: Prevent accidental deletion\n\nA confirmation now appears when removing zones and the Cockpit service.\n\nIn addition to making the interface less volatile, Cockpit will warn you when\nyou're removing the cockpit service or a zone which contains the Cockpit\nservice, as these could impact your current connection.\n\n![Firewall removing a zone warns you](/images/firewall-removing-zone-warning.png)\n\nFurthermore, in order to avoid accidentally locking yourself out, Cockpit will\nautomatically add itself to all newly-created zones.\n\n### Podman: User containers\n\nThe Cockpit-podman page now has support for user containers. These do not\nrequire administrative privileges to run.\n\n![Cockpit podman user containers](/images/podman-user-containers.png){:.screenshot}\n\n### Try it out\n\nCockpit 206 and Cockpit-podman 10 are available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/206)\n * [Cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/10)\n * [Cockpit Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-a460236814)\n * [Cockpit-podman Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-77aeecbdbf)\n * [Cockpit Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2019-0667dd1786)\n * [Cockpit-podman Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2019-f72585793e)\n"
  },
  {
    "path": "_posts/2019-11-13-cockpit-207.md",
    "content": "---\ntitle: Cockpit 207\nauthor: kkoukiou\ndate: 2019-10-30\ntags: cockpit linux\nslug: cockpit-207\ncategory: release\nsummary: Cockpit with authentication and storage page improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly.\n\n### Web server: Accept EC certificates\n\nThe `/etc/cockpit/ws-certs.d` directory can now contain\n[Elliptic Curve Cryptography](https://wiki.openssl.org/index.php/Elliptic_Curve_Cryptography) certificates in addition to the classic RSA ones.\n\n### Storage: List all software devices in a single panel\n\nThis avoids showing empty panels for types of devices that you don't have.\n\n![Storage software devices](/images/storage-software-devices.png){:.screenshot}\n\n### Redesigned notifications\n\nThis release of Cockpit features a new notification design,\nwhich corresponds to the [alert component from PatternFly 4](https://pf4.patternfly.org/components/Alert/examples/).\n\n![Alert firewall](/images/alert-firewall.png){:.screenshot}\n\n### Try it out\n\nCockpit 207 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/207)\n * [Cockpit Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-2a9d6c73dc)\n * [Cockpit Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2019-d2ecb54f20)\n"
  },
  {
    "path": "_posts/2019-11-27-cockpit-208.md",
    "content": "---\ntitle: Cockpit 208\nauthor: pitti\ndate: 2019-11-27\ntags: cockpit linux\nslug: cockpit-208\ncategory: release\nsummary: Cockpit with Machines, file system creation, and crash reporting improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.  Here are the release notes from version 208.\n\n### Storage: Drop \"default mount point\" concept\n\nCockpit no longer offers a confusing \"Default\" choice when mounting a filesystem. Creating a new filesystem now always requires a specified mount point.\n\nAdditionally, Cockpit now hides the distinction between configuration (`/etc/fstab`) and run-time state (`/proc/mounts`). Changes made in Cockpit always apply to both the configuration and run-time state. When configuration and run-time state differ from each other, Cockpit will show a warning and let you easily bring them back in sync.\n\n![Storage format dialog](/images/storage-format-mountpoint.png)\n\n### Machines: Support transient virtual networks and storage pools\n\nTransient resources exist only while active and cease to exist once deactivated. Cockpit now disables or hides functionality like autostart or deletion for transient networks and storage pools.\n\n![Transient virtual network](/images/machines-transient-network.png)\n\n### Machines: Sliders for disk size and memory in VM creation\n\n\"Create New Virtual Machine\" and \"Import Virtual Machine\" dialogs now have\nsliders to configure memory and disk sizes.\n\n![Machine creation size sliders](/images/machines-size-sliders.png)\n\n### Logs: Improve crash reporting\n\nCockpit previously sent problem and crash reports directly to [ABRT Analytics](https://github.com/abrt/faf) from the Logs page. Switching to the new \"reportd\" framework allows Cockpit report to more places, such as [Bugzilla](https://bugzilla.redhat.com/), and has improved authentication methods.\n\n![Reportd crash submission](/images/logs-reportd.png)\n\nThanks to Ernestas Kulik for this work!\n\n### Try it out\n\nCockpit 208 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/208)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-d3b55c4594)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2019-b29e09a8d4)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2019-12-13-cockpit-209.md",
    "content": "---\ntitle: Cockpit 209\nauthor: mvo\ndate: 2019-12-13\ntags: cockpit linux\nslug: cockpit-209\ncategory: release\nsummary: Cockpit with Overview improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly.  Here are the release notes from version 209.\n\n### A new design for the Overview page\n\nThe landing page has been completely redesigned.  Information is\ngrouped into easier to understand panels, health information is much\nmore prominent, the resource graphs have been moved to their own page,\nand the hardware information page should now be easier to find.\n\n![Overview](/images/new-overview.png)\n\n### Session timeouts\n\nCockpit will automatically log you out of your current session after\n15 minutes of inactivity.\n\n![Automatic logout](/images/session-timeout.png)\n\nYou can configure the timeout, in minutes, in\n`/etc/cockpit/cockpit.conf`.  For example, this will disable automatic\nlogouts completely:\n```\n[Session]\nIdleTimeout=0\n```\n\n### Support for banners on the login page\n\nLike SSH, Cockpit can now optionally show the content of banner files\non the login screen.\n\n![/etc/issue](/images/etc-issue.png)\n\nThis needs to be configured in `/etc/cockpit/cockpit.conf`.  For example:\n```\n[Session]\nBanner=/etc/issue.cockpit\n```\n\n### Support for TLS client certificate authentication\n\nYou can now log into Cockpit with a TLS client certificate that is\nprovided by your browser or a device like a Smart Card or YubiKey.\n\nSee it in action:\n\n<iframe width=\"960\" height=\"540\" src=\"https://www.youtube.com/embed/v07cHZQsRyo\" frameborder=\"0\" allowfullscreen></iframe>\n\nAnd read the documentation [here](https://cockpit-project.org/guide/latest/cert-authentication.html).\n\n### Support for Fedora CoreOS\n\n[Fedora CoreOS](https://docs.fedoraproject.org/en-US/fedora-coreos/)\nis a minimal and robust Fedora based operating system for hosting\ncontainer workloads. It is the successor of [Fedora Atomic\nHost](http://www.projectatomic.io/), which is not supported any more.\n\nWe now fully support running Cockpit on this platform.\n\nPlease see the [Running\nCockpit](https://cockpit-project.org/running.html) documentation or\nthe [cockpit/ws docker hub](https://hub.docker.com/r/cockpit/ws/) page\nfor how to install Cockpit on Fedora CoreOS.\n\n### List cockpit logins in wtmp/utmp\n\nLogins via the web console are now correctly registered in utmp and\nwtmp, allowing them to be visible in tools such as `who`, `w`, and\n`last`.\n\n```\n[root@m1 ~]# who\nroot     pts/0        2019-12-13 08:09 (172.27.0.2)\nadmin    web console  2019-12-13 08:09\n```\n\n### Dropped support for the pam_rhost module\n\nThe `pam_rhosts` module is not in Cockpit's PAM stack by default (nor\nin any other stack) and the remote IP is not a reliable piece of\ninformation.  NAT, VPNs, or reverse proxies (such as Cockpit's own\ncockpit-tls) all destroy the actual IP of the browser's machine.\n\nFor these reasons, Cockpit does not set the `PAM_RHOST` variable\nanymore when running its PAM stack.\n\n### Try it out\n\nCockpit 209 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/209)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2019-53834396c7)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2019-3df1269346)\n"
  },
  {
    "path": "_posts/2020-01-08-cockpit-210.md",
    "content": "---\ntitle: Cockpit 210 and Cockpit-podman 12\nauthor: kkoukiou\ndate: 2020-01-08\ntags: cockpit linux podman\nslug: cockpit-210\ncategory: release\nsummary: Cockpit with Overview, Dashboard and Machines improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly. Here are the release notes from version 210.\n\n### Overview: Add CPU utilization to usage card\n\nDisplay CPU usage information in the usage card of the Overview page. For detailed CPU usage information, please consult the graphs page.\n\n![Overview](/images/overview-cpu-usage.png)\n\n### Dashboard: Support SSH identity unlocking when adding new machines\n\nCockpit now offers an inline feature to unlock SSH identities when adding a new machine to the Dashboard.\n\n![unlock-keyring](/images/unlock-keyring.png)\n\n### SElinux: Introduce an Ansible automation script\n\nSELinux modifications can be reviewed and exported also as Ansible tasks. These exported tasks can be applied to other servers.\n\n![SElinux autoscript ansible](/images/selinux-autoscript-ansible.png)\n\n### Machines: Support \"bridge\" type network interfaces\n\nVirtual machines can now use \"bridge\" networking. VMs with bridged networking have full incoming and outgoing network access on a LAN, just like a physical machine.\n\n![VM NIC bridge](/images/vm-nic-bridge.png)\n\n### Machines: Support bus type disk configuration\n\nAdding and editing VM disks now supports different bus types, such as SATA, SCSI, USB, or Virtio.\n\nUsing Virtio is generally the best option, for performance reasons. Other bus types may be used if an operating system doesn't support Virtio. (For example: Windows does not support Virtio by default; additional drivers need to be installed.) Another valid reason to choose something other than Virtio is if the guest OS expects the disk to show up as another type of device.\n\n![Disk choose bus type](/images/disk-choose-bus-type.png)\n\n### Podman: Configure CPU share for system containers\n\nSystem containers now have a configuration option to adjust CPU shares.\n\nBy default, all containers have the same proportion of CPU cycles. A container’s CPU share weighting can be changed relative to the weighting of all other running containers. For more information, please refer to [`podman run`'s documentation](https://github.com/containers/libpod/blob/master/docs/source/markdown/podman-run.1.md#options), under \"cpu-shares\".\n\n![Cockpit podman CPU limit](/images/podman-cpu-limit.png){:.screenshot}\n\n### Try it out\n\nCockpit 210 and Cockpit-podman 12 are available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n\n#### Source\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/210)\n * [Cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/12)\n\n#### Fedora 30\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2020-8ff69018de)\n * [Cockpit-podman Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2020-63b7f0d62a)\n\n#### Fedora 31\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-afa121b867)\n * [Cockpit-podman Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-fbffc4a3a3)\n\n*[VM]: Virtual Machine\n*[VMs]: Virtual Machines\n*[NIC]: Network Interface Card\n*[SATA]: Serial \"Advanced Technology\" Attachment, a bus interface to attach storage devices to a computer\n*[SCSI]: Small Computer System Interface, commands and protocols for communication with (mainly storage) devices\n*[USB]: Universal Serial Bus, a protocol for hot-pluggable (and usually external) devices\n*[Virtio]: Virtual Input/Output, a standard for network and disk drivers where the guest cooperates with the host for performant virtualization\n*[SELinux]: Security-Enhanced Linux, policies for enforcing access controls in Linux\n*[SSH]: Secure Shell, a common protocol to securely connect to a remote computer\n*[CPU]: Central Processing Unit, the \"brain\" of a computer\n*[LAN]: Local Area Network\n*[OS]: Operating System\n"
  },
  {
    "path": "_posts/2020-01-22-cockpit-211.md",
    "content": "---\ntitle: Cockpit 211\nauthor: mvo\ndate: 2020-01-22\ntags: cockpit linux\nslug: cockpit-211\ncategory: release\nsummary: Cockpit with certificate and layout improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly. Here are the release notes from version 211.\n\n### Better support for various TLS certificate formats\n\nCockpit can now read certificates in a number of formats, such as the\none from LetsEncrypt.\n\nSpecifically, the web server now accepts certificates in\n`/etc/cockpit/ws-certs.d` which have a `.crt` extension, in addition\nto `.cert`. Also, private keys can now be in a separate file with a\n`.key` extension.\n\n### Switch from Zanata to Weblate\n\nThe Fedora project is [moving away from\nZanata](https://communityblog.fedoraproject.org/fedora-localization-platform-migrates-to-weblate/),\nand so is the Cockpit project.  Translations are now maintained with\n[Weblate](https://translate.fedoraproject.org/projects/cockpit/).\n\n### Overview layout optimizations\n\nThe cards of the Overview page now work better at various screen\nresolutions.\n\n### Try it out\n\nCockpit 211 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n\n#### Source\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/211)\n\n#### Fedora 30\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2020-e70cf11146)\n\n#### Fedora 31\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-d5974928d6)\n"
  },
  {
    "path": "_posts/2020-02-05-cockpit-212.md",
    "content": "---\ntitle: Cockpit 212 and Cockpit-podman 13\nauthor: Gundersanne\ndate: 2020-02-05\ntags: cockpit linux podman\nslug: cockpit-212\ncategory: release\nsummary: Cockpit with documentation and time localization improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We\nrelease regularly. Here are the release notes from version 212.\n\n### Per-page documentation\n\nThe help menu now includes links to page- and OS-specific documentation.\n\n![Documentation per page](/images/documentation-per-page.png){:.screenshot}\n\n### Localize times\n\nThe Overview, Accounts, and Logs pages now show dates and times in the\ncorrectly-localized format.\n\n![Localized time formats](/images/overview-localized-time.png){:.screenshot}\n\n### Podman: Show full log\n\nShow containers' logs since their startup, not just since opening the Logs tab.\n\n![Podman historical logs](/images/cockpit-podman-historical-logs.png){:.screenshot}\n\n### Try it out\n\nCockpit 212 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n\n#### Source\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/212)\n * [Cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/13)\n\n#### Fedora 30\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2020-f951136bb9)\n * [Cockpit-podman Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2020-cb167d1ce6)\n\n#### Fedora 31\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-ebfb75d52f)\n * [Cockpit-podman Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-88578e70da)\n"
  },
  {
    "path": "_posts/2020-02-19-cockpit-213.md",
    "content": "---\ntitle: Cockpit 213\nauthor: mvo\ndate: 2020-02-19\ntags: cockpit linux\nslug: cockpit-213\ncategory: release\nsummary: Cockpit with documentation and virtual machine improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly. Here are the release notes from version 213.\n\n### Inline documentation\n\nCockpit has started to include documentation for specific features, such as network bonds.\n\n![Feature documentation](/images/network-inline-docs.png){:.screenshot}\n\nWe plan to expand this in the future and add many more short documentation popups.\n\n### Support for transient virtual machines\n\nNot all operations make sense for transient virtual machines, and Cockpit is now aware of that.\n\n![Transient virtual machines](/images/transient-vms.png){:.screenshot}\n\n### Virtual machines can now use UEFI\n\nCockpit now supports selecting UEFI as the firmware for a new virtual machine.  This needs to be done before the first boot of that machine.\n\n![Firmware selection](/images/vm-firmware-selection.png){:.screenshot}\n\n### Unattended virtual machine installation\n\nWhen creating a virtual machine with a supported OS, Cockpit can install and configure that OS automatically, without requiring interactions.\n\n![Unattended installation](/images/vm-unattended.png){:.screenshot}\n\n### Try it out\n\nCockpit 213 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/213)\n * [Fedora 30](https://bodhi.fedoraproject.org/updates/FEDORA-2020-657c52197c)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-ec0a7fdc82)\n * [Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-0dbb2a50e0)\n"
  },
  {
    "path": "_posts/2020-03-04-cockpit-214.md",
    "content": "---\ntitle: Cockpit 214\nauthor: pitti\ndate: 2020-03-04\ntags: cockpit linux\nslug: cockpit-214\ncategory: release\nsummary: Cockpit with bug fixes\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly. Here are the release notes from version 214.\n\n### Networking: List Firewall active zones when unprivileged\n\n[firewalld](https://firewalld.org/) recently became more restrictive. Listing services in a zone is no longer possible for anyone but superusers. As a result, the Firewall page was empty in unprivileged mode.\n\nWith this new Cockpit version, the Firewall page shows active zones again, however without services listed.\n\n### Selenium tests deprecation\n\nThe Cockpit team has adjusted many \"verify\" browser tests to be non-destructive. This reworking was done to allow test VMs to be reused without resetting, which was our primary remaining reason for still having the Selenium tests.\n\nCompared to verify tests, Selenium tests are much harder to debug and coverage is not quite as complete. Therefore, we will no longer develop Selenium tests. Eventually, the Selenium tests will be completely removed.\n\nIf you work with the Selenium tests, please get in touch with us.\n\n### Try it out\n\nCockpit 214 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/214)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-22b3a559ff)\n * [Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-6c27781454)\n\n *[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2020-03-18-cockpit-215.md",
    "content": "---\ntitle: Cockpit 215\nauthor: kkoukiou\ndate: 2020-03-18\ntags: cockpit linux\nslug: cockpit-215\ncategory: release\nsummary: Cockpit with Network improvements and Docker deprecation\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly. Here are the release notes from version 215.\n\n### Networking: Show additional included ports in firewall zones\n\nThe Firewall page now shows ports that are directly added to a zone at the end of the services list.\n![zone ports](/images/firewall-zone-ports.png)\n\n### Docker: Deprecate `cockpit-docker` in favor of `cockpit-podman`\n\n`cockpit-docker` is being deprecated in favor of `cockpit-podman`, and will not be\nmaintained upstream. We have stopped building it for Ubuntu ≥ 20.04,\nDebian ≥ 11, and Fedora >= 32 (i. e. the current development series), but will keep it for the\nstable releases (i. e. backports).\n\n### Try it out\n\nCockpit 215 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/215)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-6f3212b6fa)\n * [Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-a63046430d)\n"
  },
  {
    "path": "_posts/2020-04-01-cockpit-216.md",
    "content": "---\ntitle: Cockpit 216\nauthor: lis\ndate: 2020-04-01\ntags: cockpit linux\nslug: cockpit-216\ncategory: release\nsummary: Cockpit with improved SELinux page and last login banner\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly. Here are the release notes from version 216.\n\n### SELinux: Automatic application of solutions that set booleans\n\nThe SELinux page can now automatically apply solutions that set [SELinux booleans](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/sect-security-enhanced_linux-working_with_selinux-booleans).\n\n![Apply this solution](/images/selinux-apply-this-solution.png)\n\nIn addition, command lines in solution details are now formatted properly.\n\n### Machines: Drop virsh backend support\n\nThis release drops virsh backend support from the Machines page and\nswitches to using libvirt-dbus exclusively.  As a result, as of this\nrelease, cockpit-machines is no longer supported on Ubuntu 18.04.\n\n### Overview: New \"last login\" banner\n\nSimilar to text logins at the console, or via SSH, Cockpit now displays a\nbanner showing the last successful login.  If there have been failed login\nattempts, the number of attempts and the time of the most recent failed attempt\nwill be shown as well.\n\n![Last login banner](/images/last-login-banner.png)\n\nA side-effect of this work is that Cockpit now correctly updates\n`/var/log/lastlog` (the record of last login times) and `btmp` (the\nrecord of failed login attempts).\n\n### Try it out\n\nCockpit 216 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/216)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-6bf666bd24)\n * [Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-29e40ad324)\n\n *[SELinux]: security-enhanced Linux, a way to ensure better access control to resources\n *[virsh]: virtual machine shell, a utility to control virtual machines at the command line\n *[libvirt-dbus]: a way to control virtual machines over the common \"D-Bus\" inter-process communication layer\n *[SSH]: secure shell\n"
  },
  {
    "path": "_posts/2020-04-15-cockpit-217.md",
    "content": "---\ntitle: Cockpit 217\nauthor: mvo\ndate: 2020-04-15\ntags: cockpit linux\nslug: cockpit-217\ncategory: release\nsummary: Cockpit with improved Insights details, dialog buttons, and VM consoles\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly. Here are the release notes from version 217.\n\n### Overview: More details about Insights rule hits\n\nWhen a machine is connected to Red Hat Insights, the Health card on\nthe Overview page now shows more details.\n\n![Insights details](/images/health-insights.png)\n\n### Dialogs: Buttons have been improved\n\nFollowing [PatternFly's revised design guidelines](https://www.patternfly.org/v4/design-guidelines/usage-and-behavior/buttons-and-links#button-placement), button placement in all modal dialogs has been changed [to improve usability and accessibility](https://blog.patternfly.org/patternfly/button-placement-on-forms/).\n\n![New button order](/images/new-button-order.png)\n\n### Machines: Sending more keys to the console\n\nMany more special keys can be sent to running virtual machines:\n\n- Control+Alt+Delete is usually used for rebooting a computer. On Windows systems, it is also sometimes used for signing in.\n- Control+Alt+Backspace is useful for force-quitting the X Window System.\n- The rest of of these key combinations are for switching Linux virtual consoles.\n\n![Sending keys to a VM](/images/vm-console-keys.png)\n\n### Try it out\n\nCockpit 217 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/217)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-dd9f5f6216)\n * [Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-b072ad14c8)\n"
  },
  {
    "path": "_posts/2020-04-29-cockpit-218.md",
    "content": "---\ntitle: Cockpit 218\nauthor: pitti\ndate: 2020-04-29\ntags: cockpit linux\nslug: cockpit-218\ncategory: release\nsummary: Cockpit with Services page improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly. Here are the release notes from version 218.\n\n### Services: Improved accessibility and mobile support\n\nThe Services page has been rewritten using [PatternFly 4](https://www.patternfly.org/v4/) for improved accessibility. It now also works properly in mobile mode.\n\n![Services page mobile mode](/images/services-pf4-mobile.png)\n\n### Overview: Add uptime information\n\nThe \"System Information\" card on the Overview page now shows the machine's uptime (i.e. how long it has been running since the last boot).\n\n![Overview uptime](/images/overview-uptime.png)\n\nThanks to Martin Schiffner for this contribution!\n\n### Disable idle timeout by default\n\nAs a response to user feedback, the automatic session timeout after 15 minutes introduced in [Cockpit 209](https://cockpit-project.org/blog/cockpit-209.html) is now disabled by default. As Cockpit is never the primary session on a device, it is generally sufficient to let screen lock on desktops and mobile devices protect the session.\n\nThe idle timeout can still be enabled in [cockpit.conf](https://cockpit-project.org/guide/latest/cockpit.conf.5.html). Any existing explicit setting continues to work as before.\n\n### Support building without polkit\n\nCockpit integrates a [polkit](https://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html) agent, to handle D-Bus services like firewalld and udisks for users who are not full administrators. However, polkit has some large dependencies like mozjs which may be undesirable for embedded systems. With this Cockpit version, building without the polkit libraries is possible. This will, of course, disable the polkit agent within Cockpit sessions.\n\nThanks to Michael Häner for this contribution!\n\n### Try it out\n\nCockpit 218 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/218)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-3404e09362)\n * [Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-d3da290f23)\n\n *[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2020-05-06-cockpit-ansible.md",
    "content": "---\ntitle: Scale Cockpit troubleshooting to your computing fleet\nauthor: pitti\ndate: 2020-05-06\ncategory: announcement\ntags: cockpit selinux ansible scaling troubleshooting\ncomments: true\n---\n\nYou might know Cockpit as a troubleshooting tool for individual machines. But once you discover and test a solution, wouldn't it be nice to apply it to all your other machines in your data center?\n\nOf course, not every problem works this way. You wouldn't extend LVM with a new hard disk on a hundred machines at the same time. But there *are* situations where applying the same task across a multitude of computers makes sense.\n\nIn this example, we will adjust the [SELinux policy](https://www.redhat.com/en/topics/linux/what-is-selinux) to our needs and apply it elsewhere.\n\n[Cockpit 210](./cockpit-210.html) introduced a new approach that we want to explore; asking the computer to \"show me what I have done\". It's now easy to look at SELinux policy changes, compared to the defaults on a machine, in a human-readable form, as a shell script, or an [Ansible](https://www.ansible.com/) [role](https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse). The shell script and Ansible role are both suitable for automation across multiple machines.\n\n![SElinux autoscript ansible](/images/selinux-autoscript-ansible.png)\n\nTo see SELinux debugging, fixing, and deploying in action, watch this short three-and-a-half minute demo covering the whole workflow. Follow along with steps from \"_there's a problem I need to debug_\" to \"_I'll figure out a solution with Cockpit_\" and finally to \"_I'll apply this tested solution to my entire fleet of computers_\".\n\n<iframe width=\"960\" height=\"720\" src=\"//youtube.com/embed/ChXoNofPIjw?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\nWhile this approach works for SELinux, not every part of Cockpit can be used in a similar manner. First and foremost, Cockpit always shows the server's current *state*, not its configuration. At a glance, the difference between static configuration, dynamic state (like the IP address of a DHCP network card), or even hardware properties (like the number, capacity, and serials of hard disks) are not necessarily obvious.\n\nBut there are certainly more configuration-related places and actions in Cockpit. For example:\n\n * Enabling or disabling [Simultaneous Multi-Threading](https://access.redhat.com/security/vulnerabilities/L1TF) to mitigate CPU vulnerabilities\n * Enabling or disabling PCP, firewall, kdump, or general systemd units\n * Setting up automatic package updates\n\nWould copying the settings of these and applying them across other machines be useful to you? Do you have other ideas and uses for something like this? If so, please [give us your feedback](https://github.com/cockpit-project/cockpit/issues)!\n"
  },
  {
    "path": "_posts/2020-05-13-cockpit-219.md",
    "content": "---\ntitle: Cockpit 219\nauthor: kkoukiou\ndate: 2020-05-13\ntags: cockpit linux\nslug: cockpit-219\ncategory: release\nsummary: Logs filtering and privilege changing improvements\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly. Here are the release notes from version 219.\n\n### Logs: Improved filtering\n\nLogs can now be filtered by keywords and free text. Keywords include units, time constraints, priority, and [arbitrary journal fields](https://www.freedesktop.org/software/systemd/man/systemd.journal-fields.html). Dropdowns adjust the query string — so there's no need to remember the most common journal keywords. Also, copying and pasting this query string across machines allows administrators to have a precise filtered view of logs.\n\nA pause button has been included next to the filters, to pause the streaming of logs. When toggled, it changes to a resume button, letting you quickly switch back to a stream of incoming journal entries.\n\nAdditionally, log excerpts in other pages, such as those in Networking and Storage, now have links to view the the full journal in the Logs page with the same filter.\n\n![Journal Logs Filtering](/images/journal-logs-filtering.png)\n\n### Gain or drop administrative access in a running Cockpit session\n\nCockpit now allows more control over your access level. You can gain and drop administrative access in a running session, and Cockpit will remember the state for the next session.\n\nThis finally allows the user to do administrative actions without a password on the login page,\nsuch as when using smart card or Kerberos authentication, or ssh/Dashboard login with an SSH public key.\n\nCockpit respects the \"`sudo`\" configuration for your account. For example: When `NOPASSWD` is in your configuration, you don't have to provide a password in Cockpit to gain administrative access. And if \"`sudo`\" is configured for two factor authentication, Cockpit will ask twice.\n\nCockpit only supports \"sudo\" to elevate the access level. If your\ncustom Cockpit page relies on Polkit to grant access, you now need to\nuse the superuser option for the relevant channels. For example,\nusing the UDisks2 D-Bus API now has to look like this:\n\n`conn = cockpit.dbus(\"org.freedesktop.UDisks2\", { superuser: \"try\" })`\n\nWe plan to bring Polkit support back shortly.\n\n<iframe width=\"960\" height=\"720\" src=\"https://www.youtube.com/embed/-JDMe015m-k?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Try it out\n\nCockpit 219 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/219)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-9196806743)\n * [Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-8bffc7d9dd)\n"
  },
  {
    "path": "_posts/2020-05-27-cockpit-220.md",
    "content": "---\ntitle: Cockpit 220\nauthor: marusak\ndate: 2020-05-27\ntags: cockpit linux\nslug: cockpit-220\ncategory: release\nsummary: Cockpit with new navigation\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly. Here are the release notes from version 220.\n\n### New navigation with integrated switching of hosts\n\nThe navigation has been redesigned and brings four major improvements:\n- **One-level navigation**: The current two-level navigation has been squashed for better use of space and better discoverability\n- **Integrated hosts switching**: Switching between hosts as well as editing them can be done now directly from the navigation without using the 'Dashboard' component\n- **Better discoverability of applications**: Applications are shown as the first group in the menu and are also searchable\n- **Access level for all hosts**: You can change between Administrative and Limited access on every host, right from the navigation\n\n![New one-level navigation](/images/one-level-nav.png) | ![Integrated host switcher](/images/host-switcher.png)\n\n### Logs: Inline help for filtering\n\nThe [previous release](https://cockpit-project.org/blog/cockpit-219.html) introduced new advanced search features for logs.\nThis release adds a help button that shows an overview of accepted options, and the `journalctl` command corresponding to the current filter.\n\n![Logs inline help](/images/logs-inline-help.png)\n\n### Storage: Improve side panel on details page\n\nThe side panel on the storage details page has been unified and uses the same layout as on the storage overview page.\n\n![Storage side panel](/images/storage-details-side-panel.png)\n\n### Try it out\n\nCockpit 220 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/220)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-be42373991)\n * [Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-c21a90d666)\n"
  },
  {
    "path": "_posts/2020-05-29-cockpit-common-criteria.md",
    "content": "---\ntitle: Aligning Cockpit with Common Criteria\nauthor: marusak\ndate: 2020-05-29\ncategory: announcement\ntags: cockpit common-criteria\nslug: cockpit-common-criteria\ncomments: true\n---\n\nIn the last few releases new features were delivered to make Cockpit meet the [Common Criteria](https://www.commoncriteriaportal.org/) and thus making it possible to undergo the certification process in the near future.\nThis certification is often required for large organizations, particularly in the public sector, and also gives users more confidence in using the Web Console without risking their security.\n\nThis article provides a summary of these new changes with reference to the given CC norms.\n\n### Cockpit session tracking\n\nThere is a multitude of tools to track logins. Cockpit sessions are now correctly registered in\n`utmp`, `wtmp` and `btmp`, allowing them to be displayed in tools like `who`, `w`, `last` and `lastlog`.\nCockpit also works correctly with `pam_tally2` and `pam_faillock`.\n\n```\n[root@m1 ~]# who\nroot     pts/0        2019-12-13 08:09 (172.27.0.2)\nadmin    web console  2019-12-13 08:09\n```\n\nDelivered in version [209](https://cockpit-project.org/blog/cockpit-209.html) and [216](https://cockpit-project.org/blog/cockpit-216.html).\n\n[AC-9 Previous Logon (Access) Notification](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf)\n\n### Support for banners on the login page\n\nCompanies or agencies may need to show warning which states that use of the computer is for lawful purposes, the user is subject to surveillance, and anyone trespassing will be prosecuted.\nThis must be stated before login so they had fair warning.\nLike SSH, Cockpit can optionally show the content of a banner file on the login screen.\n\nThis needs to be configured in [/etc/cockpit/cockpit.conf](https://cockpit-project.org/guide/latest/cockpit.conf.5.html). For example to show content of `/etc/issue.cockpit` on the login page:\n```\n[Session]\nBanner=/etc/issue.cockpit\n```\n\n![/etc/issue](/images/etc-issue.png)\n\nDelivered in version [209](https://cockpit-project.org/blog/cockpit-209.html).\n\n[FTA_TAB.1 Default TOE access banners](https://www.niap-ccevs.org/MMO/PP/-442-/)\n\n### Session timeouts\n\nTo prevent abusing forgotten Cockpit sessions, Cockpit can be set up to automatically log users out of their current session after some time of inactivity.\nThe timeout (in minutes) can be configured in `/etc/cockpit/cockpit.conf`. For example, to log out the user after 15 minutes of inactivity:\n\n```\n[Session]\nIdleTimeout=15\n```\n\n![Automatic logout](/images/session-timeout.png)\n\nDelivered in version [209](https://cockpit-project.org/blog/cockpit-209.html) (with default timeout\nof 15 minutes, but since version [218](https://cockpit-project.org/blog/cockpit-218.html) the\ndefault timeout is disabled).\n\n[FMT_SMF_EXT.1.1 Enable/disable session timeout](https://www.niap-ccevs.org/MMO/PP/-442-/)\n\n### Show \"last login\" information upon log in\n\nCockpit displays information about the last time the account was used and how many failed login attempts for this account have occurred since the last successful login.\nThis is an important and required security feature so that users are aware if their account has been logged into without their knowledge or if someone is trying to guess their password.\n\n![Last login banner](/images/last-login-banner.png)\n\nDelivered in version [216](https://cockpit-project.org/blog/cockpit-216.html).\n\n[AU-14 Session Audit (2)](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf)\n"
  },
  {
    "path": "_posts/2020-06-10-cockpit-221.md",
    "content": "---\ntitle: Cockpit 221\nauthor: mvo\ndate: 2020-06-10\ntags: cockpit linux\nslug: cockpit-221\ncategory: release\nsummary: Cockpit with improved information protection and deprecated patternfly CSS API\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly. Here are the release notes from version 221.\n\n### Support for Cross-Origin-Resource-Policy\n\nCockpit's web server now sets the\n[Cross-Origin-Resource-Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cross-Origin_Resource_Policy_(CORP))\nheader to `same-origin`. Web browsers use this header to prevent other\nweb sites from loading individual HTML, JavaScript, or image resources\nfrom Cockpit via `<img>`, `<script>`, or similar tags. This is mostly\na precaution -- currently there are no known vulnerabilities with\nincluding resources that way, but as this is not a legitimate use\ncase, there is no reason to allow it.\n\n### Accounts: Hide some buttons when access is limited\n\nInstead of disabling the appropriate buttons when the logged in user\ndoesn't have administrative access, they will now simply disappear.\nThis is a general theme that we want to roll out all over Cockpit.\nThe Overview, Storage, and Network pages have already been changed\nlike this in earlier releases.\n\n### Developers: Importing \"base1/patternfly.css\" is deprecated\n\nThis pre-compiled stylesheet will be dropped in the future in favor of\nprojects shipping their own CSS. This API is not maintainable, as\nCockpit cannot offer a PatternFly 3 API forever, and PatternFly 4 also\nchanges quickly enough that one style sheet for all projects is not\nrobust enough.\n\nThe Cockpit plugins that are using only [PatternFly\n4](https://www.patternfly.org/v4/) should follow the example from\n[starter-kit](https://github.com/cockpit-project/starter-kit) on how\nto import [PatternFly 4](https://www.patternfly.org/v4/) stylesheets.\ng\nThe Cockpit plugins which are still relying on [PatternFly\n3](https://www.patternfly.org/v3/) should follow the migration from\nthe deprecated API to the new PatternFly stylesheet import approach as\nimplemented in this [cockpit-podman\ncommit](https://github.com/cockpit-project/cockpit-podman/commit/86fa1ee8b84ff50db0623a453de094b47a5bc2a4).\n\n### Try it out\n\nCockpit 221 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/221)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-983ae499fa)\n * [Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-9c0127be8c)\n"
  },
  {
    "path": "_posts/2020-06-24-cockpit-222.md",
    "content": "---\ntitle: Cockpit 222\nauthor: pitti\ndate: 2020-06-24\ntags: cockpit linux\nslug: cockpit-222\ncategory: release\nsummary: Cockpit with Logs filtering improvements and web server hardening\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly. Here are the release notes from version 222.\n\n### Logs: More flexible text filters\n\nThe text filter gained new `since:` and `boot:` quantifiers which restrict the logs to a given time span or the number of a previous boot; for example, `since:-12hours` or `boot:-2`. The \"Time\" dropdown controls these fields, and continues to have the same standard options as before, but they can now be customized easily.\n\nThe `service:`*unitname* filter now also accepts a unit name without the `.service` suffix. This mirrors the [systemctl](https://www.freedesktop.org/software/systemd/man/systemctl.html) command line behaviour.\n\n![Logs filtering by time and boot](/images/logs-filter-since-boot.png)\n\n### Services, Dashboard: Hide some buttons when access is limited\n\nSimilarly to previous releases, the Services and Dashboard pages will now hide buttons for privileged actions when the logged in user doesn't have administrative access.\n\n### Webserver: Lock down cockpit.service privileges\n\nThe `cockpit.service` unit which runs [Cockpit's TLS proxy](https://cockpit-project.org/guide/latest/cockpit-tls.8.html) gained several additional [privilege restriction options](https://man7.org/linux/man-pages/man5/systemd.exec.5.html). This has been tested to work with all supported authentication methods and should not cause any behaviour change/regression. If you notice problems, please [report a bug](https://github.com/cockpit-project/cockpit/issues).\n\n### Try it out\n\nCockpit 222 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/222)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-f6114a1e30)\n * [Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-0318da8e1f)\n\n *[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2020-07-08-cockpit-223.md",
    "content": "---\ntitle: Cockpit 223\nauthor: kkoukiou\ndate: 2020-07-08\ntags: cockpit linux\nslug: cockpit-223\ncategory: release\nsummary: Cockpit with web server hardening\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly. Here are the release notes from version 223.\n\n## Webserver: Standard-conformant lifetime of web server certificate\n\nCockpit's web server creates a self-signed certificate `0-self-signed.cert` on startup if the administrator did not already install one. They now are valid for one year, following the [official standard](https://www.globalsign.com/en/blog/ssl-certificate-validity-capped-at-maximum-two-years). The previous lifetime of 100 years for a self-signed certificate (or 10 years with sscg) may not be accepted by some browsers in the future.\n\nAn expired `0-self-signed.cert` is now renewed automatically.\n\n\n## Certificate authentication against Active Directory\n\nCockpit now officially supports authentication with client certificates (commonly through Smart Cards) on machines that are joined to a Microsoft or [Samba](https://www.samba.org/) [Active Directory](https://en.wikipedia.org/wiki/Active_Directory) domain. The necessary setup steps are [described in the guide](https://cockpit-project.org/guide/latest/cert-authentication.html).\n\n### Try it out\n\nCockpit 223 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/223)\n * [Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-d4e78b7bfd)\n * [Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-109902c9fa)\n"
  },
  {
    "path": "_posts/2020-07-22-cockpit-224.md",
    "content": "---\ntitle: Cockpit 224 and Cockpit Podman 20\nauthor: kkoukiou\ndate: 2020-07-22\ntags: cockpit linux\nslug: cockpit-224\ncategory: release\nsummary: Cockpit Podman new features and Cockpit bug fixes\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nCockpit 224 with bug fixes was released as well as Cockpit Podman 20. Here are release notes for Cockpit Podman 20.\n\n### Podman: Show networking information for containers\n\nContainer details now include basic networking information.\n\n![Cockpit podman networking info](/images/podman-networking-info.png){:.screenshot}\n\n_Thanks to Eric Jeffrey for this contribution!_\n\n### Podman: Enable filtering images and containers by owner\n\nFiltering between system, rootless, and all containers has been added.\n\n![Cockpit podman owner filter](/images/podman-owner-filter.png){:.screenshot}\n\n### Podman: Optionally show intermediate images\n\nIntermediate images are hidden by default, but there is a link to show them.\n\n![Cockpit podman intermediate images](/images/podman-intermediate-images.png){:.screenshot}\n\n### Podman : Enable setting up SELinux label when mounting volumes\n\nDuring container creation and volume mounting, `:z` or `:Z` labels can be specified.\nThese options tell Podman to relabel file objects on the shared volumes.\n\n![Cockpit podman intermediate images](/images/podman-selinux-label-volumes.png){:.screenshot}\n\n### Try it out\n\nCockpit 224 and Cockpit-podman 20 are available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/224)\n * [Cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/20)\n * [Cockpit Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-e8e7ea757e)\n * [Cockpit-podman Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-0e84c4f20d)\n * [Cockpit Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-47301d5f37)\n * [Cockpit-podman Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-6b6261476a)\n"
  },
  {
    "path": "_posts/2020-08-05-cockpit-225.md",
    "content": "---\ntitle: Cockpit 225 and Cockpit Podman 21\nauthor: marusak\ndate: 2020-08-05\ntags: cockpit linux\nslug: cockpit-225\ncategory: release\nsummary: Cockpit and Cockpit Podman news\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly. Here are the release notes from Cockpit version 223 and Cockpit Podman version 21.\n\n### Machines: Add support for VM snapshots\n\nCockpit now supports [libvirt's qcow2-based \"internal\" snapshotting](https://libvirt.org/formatsnapshot.html).\n\nWhen a virtual machine is not running and Cockpit makes a snapshot, only the disk contents will be saved. When a virtual machine is running, Cockpit will snapshot both the disk and memory state.\n\n![VM snapshots](/images/machines-snapshots.png){:.screenshot}\n\n### Developer API: Launch and reattach to a long-running process\n\nPages in Cockpit should never tie long-running processes to the browser's session, as the page could reload at any time, the browser tab could be closed, or the computer running the browser could be shut down. These long-running sessions, such as software installers and Ansible playbooks, should persist across Cockpit sessions.\n\nTo anyone creating a Cockpit page, please review the new [long-running process example](https://github.com/cockpit-project/cockpit/tree/master/examples/long-running-process) to ensure your page is more robust. The example demonstrates how a to handle detached sessions by running a process in a transient systemd unit and having the page attach (and re-attach, when the session changes) to the running process. Using this method allows for session interruptions.\n\nAll of this logic is implemented in a [JavaScript module](https://github.com/cockpit-project/cockpit/blob/master/pkg/lib/long-running-process.js) which we encourage you to copy into your own project.\n\n### Podman: Support for pod groups\n\nInitial support for pod groups in Cockpit has landed! The `cockpit-podman` plugin can now list pods (a group of containers) alongside the rest of the containers on a system. Basic actions like starting and pausing pods is also supported.\n\n![Cockpit pod groups](/images/podman_pods.png){:.screenshot}\n\n### Podman: Support checkpoint and restore\n\n\"Checkpointing\" stops a container and writes the state of all container processes to disk. A container can later be resumed from a checkpoint in the exact state from when the checkpoint was made. \n\nThis checkpointing capability requires [CRIU 3.11](https://www.criu.org/Main_Page) or later installed. Currently, only the `runc` container runtime is supported and also is only available with `cgroupv1` systems.\n\n![Cockpit podman checkpoint](/images/podman-checkpoint.png){:.screenshot}\n\n_Thanks to Tomáš Glozar for this contribution!_\n\n### Podman: Registry selection in \"download image\" dialog\n\nWhen downloading images, a specific registry source can be selected.\n\n![Cockpit podman registries](/images/podman-registries.png){:.screenshot}\n\n### Podman: Selected tag removal during deletion\n\nDeleting images now shows a confirmation dialog where just specific tags can be selected for removal.\n\n![Cockpit podman untag](/images/podman-untag.png){:.screenshot}\n\n### Try it out\n\nCockpit 225 and Cockpit-podman 21 are available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/225)\n * [Cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/21)\n * [Cockpit Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-77ae30c93a)\n * [Cockpit-podman Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-279a329f4c)\n * [Cockpit Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-7f840e03a3)\n * [Cockpit-podman Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-322ae82d18)\n"
  },
  {
    "path": "_posts/2020-08-19-cockpit-226-cockpit-podman-22.md",
    "content": "---\ntitle: Cockpit 226 and Cockpit Podman 22\nauthor: mvo\ndate: 2020-08-19\ntags: cockpit linux\nslug: cockpit-226\ncategory: release\nsummary: Cockpit and Cockpit Podman news\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly. Here are the release notes from Cockpit version 226 and Cockpit Podman version 22.\n\n### Storage: Better support for \"noauto\" LUKS devices\n\nCockpit better respects the LUKS \"noauto\" option for encrypted filesystems.\n\nPreviously, Cockpit would force a encrypted filesystem to mount at next boot when it was simply mounted within Cockpit. Now, encrypted filesystems set with \"noauto\" will remain unmounted during boot.\n\nPlease [refer to issue 14467](https://github.com/cockpit-project/cockpit/issues/14467) for more details.\n\n### Podman: Support for pod group deletion\n\nThe cockpit-podman plugin gained the ability to delete pod groups.\n\n![Pod group deletion](/images/podman-pod-deletion.png)\n\n### Try it out\n\nCockpit 226 and Cockpit-podman 22 are available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/226)\n * [Cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/22)\n * [Cockpit Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-635cfe8993)\n * [Cockpit-podman Fedora 31](https://bodhi.fedoraproject.org/updates/FEDORA-2020-f9f6691e27)\n * [Cockpit Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-90dcc0629f)\n * [Cockpit-podman Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-2b6de47fe5)\n"
  },
  {
    "path": "_posts/2020-09-02-cockpit-227.md",
    "content": "---\ntitle: Cockpit 227\nauthor: pitti\ndate: 2020-09-02\ntags: cockpit linux\nslug: cockpit-227\ncategory: release\nsummary: Cockpit with VM filtering and PatternFly 4 design changes\ncomments: 'true'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/). We release regularly. Here are the release notes from version 227.\n\n### Machines: Virtual machine list filtering\n\nThe Virtual Machine overview page can now be filtered by name and state.\n\n![VM filtering](/images/machines-vm-list-filter.png)\n\n### Continued PatternFly 4 migration\n\nThe Networking, Firewall, Services, and Storage pages use more [PatternFly 4](https://www.patternfly.org/v4/) elements, which improves accessibility and mobile views.\n\n### Stop Fedora 31 releases\n\nWith [Fedora 33](https://fedorapeople.org/groups/schedule/f-33/f-33-key-tasks.html) nearing Beta, and Fedora 31 nearing its end-of-life, Cockpit will no longer have updates in Fedora 31.\n\nCockpit 227 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/227)\n * [Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-5dc4f5b8f5)\n * [Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2020-02c8c858ae)\n\n *[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2020-09-16-cockpit-228.md",
    "content": "---\ntitle: Cockpit 228\nauthor: kkoukiou\ndate: 2020-09-16\ntags: cockpit linux\nslug: cockpit-228\ncategory: release\nsummary: Cockpit\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly. Here are the release notes from Cockpit version 228.\n\n### Accounts: Allow setting weak passwords\n\nCockpit now allows users to set up a weak password. The user gets notified that the password is weak, but clicking the submit button again will use the selected password anyway. This is similar to how weak passwords are handled in the Anaconda installer.\n\n![Accounts weak password](/images/accounts-weak-password.png){:.screenshot}\n\n### Changes to remote host logins\n\nCockpit used to try to log into remote hosts with your initial login password when \"Reuse my password for remote connections\" was selected during login. This option has been removed, and Cockpit does not promote password reuse across accounts anymore. Instead, Cockpit now helps with setting up SSH keys for users that want automatic and password-less login to remote hosts.\n\n![Remote host logins](/images/remote-hosts-logins.png){:.screenshot}\n\nThere is also an earlier [demo video](https://www.youtube.com/watch?v=4UBZWKk-T28) to see how it looks like in action.\n\n### Machines: Add support for reverting to and deleting VM snapshots\n\nOne can now restore a VM guest to a previously created snapshot. Existing snapshots can be deleted as well. Deleting a single snapshot preserves the current state of the VM and does not affect any other snapshot.\n\n![VM snapshot actions](/images/machines-snapshots-actions.png){:.screenshot}\n\n### Drop cockpit-docker code\n\nAs announced half a year ago in [Cockpit 215](https://cockpit-project.org/blog/cockpit-215.html),\ncockpit-docker is deprecated in favor of [cockpit-podman](https://github.com/cockpit-project/cockpit-podman).  None of the [currently supported operating systems](https://cockpit-project.org/running.html) builds the cockpit-docker package any more,\nthus it was finally removed upstream as well. If you still use it on another distribution or from upstream builds, please migrate now, or build it from an older upstream release.\n\n### Try it out\n\nCockpit 228 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/228)\n * [Cockpit Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-d185b2afc0)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2020-f617c3f387)\n"
  },
  {
    "path": "_posts/2020-09-30-cockpit-229.md",
    "content": "---\ntitle: Cockpit 229\nauthor: mvo\ndate: 2020-09-30\ntags: cockpit linux\nslug: cockpit-229\ncategory: release\nsummary: Cockpit\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly. Here are the release notes from Cockpit version 229.\n\n### Shell: Any page can be the shell\n\nCockpit has long had a configuration option to replace the default shell with something else. Shell replacement has now been documented and bugs have been fixed to allow any Cockpit page to assume the role of the shell. Additionally, this change enables support for third-party custom shells.\n\nTo see this in action with the terminal, place the following in `/etc/cockpit/cockpit.conf`:\n\n```\n[WebService]\nShell = /system/terminal.html\n```\n\n&hellip;and _nothing but the terminal_ will be shown after logging into Cockpit.\n\n![screenshot of the terminal as the shell](/images/terminal-as-shell.png)\n\n### Try it out\n\nCockpit 229 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/229)\n * [Cockpit Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-8bee823348)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2020-fde3b93273)\n"
  },
  {
    "path": "_posts/2020-10-14-cockpit-230.md",
    "content": "---\ntitle: Cockpit 230\nauthor: Gundersanne\ndate: 2020-10-14\ntags: cockpit linux\nslug: cockpit-230\ncategory: release\nsummary: Cockpit with improved storage page\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly. Here are the release notes from Cockpit version 230.\n\n### Storage: List entries from /etc/crypttab that are still locked\n\nCockpit now lists those encrypted devices in the overview that are still\nlocked. This makes them easy to find if you want to unlock them manually.\n\n<iframe width=\"960\" height=\"720\" src=\"https://www.youtube.com/embed/mmFOTQ39ZPk\" frameborder=\"0\" allowfullscreen></iframe>\n\n### Try it out\n\nCockpit 230 and Cockpit-podman 25 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/230)\n * [Cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/25)\n * [Cockpit Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-c4d3552a8b)\n * [Cockpit-podman Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-e58f6d67de)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2020-ae649e602e)\n * [Cockpit-podman Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2020-5fd4e6c410)\n\nCockpit-podman also had a release:\n\n\n"
  },
  {
    "path": "_posts/2020-10-29-cockpit-231.md",
    "content": "---\ntitle: Cockpit 231\nauthor: marusak\ndate: 2020-10-29\ntags: cockpit linux\nslug: cockpit-231\ncategory: release\nsummary: Cockpit with new performance graphs\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly. Here are the release notes from Cockpit version 231.\n\n### Replace system's graph page with a completely new USE method page\n\nThe system graphs were replaced with a dedicated page for analyzing the current and historical performance of a machine. This page (reachable after clicking on 'View details and history' on the Overview page) shows current metrics as well as historical events based on the [USE](http://www.brendangregg.com/usemethod.html) method.\n\n![performance_graphs](/images/perf-graphs.png){:.screenshot}\n\n### Machines: Reimplement the design of the main VMs list\n\nDetails of virtual machines are now displayed on a separate page that contains all information in one\nplace. There is no need anymore to change between tabs to see different properties of a virtual machine.\n\n![VM subpage](/images/vm-details.png){:.screenshot}\n\n### Logging of remote IP addresses\n\nCockpit records the remote IP address for user logins (and failed attempts) again. The IP address will appear in the system logs, in the output of tools such as `w` or `who`, and in the login-time messages about when the last successful login happened, and any failed login attempts. It also means that PAM modules can filter logins based on IP address (for example, temporarily blocking a subnet when there are too many failed login attempts).\n\n### Try it out\n\nCockpit 231 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/231)\n * [Cockpit Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-689ad5b15a)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2020-397165407a)\n"
  },
  {
    "path": "_posts/2020-11-11-cockpit-232.md",
    "content": "---\ntitle: Cockpit 232\nauthor: kkoukiou\ndate: 2020-11-11\ntags: cockpit linux\nslug: cockpit-232\ncategory: release\nsummary: Cockpit with Dashboard and Machines improvements\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly. Here are the release notes from Cockpit version 232.\n\n### Improved host editing\n\nWhen editing the parameters of a host in the Shell or the Dashboard pages,\nCockpit no longer tries to change the name of the remote host.\nInstead, it will now connect to the newly-entered hostname.\n\n![edit host new](/images/edit-host-new.png){:.screenshot}\n\n### Machines: Inline error messages\n\nError notifications for machines, storage pools and virtual networks are now displayed\nin a popover next to the resource's state.\n\n![VM notifications](/images/vm-error-notification-inline.png){:.screenshot}\n\n### Try it out\n\nCockpit 232 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/232)\n * [Cockpit Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-fbe8868890)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2020-d100b57cac)\n"
  },
  {
    "path": "_posts/2020-11-25-cockpit-233.md",
    "content": "---\ntitle: Cockpit 233\nauthor: lis\ndate: 2020-11-25\ntags: cockpit linux\nslug: cockpit-233\ncategory: release\nsummary: Cockpit with various bug fixes and performance improvements\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly. Here are the release notes from Cockpit version 233.\n\n### Non-admin users no longer see Cockpit in motd\n\nThe motd message suggesting how Cockpit can be enabled or used is now\nshown only to admin users.  This depends on PAM 1.5.0 (which is not yet\nreleased) but the needed patches have been backported to Fedora 33 and\nmay land in other distributions in the future.\n\n## Developers: jQuery removal\n\n[As previously announced](https://cockpit-project.org/blog/cockpit-163.html), we have finally removed the long-deprcated `../base1/jquery.js` API from Cockpit. The bundled version is no longer built or shipped. If you are using jQuery in your application, be sure to build against your own copy.\n\nAll known projects which used this API were ported away two years ago already.\n\n[Read more details in the original announcement](https://lists.fedorahosted.org/archives/list/cockpit-devel@lists.fedorahosted.org/thread/TDBKI4372I4ZPGQFCZB377DX2QG2YDDY/).\n\n### Try it out\n\nCockpit 233 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/233)\n * [Cockpit Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-7e9135f27c)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2020-78807dbfdb)\n"
  },
  {
    "path": "_posts/2020-12-09-cockpit-234.md",
    "content": "---\ntitle: Cockpit 234 and Cockpit-Podman 26\nauthor: mvo\ndate: 2020-12-09\ntags: cockpit linux\nslug: cockpit-234\ncategory: release\nsummary: Cockpit with various bug fixes and performance improvements\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).  We release regularly.\n\nHere are the release notes from Cockpit version 234 and Cockpit-Podman 26.\n\n## Machines: Select virtual machine CPU mode and model\n\nThe Virtual Machines page now has the option to select a CPU model. \n\nChoosing a strategy may maximize performance, protect against various CPU hardware flaws, and allow for live migration between hosts with similar CPU models.\n\nThree different options are supported:\n\n- **Host passthrough**\n  The host CPU model, features, and stepping are passed directly to the guest. This is the fastest mode, but lacks compatibility for live migration of VMs to another host.\n\n- **Host model**\n  This balanced mode, also known as QEMU's \"named model\", makes tradeoffs to ensure live migration is safe while attempting to preserve performance. It does this by choosing a _compatible_&mdash;but not necessarily _identical_&mdash;CPU family, stepping, and feature set with the host and tries to preserve as much passthrough as possible.\n\n- **Custom / Named model**\n  Selecting a specific named CPU model maximizes the flexibility to live migrate between hosts with differing hardware, by abstracting the simulated CPU from the host's own CPU. The list of CPU models comes directly from QEMU and referrers to specific generations of hardware released by Intel and AMD.\n\nMore information about CPU model selection can be found in the [QEMU documentation page](https://www.qemu.org/docs/master/system/qemu-cpu-models.html).\n\n![screenshot of the cpu mode configuration](/images/machines-cpu-model.png)\n\n## Machines: Add support for cloning virtual machines\n\nCloning copies a virtual machine into a new VM, duplicating configuration and storage. After cloning, the original VM and its clone are nearly identical, with the exception of the few configuration changes that need to differ.\n\nVirtual machine cloning is often used for preparing an optimal virtual machine and then quickly spinning up several similar VMs without having to step through an installation process.\n\n![screenshot of the machine cloning](/images/machines-cloning.png)\n\n## The dashboard has been removed\n\nDue to limited functionality, the dashboard page has been removed. Connecting to additional hosts is directly available in the Shell without the need for a separate package. The dashboard graphs were not providing enough information to be useful and were implemented with a performance cost on the servers and the browser. Individual machine metrics are available on a separate page on the Overview page. Multi-host monitoring is handled better by other tools (e.g. Grafana), which provide more useful data.\n\n## Podman: Set IP address when exposing container ports\n\nThe Cockpit-Podman add-on now supports binding a container's ports to a specific host IP address. If the host IP is unset or set to `0.0.0.0`, the port will be bound on all IPs on the host.\n\n![screenshot of port IP configuration](/images/podman-ip-for-ports.png)\n\n### Try it out\n\nCockpit 234 and Cockpit-Podman 26 are available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/234)\n * [Cockpit Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-ea1ee62c3d)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2020-d10db68200)\n * [Cockpit-Podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/26)\n * [Cockpit-Podman Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2020-c37784f036)\n * [Cockpit-Podman Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2020-1089febeaf)\n"
  },
  {
    "path": "_posts/2021-01-07-cockpit-235.md",
    "content": "---\ntitle: Cockpit 235\nauthor: pitti\ndate: 2021-01-07\ntags: cockpit linux\nslug: cockpit-235\ncategory: release\nsummary: Cockpit with SSH key improvements and motd editing\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).  We release regularly.\n\nHere are the release notes from Cockpit version 235.\n\n## Login: Improved handling of SSH host keys\n\nThis release improves key management while logging into secondary hosts. The log in screen now explains unknown and altered keys&mdash;and also how to verify these new keys. Browsers remember accepted keys in client-side storage to improve the user experience.\n\n![login page SSH fingerprint](/images/login-fingerprint.png)\n\n## Overview: Editable motd\n\nThe Overview page's motd now has an edit button to change `/etc/motd`.\n\n*[motd]: message of the day\n\n![Overview motd editing](/images/overview-motd-edit.png)\n\n### Try it out\n\nCockpit 235 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/235)\n * [Cockpit Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2021-ef799c5b6b)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-281e7c7bb6)\n"
  },
  {
    "path": "_posts/2021-01-21-cockpit-236.md",
    "content": "---\ntitle: Cockpit 236\nauthor: pitti\ndate: 2021-01-22\ntags: cockpit linux\nslug: cockpit-236\ncategory: release\nsummary: Cockpit with SSH key improvements and motd editing\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).  We release regularly.\n\nHere are the release notes from Cockpit version 236.\n\n## fslist channels: Include properties of changed files\n\nThe [fslist channel API](https://github.com/cockpit-project/cockpit/blob/master/doc/protocol.md#payload-fslist1) lists files in a directory, watches for further changes to files, and sends events when changes happen. These notifications now include additional properties about the file: the owner and group name, file size, and time of last modification.\n\nThis contribution from leomoty can serve as the basis of a third-party file manager page. _Thanks, leomoty!_\n\n## Internal stabilization work\n\nThe Cockpit authors spent a lot of time on refactoring, dropping some obsolete dependencies like [jquery-flot](https://www.npmjs.com/package/jquery-flot), replacing some custom React components with standard [PatternFly](https://www.patternfly.org/v4/) ones, build system simplifications, and test stabilization. These don't have a user-visible effect, but will make Cockpit easier to develop in the future.\n\n### Try it out\n\nCockpit 236 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/236)\n * [Cockpit Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2021-fe1bd864ea)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-3408685d15)\n"
  },
  {
    "path": "_posts/2021-02-03-cockpit-237.md",
    "content": "---\ntitle: Cockpit 237\nauthor: marusak\ndate: 2021-02-03\ntags: cockpit linux\nslug: cockpit-237\ncategory: release\nsummary: Cockpit with restyled updates page\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).  We release regularly.\n\nHere are the release notes from Cockpit version 237.\n\n## Updates: Restyling in preparation for upcoming features\n\nThe updates page went through some design polishing in preparation for upcoming features.\n\n![Restyled updates page](/images/updates-restyled.png)\n\n## Shell: SSH connections to remote machines are only opened when necessary\n\nCockpit remembers all remote hosts of a session and would previously connect to all of them\nwhen starting the next session. Now an SSH connection is only opened when navigating to the remote\nmachine for the first time. This restricts possible security issues, as connected hosts can\ninteract with each other.\n\n## Internal CI improvements\n\nIn the last two weeks, the team has been focusing heavily on stabilizing and improving our CI. These\nimprovements include work on self-testing CI infrastructure as well as [defining](https://github.com/cockpit-project/cockpit/wiki/DevelopmentPrinciples#our-testsci-error-budget) and [implementing](https://images-frontdoor.apps.ocp.ci.centos.org/tests.html) an [error budget](https://sre.google/sre-book/embracing-risk/). These changes don't have a user-visible effect,\nbut will make Cockpit easier to develop in the future. Also we continued working on tests and build system improvements.\nOn top all of that there is a bug fix in websocket; _thanks to Asad Mehmood for that contribution!_\n\n### Try it out\n\nCockpit 237 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/237)\n * [Cockpit Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2021-98c970e99a)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-0ad93a9b1e)\n"
  },
  {
    "path": "_posts/2021-02-16-cockpit-238.md",
    "content": "---\ntitle: Cockpit 238\nauthor: kkoukiou\ndate: 2021-02-17\ntags: cockpit linux\nslug: cockpit-238\ncategory: release\nsummary: Cockpit with restyled updates page\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).  We release regularly.\n\nHere are the release notes from Cockpit version 238.\n\n### Updates: List outdated software that needs a restart\n\nCockpit now uses [Tracer](http://tracer-package.com/) to discover outdated services and applications after each software update.\n\nIn some cases, software updates might not require a reboot or any services to be restarted.\n\n![Update no restart](/images/update-no-restart.png)\n\nWhen necessary, Cockpit will prompt to restart services or schedule a system reboot.\n\n![Update with restart](/images/update-with-restart.png)\n\nCurrently, Tracer is only supported in Fedora.  In distributions where Tracer is not available, Cockpit will reboot after software updates, as it has previously done.\n\n### Web server: Preserve permissions of administrator-provided certificates\n\nCockpit's web server supports and encourages [using your own TLS certificate and key](/guide/latest/https.html#https-certificates) in `/etc/cockpit/ws-certs.d/`.\ncertificates. \n\nFor enhanced compatibility with other software, Cockpit has been changed to only adjust permissions for certificates it creates and manages itself. These specific files are `0-self-signed.cert` and `10-ipa.cert`. If you do provide your own certificate, you must ensure these files are readable by the `cockpit-ws` user or group, in addition to other software using the certificates.\n\n### System: Performance page shows busiest CPU cores\n\n![CPU cores metrics](/images/metrics-cores.png)\n\n### Machines: VM disk creation supports a custom path\n\nCustom paths are now supported when adding disks to a VM. Supported file types include disk files (qcow, qcow2, and raw images) and CD/DVD ISOs (which will be attached as a CD-ROM device).\n\n![Machines](/images/disk-iso.png)\n\n### Try it out\n\nCockpit 237 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/238)\n * [Cockpit Fedora 32](https://bodhi.fedoraproject.org/updates/FEDORA-2021-f98214dae5)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-bf4a30e37d)\n * [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-db6f42b9df)\n"
  },
  {
    "path": "_posts/2021-03-03-cockpit-239.md",
    "content": "---\ntitle: Cockpit 239\nauthor: lis\ndate: 2021-03-03\ntags: cockpit linux\nslug: cockpit-239\ncategory: release\nsummary: Cockpit with various improvements\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).  We release regularly.\n\nHere are the release notes from Cockpit version 239.\n\n## Terminal: Support for changing the font size\n\nUsers can now change the font size in the emulator window on the\nterminal page.\n\n![New font size selector in the terminal](/images/terminal-font-size.png)\n\n### Machines: Allow editing disk cache mode\n\nIt's now possible to edit the cache mode for existing virtual machine\ndisks.  This was previously only possible when creating new disks.  In\norder to edit the cache mode, any machines using the volume need to be\npowered off.\n\n![Cache mode editing for machines](/images/edit-vm-cache-mode.png)\n\n### Logs: Link to related services page\n\nThe detailed view for log entries now links to related services, when\napplicable.\n\n![Log entry linking to service](/images/log-link-to-service.png)\n\n### SELinux: Restyle to resemble other pages\n\nThe SELinux page now matches the style of other pages in Cockpit.\npages in Cockpit.\n\n![SELinux page with the new style](/images/selinux-restyled.png)\n\n### Packaging: Removed ./configure options for distribution-specific packages\n\nThe `./configure` script dropped several distribution-specific options:\n\n- `--with-vdo-package`\n- `--with-nfs-client-package`\n- `--with-appstream-config-packages`\n- `--with-appstream-data-packages`\n\nManifest files now contain this same information, which is more portable across distributions.\n\nAdministrators can still adjust these values in `override.json` files.\n\n\n### Try it out\n\nCockpit 239 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/239)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-3eac86a1e3)\n * [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-1f7c0290a1)\n"
  },
  {
    "path": "_posts/2021-03-17-cockpit-240.md",
    "content": "---\ntitle: Cockpit 240\nauthor: mvo\ndate: 2021-03-17\ntags: cockpit linux\nslug: cockpit-240\ncategory: release\nsummary: Cockpit with various improvements\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).  We release regularly.\n\nHere are the release notes from Cockpit version 240.\n\n## New localization: Norwegian Bokmål\n\nCockpit is now also available in Norwegian Bokmål localization. Thank\nyou Stein-Aksel Basma for this contribution!  Cockpit is being\ntranslated in [Weblate](https://translate.fedoraproject.org/projects/cockpit/master/),\nwhere anyone can help to improve Cockpit.\n\n## Performance metrics: Journal integration\n\nThe Metrics page identifies high CPU, memory, disk, and network resource usage. Now you can expand each of these \"spikes\" to view related log entries, to help identify resource hogs.\n\n![Journal entries for an event](/images/metrics-journal.png)\n\n## Machines: Cloud image authentication\n\nDistro cloud images have no login accounts by default. The user can\nnow specify the root and user account login credentials, which will be\npassed to [cloud-init](https://cloud-init.io/).\n\n![Cloud image account initialization](/images/cloud-init.png)\n\n### Try it out\n\nCockpit 240 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/240)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-5bbe040d32)\n * [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-03343cebaf)\n"
  },
  {
    "path": "_posts/2021-03-31-cockpit-241.md",
    "content": "---\ntitle: Cockpit 241\nauthor: skobyda\ndate: 2021-03-31\ntags: cockpit linux\nslug: cockpit-241\ncategory: release\nsummary: Cockpit with various improvements\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).  We release regularly.\n\nHere are the release notes from Cockpit version 241.\n\n## Kdump: Beautification and alignment fixes\n\nThis release improves the Kdump page, used for easier kernel debugging. The reworked page now matches the style of the rest of Cockpit and fixes alignment issues.\n\n![Cloud image account initialization](/images/kdump-redesign.png)\n\n## Start of TLS certificate improvements\n\nCockpit is starting the process of transitioning away from its (somewhat unique) \"merged\" form of certificate files, towards the more usual separate files for the certificate and the private key. This release changes the IPA certificate setup to use the split format, as well as setting the correct permissions at the time the certificate is created.\n\nWatch for more progress on this front in coming releases.\n\n### Try it out\n\nCockpit 241 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/241)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-d610c3d956)\n * [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-ea47afc582)\n"
  },
  {
    "path": "_posts/2021-04-05-fmf-unified-testing.md",
    "content": "---\ntitle: Unified upstream and downstream testing with tmt and Packit\nauthor: pitti\ndate: 2021-04-05\ncategory: howto\ntags: qa testing gating distribution fmf tmt fedora packit\n---\n\nAutomated package update gating can tremendously increase the quality of a Linux distribution. (Gated packages are only accepted into a distribution when tests pass.)\n\nTwo and a half years ago, we started to [gate the Fedora cockpit package on our browser integration tests](https://src.fedoraproject.org/rpms/cockpit/c/f639e531f9357e1a42ce7a050726d520c1586535). We have continued to increase the number of tests ever since.\n\nI'm especially happy gating is now in Fedora, as I had worked on [testing in Ubuntu](https://wiki.ubuntu.com/ProposedMigration) and [Debian](https://ci.debian.net/status/) [many years ago](https://piware.de/2011/11/12-04-testing-ftw/). (Adoption is a bit slower in Fedora, as it does not do reverse dependency gating *yet*.)\n\n## Fedora gating woes\n\nBut there's a problem of scale: The more tests we added to gating, the more likely it became that any one of them would fail. Fedora's distribution gating tests also failed at the worst possible time: After an upstream release. It felt like every single Bodhi update in the last year had failing tests. I couldn't remember a single time when tests were green.\n\nFedora's test VMs use different settings from Cockpit's, such as the number of CPUs and amount of RAM, or the list of preinstalled packages. The time it takes to perform each test varies as well. For example: Fedora's testing VMs (running on EC2) are notably slow during evenings in Europe.\n\nRunning Fedora's tests locally requires know-how and tricks:\n\n- How is the test environment defined and configured?\n- Where can someone download the gating VM images?\n- How do I start them to get a similar environment as the CI system?\n\nFedora's [Standard Test Interface](https://docs.fedoraproject.org/en-US/ci/standard-test-interface/) was flexible and precise when covering the API, but lacked pinning down the test environment. The documentation more or less says \"just run `ansible-playbook` in a VM\", but there is no tool to provide such a VM.\n\nIt was time to fix this once and for all.\n\n## Fix: Run distribution tests upstream\n\nThe concept to fix the tests is simple:\n1. Pin down the environment where these tests run, and provide a tool to create and use them.\n2. Make it trivial to locally run and debug a package’s gating tests.\n3. Run gating tests for *every* upstream change (i.e. pull request), using *the exact same* environment, test metadata, and configuration.\n\nI'm happy to say that, after a lot of work from several different teams, all these now exist!\n\n## Flexible Metadata Format\n\n[FMF](https://tmt.readthedocs.io/en/latest/spec.html) (Flexible Metadata Format) is the successor of the Ansible-based Standard Test Interface. FMF is declarative YAML and distribution/project agnostic. The \"flexible\" in FMF is rich, so that (by design) it does not limit what tests can do or where to they run. Despite its complexity, most settings have good defaults, so you don’t need to know about every detail.\n\nWe first added FMF to Cockpit's [starter kit](https://github.com/cockpit-project/starter-kit/commit/09823650e222da0). As a reference, the central file is [`test/browser/main.fmf`](https://github.com/cockpit-project/starter-kit/blob/master/test/browser/main.fmf). This lists the test dependencies, the entry script, and a timeout:\n\n```yaml\nsummary:\n    Run browser integration tests on the host\nrequire:\n  - cockpit-starter-kit\n  [...]\n  - npm\n  - python3\ntest: ./browser.sh\nduration: 60m\n```\n\nTranslating from [the STI Ansible tests.yml](https://src.fedoraproject.org/rpms/cockpit/blob/d6853f04e1184f562f872c5c765f40644ef5edc8/f/tests/tests.yml) is straightforward. The STI configuration looked like this:\n\n```yaml\n- hosts: localhost\n  roles:\n  - role: standard-test-source\n    tags:\n    - always\n\n  - role: standard-test-basic\n    tags:\n    - classic\n    required_packages:\n    - cockpit\n    [...]\n    - npm\n    - python3\n    tests:\n    - verify:\n        dir: .\n        run: ./verify.sh\n        save-files: [\"logs/*\"]\n```\n\nAside from the above, there's a little bit of boilerplate needed:\n\n- `.fmf/version` (just “1”)\n- At least one top-level [`plans/*.fmf`](https://github.com/cockpit-project/starter-kit/blob/master/plans/all.fmf). This can be the same for every project. Hopefully, it may be the implied default some day.\n\nThis test metadata format provides underpinnings for the following new tools.\n\n## Test Management Tool\n\n[Test Management Tool](https://docs.fedoraproject.org/en-US/ci/tmt/) (tmt) addresses the first two points (pinning the environment and running locally). If a project has FMF metadata for its tests, running tmt as simple as:\n\n```sh\ntmt run\n```\n\nThe tool then:\n\n1. downloads a standard Fedora development series VM (34 at the moment)\n2. starts it in libvirt/QEMU\n3. runs your tests inside the VM\n4. produces a live log while the test is running\n5. copies out all the test logs and artifacts\n6. cleans up everything in the previous steps\n\n### tmt customization\n\nThe run command uses a lot of defaults, but supports customization.\n\n**Example 1**: Run on a different Fedora release:\n\n```sh\ntmt run --all provision --how virtual --image fedora-33\n```\n\n**Example 2**: Run the steps until the report stage (thus skipping finish). This allows you to ssh into the test VM and investigate failures.\n\n```sh\ntmt run --until report\ntmt run -l login\n```\n\nSee `--help` and the documentation for details.\n\nUntil recently, this only worked with `qemu:///system` libvirt. (That is: not in containers or [`toolbox`](https://docs.fedoraproject.org/en-US/fedora-silverblue/toolbox/).)\n\nThe latest testcloud and tmt versions have switched to `qemu:///session` by default. (Thanks to Petr Šplíchal for responding to my nagging so quickly!) Using session enables tmt to run without root privileges, bridges, or services.\n\n## Packit\n\n[Packit](https://packit.dev/) is a tool and a service to automatically package upstream releases into Fedora or Copr.\n\nIt recently learned a cool new trick: The [Packit-as-a-Service GitHub app](https://github.com/marketplace/packit-as-a-service) runs a project's FMF test plans in pull requests. Packit-as-a-Service is open source, [simple to set up](https://packit.dev/docs/packit-as-a-service/), and free to use. For projects that use it, this addresses point 3 above (running gating tests for every upstream change).\n\nTests run on the [testing-farm](https://testing-farm.gitlab.io/api/), which provides reasonable (1 CPU, 2 GiB RAM) AWS EC2 instances. Critically, this is the exact same  infrastructure that the Fedora gating tests use.  This is by design. It’s easier to maintain one testing farm than two sets of infrastructure. Using the same infrastructure provides the necessary reproducibility for project maintainers.\n\nLike Travis or GitHub workflows, your project only needs to add a packit.yaml file. For example, here's Cockpit starter-kit’s:\n\n```yaml\nspecfile_path: cockpit-starter-kit.spec\nactions:\n  post-upstream-clone: make cockpit-starter-kit.spec\n  # reduce memory consumption of webpack in sandcastle container\n  # https://github.com/packit/sandcastle/pull/92\n  # https://medium.com/the-node-js-collection/node-js-memory-management-in-container-environments-7eb8409a74e8\n  create-archive: make NODE_OPTIONS=--max-old-space-size=500 dist-gzip\n  # starter-kit.git has no release tags; your project can drop this once you have a release\n  get-current-version: make print-version\njobs:\n  - job: tests\n    trigger: pull_request\n    metadata:\n      targets:\n      - fedora-all\n```\n\nThe YAML above binds together:\n\n- the knowledge how to produce an upstream release tarball from your branch\n- where the spec file is\n- which Fedora releases to run tests in a PR\n\n\nPackit will then use this information to:\n\n1. build the tarball (`create-archive`)\n2. build an SRPM with the spec file\n3. build the SRPM in a temporary Copr\n4. use tmt to run your tests against these built RPMs\n\nFor an upstream project relying on tests, it can’t get much simpler!\n\n### An in-practice example with starter-kit\n\nAs an example: Look at a [recent starter-kit PR](https://github.com/cockpit-project/starter-kit/pull/442). Click on “View Details” to expand the tests. It shows four Packit runs.\n\nIt's great, but not yet perfect. It is still not obvious how to get from such a [result link](http://artifacts.dev.testing-farm.io/f24bede3-995e-4f10-970f-dc849e950e3a/) to all artifacts.\n\nMinor quality-of-life improvements that are likely forthcoming:\n\n- Finding test artifacts (for now, look at the log to find out the path to the `/work-allXXXXXX` directory and append that to the URL)\n- Seeing [live logs while a test is running](https://gitlab.com/testing-farm/general/-/issues/13)\n\n\n\n## Recent Fedora CI changes\n\nAs mentioned above, Fedora's gating tests are now using the exact same testing farm as Packit. This recent switch allows the test to run in the same environment. It also supports the new FMF+tmt test metadata and the legacy STI format.\n\nThese changes get us close to the goal of sharing tests upstream and downstream.\n\n### Missing: embedded test support\n\nWhile it's almost complete, there is a missing part. There is no current clean way to run tests contained in the upstream tarball.\nRight now, the packaging dist-git must have a [top-level FMF test plan](https://src.fedoraproject.org/rpms/cockpit/blob/rawhide/f/plans/upstream.fmf) like this:\n\n```yaml\ndiscover:\n  how: fmf\n  repository: https://github.com/cockpit-project/cockpit\n  # FIXME: get rid of the hardcoding: https://github.com/psss/tmt/issues/585\n  ref: \"241\"\nexecute:\n  how: tmt\n```\n\nThe workaround, seen in the above snippet, uses tests from a specific tag in the upstream project git. The git tag must match the release in the spec file, to keep tests in-sync with the tested packages. This is awkward, as it requires accessing a remote git (at a specific tag), even though tests exist in the source tarball.\n\nChanging this requires some [tmt design discussion](https://github.com/psss/tmt/issues/585). For now, we [hacked our release scripts](https://github.com/cockpit-project/cockpituous/commit/2ef3f6c99912) to bump up the test plan's `ref:`  when committing a new release to dist-git. If you use this in your project, you need similar \"magic\" or always update the test plan’s `ref:` along with your spec file.\n\nEven with this hack, Cockpit’s [commit to move from STI to upstream FMF](https://src.fedoraproject.org/rpms/cockpit/c/0fee2830080033ea2be13be30d156b51dcf75b7d) was still a major net gain. Cockpit's tests run straight from upstream now.\n\n## Putting it all together\n\nCockpit’s [starter-kit](https://github.com/cockpit-project/starter-kit/#running-tests-in-ci), the basis for creating your own Cockpit UIs, implements this all now: FMF metadata, [setup scripts](https://github.com/cockpit-project/starter-kit/tree/master/test/browser), [packit.yaml](https://github.com/cockpit-project/starter-kit/blob/master/packit.yaml), and [documentation](https://github.com/cockpit-project/starter-kit#running-tests-in-ci).\n\n[Doing the same for Cockpit itself](https://github.com/cockpit-project/cockpit/pull/15504) was more involved, because packit’s `create-archive` step has limits: it needs to work in a 768 MiB VM and finish within 30 minutes, but for larger projects this is not enough for webpack. Instead, [a GitHub workflow builds the tarballs](https://github.com/cockpit-project/cockpit/blob/master/.github/workflows/build-dist.yml) and Packit downloads the pre-built artifacts. (We want to do that anyway, as pre-building is useful for speeding up reviews and local development as well.)\n\nThe VM constraints are not an issue for smaller projects like [cockpit-podman](https://github.com/cockpit-project/cockpit-podman). The entire webpack build does fit within packit's limits.\n\nIt should also not be an issue for most C/Python/etc. projects where `make dist` (or `meson dist`, `./setup.py sdist`, etc.) will usually be quick and lean.\n\nFinally, we were able to collect the prize... Thanks to the new testing frameworks, Cockpit release 241 [passed Fedora gating tests](https://bodhi.fedoraproject.org/updates/FEDORA-2021-abd3934d7b) for the first time in roughly a year! 🎉\n\n## Conclusion\n\nThere are finally tools to for cloud-first, proper, consistent, and free upstream/downstream CI... and all without having to maintain your own infrastructure! This is a major milestone and motivator. There's now no excuse to ship any more broken stuff! 😀\n\nMany thanks in particular to [Petr Šplíchal](https://github.com/psss) (testcloud/tmt), [Tomas Tomecek](https://github.com/TomasTomecek/) (packit), and [Miroslav Vadkerti](https://github.com/thrix) (Testing Farm) for tirelessly fixing stuff, responding to my nagging, and helping me with figuring out how it all hangs together!\n\n*[AWS]: Amazon Web Services\n*[CI]: continuous integration (testing)\n*[Copr]: A build service for unofficial / semi-official Fedora community projects. It's a portmanteau, short for \"Community Projects\". Pronounced like the metal \"copper\".\n*[EC2]: Amazon Elastic Compute Cloud\n*[FMF]: Flexible Metadata Format\n*[SRPM]: source RPM\n*[STI]: Fedora's Standard Test Interface\n*[tmt]: test management tool\n*[VM]: virtual machine\n*[VMs]: virtual machines\n*[tmt]: test management tool\n"
  },
  {
    "path": "_posts/2021-04-14-cockpit-242.md",
    "content": "---\ntitle: Cockpit 242\nauthor: marusak\ndate: 2021-04-14\ntags: cockpit linux\nslug: cockpit-242\ncategory: release\nsummary: Cockpit with split out Machines page and website refresh\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).  We release regularly.\n\nHere are the release notes from Cockpit version 242.\n\n\n## Groundwork for Snowpack support\n\n[Snowpack](https://www.snowpack.dev/) is a web project build system alternative to [webpack](https://webpack.js.org/). Previously, when using Snowpack to build Cockpit pages using an [npm module](https://www.npmjs.com/) with an `@`, the page [could not be loaded](https://github.com/cockpit-project/cockpit/issues/15288). This has been fixed. As Cockpit uses [@patternfly](https://www.npmjs.com/package/@patternfly/react-core) in this style, it was an important first step.\n\nPlease be aware that there is not a fully working and supported example of a Snowpack-built Cockpit project at this time, just some [initial experimentation](https://piware.de/post/2021-02-05-snowpack/).\n\n\n## Machines: Split out to separate project\n\nThe Machines page is easily the largest Cockpit component. It has been split out to the standalone [cockpit-machines project](https://github.com/cockpit-project/cockpit-machines/), making it easier and faster to develop. This same split has also happened in [Fedora](https://bodhi.fedoraproject.org/updates/?packages=cockpit-machines) and [Debian](https://tracker.debian.org/pkg/cockpit-machines) packaging.\n\n## Cockpit website refresh\n\n[Cockpit website](https://cockpit-project.org/) has been restyled and refreshed. This update includes:\n- a fresh style\n- completely new content on the front page\n- updated screenshots\n- a brand new [docs page](https://cockpit-project.org/documentation.html)\n\n## Cockpit ecosystem updates\n\nToday, we're also releasing new versions of [cockpit-podman](https://github.com/cockpit-project/cockpit-podman/releases/tag/30), [cockpit-ostree](https://github.com/cockpit-project/cockpit-ostree/releases/tag/185), and the newly-independent [cockpit-machines](https://github.com/cockpit-project/cockpit-machines/releases/tag/243).\n\n\n### Try it out\n\nCockpit 242 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/242)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-d230b3a6a0)\n * [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-4bcccbe0bd)\n"
  },
  {
    "path": "_posts/2021-04-28-cockpit-243.md",
    "content": "---\ntitle: Cockpit 243\nauthor: pitti\ndate: 2021-04-28\ntags: cockpit linux\nslug: cockpit-243\ncategory: release\nsummary: Cockpit with Services page improvements\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).  We release regularly.\n\nHere are the release notes from Cockpit version 243.\n\n## Services: Show sockets and memory usage\n\nSocket units show listening paths and ports, as well as the service units they activate.\n\n![Socket unit listening path](/images/services-socket-listen.png)\n\nService units show memory usage and which socket unit activated them.\n\nLess important static relationships like \"Requires:\" are collapsed by default, making it easier to see the journal output.\n\n![Service memory usage](/images/services-mem-usage.png)\n\n## Developer API: Watch for file changes without reading\n\nThe [cockpit.file.watch() API](https://cockpit-project.org/guide/latest/cockpit-file.html#cockpit-file-notify) can be used to update a Cockpit page when files change. This has always read the file and returned the contents in a handler function.\n\nReading files is impractical in many cases, as contents may be unimportant or a file could be large (for example a database). Therefore, the watch API has gained a `read` option to disable the automatic reading. When `read` is set to `false`, the callback's `content` will always be `null`.\n\n### Try it out\n\nCockpit 243 is available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/243)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-58213e627d)\n * [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-ad68878262)\n"
  },
  {
    "path": "_posts/2021-05-06-pixel-tests.md",
    "content": "---\ntitle: Testing all the pixels\nauthor: mvo\ndate: 2021-05-06 10:00\ntags: cockpit\nslug: pixel-testing\ncategory: tutorial\ncomments: 'true'\n---\n\nThe Cockpit integration tests can now contain \"pixel tests\". Such a\n test will take a screenshot with the browser and compare it with a\n reference.  The idea is that we can catch visual regressions much\n easier this way than if we would hunt for them in a purely manual\n fashion.\n\n## Preparing a repository for pixel tests\n\nA pixel test will take a screenshot of part of the Cockpit UI and\ncompare it with a reference.  Thus, these reference images are\nimportant and play the biggest role.\n\nA large part of dealing with pixel tests will consequently consist of\nmaintaining the reference images.  At the same time, we don't want to\nclog up our main source repository with them.  While the number and\nsize of the reference images at any one point in time should not pose\na problem, we will over time accumulate a history of them that we are\nafraid would dominate the source repository.\n\nThus, the reference images are not stored in the source repository.\nInstead, we store them in an external repository that is linked into\nthe source repository as a\n[submodule](https://git-scm.com/book/en/v2/Git-Tools-Submodules).\nThat external repository doesn't keep any history and can be\naggressively pruned.\n\nDevelopers are mostly isolated from this via the new\n`test/common/pixel-tests` tool.  But if you are familiar with git\nsubmodules, there should be no surprises for you here.\n\nA source repository needs to be prepared before it can store reference\nimages in a external storage repository. You can let the tool do it by\nrunning\n\n```\n$ ./test/common/pixel-tests init\n```\n\nand then committing the changes it has done to the source repository.\n(Those changes will be a new or modified .gitmodules file, and a new\ngitlink at test/reference.)\n\n## Adding a pixel test\n\nTo add a pixel test to a test program, call the new \"assert_pixels\"\nfunction of the Browser class:\n\n```py\n    def testSomeDialog(self):\n        ...\n        self.browser.assert_pixels('#dialog button.apply', \"button\")\n        ...\n```\n\nThe first argument is a CSS selector that identifies the part of the\nUI that you want to compare.  The screenshot will only include that\nelement.  The second argument is an arbitrary but unique key for this\ntest point.  It is used to name the files that go with it.\n\nFor each such call, there needs to be a reference image in the\n`test/reference/` directory.\n\nAs mentioned above, the `test/reference/` directory is very special\nindeed, and needs to be carefully managed with the\n`test/common/pixel-tests` tool (or even more carefully with `git\nsubmodule` et al).\n\nFirst, make sure `test/reference` is up-to-date:\n\n```\n$ ./test/common/pixel-tests pull\n```\n\nThen you can add new reference images to it.\n\nThe easiest way to get a new reference image is to just run the test\nonce (locally or in the CI machinery).  It will fail, but produce a\nreference image for the current state of the UI.\n\nWhen you run the test locally, the new reference image will appear in\nthe current directory.  Just move it into test/reference/.  The next\nrun of the test should then be green.\n\nWhen you run the tests in the CI machinery, you need to download the\nnew reference images from the test results directory.  They show up as\nregular screenshots.\n\nIf there are parts of the reference image that you want to ignore, you\ncan pass a suitable \"ignore\" argument to assert_pixels.  It contains a\nlist of CSS selectors, and any pixel that is within their bounding\nrectangles is ignored.  For example, this\n\n```py\n    def testSomeDialog(self):\n        ...\n        self.browser.assert_pixels('#dialog', \"dialog\", ignore=[\"#memory-available\"])\n        ...\n```\n\nwould compare a full dialog to a reference, but would exclude the DOM\nelement that shows a number that is dependent on the environment that\nthe test runs in.\n\nYou can also change the transparency (alpha channel) of parts of the\nreference image itself (with the GIMP, say).  Any pixel that is not\nfully opaque will be ignored during comparison.\n\nWhen you are done adding images to `test/reference`, push them into\nthe storage repository like so:\n\n```\n$ ./test/common/pixel-tests push\n```\n\nThis `push` command will record a change to `test/reference` in the\nmain repository, and you need to commit this change.  This is how the\nmain repository specifies which reference images to use exactly for\neach of its commits.\n\nIf you want to see what changes would be pushed without actually\npushing them, you can run this:\n\n```\n$ ./test/common/pixel-tests status\n```\n\nHere is a PR that adds two pixel test points to the starter-kit,\ncomplete with reference images:\n\n  [starter-kit#436](https://github.com/cockpit-project/starter-kit/pull/436)\n\n## Debugging a failed pixel test\n\nWhen making changes that change how the UI looks, some pixel tests\nwill fail.  The test results will contain the new pixels, and you can\ncompare them with the reference image right in the browser when looking\nat the test logs.\n\nHere is a PR that makes the two pixel tests fail that had been added\nin #436:\n\n  [starter-kit#435](https://github.com/cockpit-project/starter-kit/pull/435)\n\nAs you can see, it has \"changed pixels\" links in the same place as the\nwell known \"screenshot\" links.  Clicking on it gets you to a page\nwhere you can directly compare the previous and current UI.\n\nAs the author of the pull request, you can decide from there whether\nthese changes are intended or not.\n\nFor a intended change, see the next section.  For unintended changes,\nyou need to fix your code and try again, of course.\n\n## Updating a pixel test\n\nIf you make a change that intentionally changes how Cockpit looks, you\nneed to install new reference images in `test/reference/`.\n\nThis is very similar to adding a new pixel test point.  Take the\nTestFoo-testBasic-pixels.png that was written by the failed test run,\nmove it into `test/reference`, push it to the storage repository with\n`./test/common/pixel-tests push`, and commit `test/reference` in the\nmain repository.\n\nA local test run has dropped the new reference image into the current\ndirectory, for a remote run it will be in the test results directory\nand the pixel comparison view has a link to it.\n\nWhen a test writes a new TestFoo-testBasic-pixels.png file for a\nfailed test, it will have the alpha channel of the old reference\ncopied into it.  That makes it easy to keep ignoring the same parts.\n\n## Reviewing a changed pixel test\n\nHere is a second version of the starter-kit pull request from the\nprevious section:\n\n  [starter-kit#438](https://github.com/cockpit-project/starter-kit/pull/438)\n\nIt has the same code changes, but now the reference images have been\nupdated as well, since the change in color was of course intended.\n\nNow this PR needs to be reviewed, and the changed visuals need to be\napproved.  But since the reference images are not stored in the main\nrepository, Github will not include them in the PR diff view.\n\nInstead, the robots will automatically add a comment to a pull request\nwith a link to a page that allows reviewing the changed reference\nimages.\n"
  },
  {
    "path": "_posts/2021-05-12-244.md",
    "content": "---\ntitle: Cockpit 244\nauthor: kkoukiou\ndate: 2021-05-12\ntags: cockpit linux\nslug: cockpit-244\ncategory: release\nsummary: Cockpit with various improvements\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).  We release regularly.\n\nHere are the release notes from Cockpit version 244 and Cockpit Machines 244.\n\n## Shell: sudo is invoked only when explicitly requested\n\nCockpit will no longer try to automatically run sudo on the very first login: you'll have to\nexplicitly turn on administrative access once for each browser profile that you\nuse to access Cockpit. This reduces a lot of noise about authentication failures in the journal.\n\nIn addition, Cockpit now shows sudo's exact messages in the \"Administrative access\" dialog.\n\n![Sudo error messages](/images/sudo-error-messages.png)\n\n## Machines: Edit the MAC address of a VM's network interface\n\nTo edit the MAC address of a virtual machine click the `Edit` button on the row\nof the network interface. A common scenario where this is needed is when\nconfiguring the DHCP server to map a static IP address to a certain MAC address.\n\n![VM edit MAC address](/images/vm-edit-mac-address.png)\n\n### Try it out\n\nCockpit 244 and Cockpit Machines 244 are available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/244)\n * [Cockpit Machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/244)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-de41124d1b)\n * [Cockpit Machines Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-27b4c7a5a3)\n * [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-16d3cfc061)\n * [Cockpit Machines Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-636fbff930)\n"
  },
  {
    "path": "_posts/2021-05-26-cockpit-245.md",
    "content": "---\ntitle: Cockpit 245\nauthor: lis\ndate: 2021-05-26\ntags: cockpit linux\nslug: cockpit-245\ncategory: release\nsummary: Cockpit with metrics and storage improvements\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).  We release regularly.\n\nHere are the release notes from Cockpit version 245 and cockpit-podman version 31.\n\n## Metrics: New PCP configuration dialog\n\nThe Metrics page header has a new \"Metrics settings\" button:\n\n![Metrics page header showing new settings button](/images/metrics-menu.png)\n\nThis allows you to enable or disable the [Performance Co-Pilot](https://pcp.io/) (PCP) metrics collector:\n\n![The start of a new Metrics settings dialog](/images/metrics-settings.png)\n\nRelated options will be added in the near future.\n\n## Storage: Show both SHA256 and SHA1 Tang fingerprints\n\nNewer versions of `tang-show-keys` will use SHA256 to compute the thumbprints\nof the keys, so Cockpit now shows both versions to allow key verification for\nboth new and old versions.\n\n![Key verification with SHA256 and SHA1 fingerprints](/images/storage-tang-dual-fingerprint.png)\n\n## Release: No more cockpit-cache tarball\n\nThe Cockpit project is no longer distributing the cockpit-cache tarball as part\nof its releases.  This tarball previously contained the exact state of the\n`node_modules/` directory at the time the release was made, and was provided for\nreproducibility and possible GPL compliance reasons (since the main release\ntarball contains a good deal of generated code).\n\nThis has been replaced with a separate git repository,\n[cockpit-project/node-cache](https://github.com/cockpit-project/node-cache/releases),\nwhich will now receive a tag for each release.\n\n## cockpit-podman: Added Korean translation\n\nA new translation has been added for the Korean language.\n\nThanks to [simmon](https://translate.fedoraproject.org/user/simmon/) for the efforts.\n\n### Try it out\n\nCockpit 245 and cockpit-podman 31 are available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/245)\n * [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-c56d879ccc)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-4d35210e6d)\n * [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/31)\n * [cockpit-podman Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-53b0a0e1e1)\n * [cockpit-podman Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-5ac7229f7d)\n"
  },
  {
    "path": "_posts/2021-06-23-cockpit-247.md",
    "content": "---\ntitle: Cockpit 247\nauthor: kkoukiou\ndate: 2021-06-23\ntags: cockpit linux\nslug: cockpit-247\ncategory: release\nsummary: Cockpit with Metrics and Virtual Machines improvements\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).  We release regularly.\n\nHere are the release notes from Cockpit version 247 and Cockpit Machines version 246.\n\n## Metrics: Enable Grafana client setup\n\n\"Metrics settings\", [introduced in Cockpit 245](https://cockpit-project.org/blog/cockpit-245.html), has a new option to share Performance Co-Pilot data over the network. Enabling \"export to network\" enables a [Redis](https://grafana-pcp.readthedocs.io/en/latest/datasources/redis.html) data source with the [pmproxy service](https://linux.die.net/man/1/pmproxy).\n\n![metrics settings](/images/metrics-settings-2.png)\n\nIf the machine uses firewalld, you can allow pmproxy in a particular zone afterwards:\n\n![metrics firewall zone selector](/images/metrics-fw-sel.png)\n\nA remote [Grafana](https://grafana.com/) instance can then read the machine's metrics using the [PCP Grafana plugin](https://grafana-pcp.readthedocs.io/). More details are available on [the PCP metrics feature page](https://cockpit-project.org/guide/latest/feature-pcp.html).\n\n## Machines: Share host files with the guest using virtiofs\n\nCockpit Machines can now share a host directory with a guest VM.\n\n[virtiofs](https://virtiofs.gitlab.io/) powers this sharing feature, offering local file system semantics and performance. virtiofs has been available in mainline Linux 5.4, QEMU 5.0, and libvirt 6.2. Sharing host files is available only when these versions are met.\n\n![shared directories card](/images/machines-shared-directories-card.png)\n\n![machines new shared directory dialog](/images/machines-new-shared-directory-dialog.png)\n\n## Machines: Show list of pass-through devices\n\nThe virtual machines details page now shows the list of USB, PCI and SCSI host devices that are passed through to the guest VM.\n\n![machines host devices card](/images/machines-host-devices-card.png)\n\n### Try it out\n\nCockpit 247 and Cockpit Machines 246 are available now:\n\n * [For your Linux system](https://cockpit-project.org/running.html)\n * [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/247)\n * [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-b61fc3e33d)\n * [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-914e35e595)\n * [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/246)\n * [cockpit-machines Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-d9dd21b606)\n * [cockpit-machines Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-115bb6f593)\n\n *[VM]: Virtual Machine\n *[PCP]: Performance Co-Pilot\n"
  },
  {
    "path": "_posts/2021-07-05-pcp-grafana.md",
    "content": "---\ntitle: Setting up PCP and Grafana metrics with Cockpit\nauthor: pitti\ndate: 2021-07-05\ncategory: howto\ntags: metrics pcp grafana\n---\n\nFinding performance problems is a common troubleshooting activity. Monitoring the usage of CPU, memory, network, and other resources helps administrators to spot patterns when unusual resource usage occurs.\n\nCockpit can help. Let's take a look!\n\n## Starting point\n\nLet's start with a pristine Fedora 34 system which has at least [Cockpit 247](https://cockpit-project.org/blog/cockpit-247.html). Everything here works in principle on CentOS/RHEL 8, Debian, and Ubuntu as well, but at the time of writing these distributions still have an older Cockpit version. Let's make sure that Cockpit is installed, enabled, and that the port is open in the firewall, as [documented on the Install page](https://cockpit-project.org/running.html):\n\n```\n# rpm -q cockpit\ncockpit-247-1.fc34.x86_64\n# systemctl enable --now cockpit.socket\n# firewall-cmd --permanent --add-service cockpit\n# firewall-cmd --reload\n```\n\n## Metrics in Cockpit for the local machine\n\nYou can now log into Cockpit on [https://localhost:9090](https://localhost:9090), or the corresponding host name of the system which you want to troubleshoot. The Overview page shows a very brief CPU/memory usage with a \"View Details and history\" link:\n\n![Overview usage card](/images/overview-card-usage.png)\n\nThat link leads you to the Metrics page, which in a minimal installation only shows current metrics:\n\n![Metrics page without PCP](/images/metrics-page-no-pcp.png)\n\nFor spotting performance problems in the past, we need to enable historical metrics, which are provided by [Performance Co-Pilot](https://pcp.io/), aka. \"PCP\".\n\nThe \"Install cockpit-pcp\" button installs the necessary support for this, and asks you to log in again (the newly-installed cockpit-pcp support cannot be used in an existing session). After that, the Metrics page will start to show historical metrics. Combined with Cockpit's other pages such as \"Services\", \"Logs\", or \"Podman containers\", this is a very powerful tool to find performance related problems:\n\n<iframe width=\"960\" height=\"720\" src=\"https://www.youtube.com/embed/8_NLoJBjay4?rel=0\" frameborder=\"0\" allowfullscreen></iframe>\n\n\n## Metrics of multiple machines\n\nBut what if you want to monitor not just one machine, but your whole fleet?\n\nCockpit used to have a \"Dashboard\" to see some basic resource usage of up to twenty machines, but this was very inflexible, inefficient, insecure, lacking important features such as alerting, and was bound to a running Cockpit session. For these reasons, the Dashboard was removed in [Cockpit 234](https://cockpit-project.org/blog/cockpit-234.html).\n\nOne of today's industry standard solutions for visualizing metrics is [Grafana](https://grafana.com/); it doesn't have above limitations. PCP offers a [Grafana plugin](https://grafana-pcp.readthedocs.io/en/latest/) to provide the machine's metrics to a local or remote Grafana installation.\n\n## Setup of monitored machines\n\nSetting up the machines for sending metrics to Grafana involves a couple of steps, which the most recent Cockpit version can do automatically for you:\n\n * Install PCP and enable `pmlogger.service` to start data collection. This already happened with the \"Install cockpit-pcp\" button above.\n * Enable `pmproxy.service`, the PCP component which exposes a read-only metrics query API to the network.\n * pmproxy needs the [Valkey](https://valkey.io/) or [Redis](https://redis.io/) database, so the `valkey` or `redis` package needs to be installed, and the service configured to start with `pmproxy.service`.\n * pmproxy opens a network port (44322 by default), which needs to be opened in the firewall for the zone that contains the Grafana machine.\n\nThe \"Metrics settings\" button at the top of the page opens a dialog where you can enable \"Export to network\":\n\n![Metrics settings with enabled pmproxy](/images/metrics-settings-2.png)\n\nThis will let you confirm any extra packages that need to be installed (such as valkey), and configure pmproxy. After that, you may get an alert for opening the corresponding firewall service (if it is not yet open in any zone):\n\n![pmproxy firewall alert](/images/metrics-fw-sel.png)\n\nRepeat this on all the machines that you want to monitor, or use a configuration management tool like [Ansible](https://www.ansible.com/) to [automate these steps](https://cockpit-project.org/guide/latest/feature-pcp.html).\n\n## Grafana setup\n\nNow that the monitored machines all export Grafana-compatible PCP performance metrics, you need to [install Grafana itself](https://grafana.com/docs/grafana/latest/installation/). This can happen on one of the existing servers, but it is recommend to install Grafana on a separate machine, or deploy it in [Kubernetes](https://grafana.com/docs/grafana/latest/installation/kubernetes/).\n\nOn Fedora you can just run the distribution package:\n\n    dnf install grafana grafana-pcp\n    systemctl enable --now grafana-server\n\nAfter that you should see Grafana's login page on [http://localhost:3000](http://localhost:3000), or again, the corresponding Grafana host name. Log in as admin/admin for the first time, provide a real password, and you should see the start page:\n\n![Grafana Overview](/images/grafana-overview.png)\n\nIn the left menu, select the Cog wheel (Configuration) → Plugins, and enable the PCP plugin:\n\n![Grafana enable PCP plugin](/images/grafana-enable-pcp-plugin.png)\n\nNow select Configuration → Data sources, and add a \"PCP Redis\" data source:\n\n![Grafana Add PCP Redis data source](/images/grafana-add-data-source.png)\n\nNormally you just need to enter the host name of the above machine which we configured for PCP data export:\n\n![Grafana Add PCP data source details](/images/grafana-add-data-source-details.png)\n\nAfter clicking \"Save & Test\" you should get a \"Datasource is working\" confirmation. Data sources usually come with some default dashboards for an easy start. Switch to the \"Dashboards\" tab of that same page and import the \"Host Overview\":\n\n![Grafana PCP dashboard import](/images/grafana-pcp-dashboard-import.png)\n\nThat's it! You now have a dashboard with a *lot* of panels for all sorts of interesting metrics. The screenshot just shows the top ones:\n\n![Grafana PCP dashboard](/images/grafana-pcp-dashboard.png)\n\nYou can switch between multiple hosts, set up alerting, or adjust the panels to your liking.\n\nHappy performance debugging!\n\n*[PCP]: Performance Co-Pilot\n"
  },
  {
    "path": "_posts/2021-07-07-cockpit-248.md",
    "content": "---\ntitle: Cockpit 248\nauthor: garrett\ndate: '2021-07-07'\ntags: cockpit, machines, ostree, podman, grafana, pcp, redis, metrics, pam\nslug: cockpit-248\ncategory: release\nsummary: 'Metrics, PAM, Machines, OSTree, and git main branch changes'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 248, cockpit-machines 247, cockpit-ostree 186, and cockpit-podman 32:\n\n\n## Metrics: Install missing packages\n\n[Cockpit 247](https://cockpit-project.org/blog/cockpit-247.html) introduced setting up a machine for Grafana metrics. However, this only worked if the `pcp` and `redis` packages were already installed. In Cockpit 248 and after, selecting these options will install any missing packages.\n\n![screenshot of install missing packages]({{ site.baseurl }}/images/248-metrics-install-missing-packages.png)\n\n![screenshot of install missing packages]({{ site.baseurl }}/images/248-metrics-install-missing-packages-2.png)\n\nThis completes the story of [setting up PCP and Grafana metrics with Cockpit](https://cockpit-project.org/blog/pcp-grafana.html).\n\n## PAM: Deprecate `pam_cockpit_cert` module\n\nThe `pam_cockpit_cert` module is deprecated and no longer required for client certificate authentication. Cockpit continues to ship a stub module which returns `PAM_IGNORE`, but a future release will drop this stub.\n\nUpgrading packages will not update a modified `/etc/pam.d/cockpit` file. If you have modified this file, please take care to remove the relevant entry.\n\n## Machines: Bug fixes and improvements\n\n`cockpit-machines` has a new release with several bug fixes and minor improvements.\n\n## OSTree: Bump epoch to 1\n\nThe `cockpit-ostree` RPM package is being released as version `1:186`, with a newly introduced epoch. This new version will re-enable upgrading from an unintentional \"version 999\" of cockpit-ostree, which was accidentally published while testing the release infrastructure.\n\n## All: Git branches are now `main`\n\nOver the past few months, many Cockpit sub-projects changed their primary development branch to `main`. As of this release, all Cockpit repositories&mdash;including the main Cockpit repository&mdash;have finished the switch. Developers with checked out git repositories should [update their branches](https://docs.github.com/en/github/administering-a-repository/managing-branches-in-your-repository/renaming-a-branch#updating-a-local-clone-after-a-branch-name-changes). \n\nThis set of releases also marks the end of our transition to Dart Sass and Webpack 5, as well as cleanups and modernization to Cockpit's build system.\n\n## Try it out\n\nCockpit 248, cockpit-machines 247, and cockpit-ostree 187 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/248)\n* [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-56a2a973ac)\n* [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-c38f16f21e)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/247)\n* [cockpit-machines Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-8a0b90aea9)\n* [cockpit-machines Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-eee63f130a)\n* [cockpit-ostree Source Tarball](https://github.com/cockpit-project/cockpit-ostree/releases/tag/186)\n* [cockpit-ostree Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-01c2d704f6)\n* [cockpit-ostree Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-fad996bbc4)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/32)\n* [cockpit-podman Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-9f1a5b994b)\n* [cockpit-podman Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-fb780bee35)\n\n*[PCP]: Performance Co-Pilot\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2021-07-13-ci-metrics.md",
    "content": "---\ntitle: CI Metrics and Error Budgets\nauthor: pitti\ndate: 2021-07-13\ncategory: howto\ntags: metrics ci prometheus grafana error-budget service-level\n---\n\nThe Cockpit project literally lives and dies together with our integration tests and the CI machinery to run them. We notice this the hard way whenever there is an outage; that's why we invested quite some efforts to run tests on at least two different clouds, and [fall back to Amazon EC2](https://github.com/cockpit-project/cockpituous/tree/main/ansible/aws) when needed.\n\nBut there is a wholly different version of that pain: When tests or the infrastructure slowly become worse. At first it's just a single \"oh, a red test, this is unrelated, let's just retry\", and before you know it it takes a day to get a pull request to green, and developers get frustrated and even afraid of touching tests.\n\n## Error budget\n\nWith our tests and CI machinery being such important tools, we need to constantly measure their current state and quality to detect when they become too bad. In that case it is better to immediately react, stop feature development, and fix up our tools until they are in shape again. In total this minimizes the unnecessary pain and time spent on pull requests to get along with or work around breakage.\n\nThe goal is to turn a vague gut feeling into objective numbers and alerts. This helps your own team to stay honest, be transparent to colleagues, users, and management, and also to invest the *right amount* of work into infrastructure. The latter point is crucial -- clearly you can spend too little work and end up with a tool which is more of a hindrance than an aid. But you can also spend *too much* work on it, just because it's fun, or you are a perfectionist, ending up with [diminishing returns](https://en.wikipedia.org/wiki/Diminishing_returns).\n\nThis approach is called an *error budget* and described in all of its details and consequences in the free Google book [Site Reliability Engineering](https://sre.google/sre-book/table-of-contents/). This principle is mostly applied for services towards external customers, such as a web application or cloud engine. But we realized that it equally well applies to our development team as an internal service -- we are just our own customers, with two different hats: Most of the time we develop Cockpit, but sometimes we switch roles and develop our infrastructure.\n\n## Define Service Level Objectives\n\nThe first step of that story is to sit down with the stakeholders -- in this case our own development team. We discussed our high-level expectations on our development process, and agreed that we are \"happy\" as long as these hold:\n\n - PRs get validated in a reasonable time (queue + test run time).\n - We don't waste time on interpreting unstable test results.\n - We are not afraid of touching code.\n - Test failures are relevant and meaningful. Relieve us from having to decide about “unrelated or not” every. single. time.\n\nAs stated, these expectations are not objective; they need to be translated into concrete and measurable \"Service Level Indicators\" (SLI), together with a definition which range of an SLI we consider as \"good\"/\"keeps us happy\" according to the abstract expectations above. The latter is called a [Service Level Objective (SLO)](https://en.wikipedia.org/wiki/Service-level_objective). For us they look like this, in descending importance:\n\n\n 1. A merged PR becomes fully green with a 75% chance at the first attempt, and with a 95% chance after one retry.\n 2. Every individual test succeeds at least 90% of the time.\n 3. 95% of all PRs are merged without failed tests.\n 4. 95% of test runs take no more than 1 hour to execute.\n 5. 95% of test runs spend no more than 5 minutes in the queue until they get assigned to a runner.\n 6. 95% of scheduled tests run through to completion (all tests ran and status got reported to PR).\n\n These levels are not very ambitious compared to [five nines](https://en.wikipedia.org/wiki/High_availability#Percentage_calculation) that are often required in other places. We intentionally started low to get a grasp of how an error budget works. These SLOs represented a challenge which was achievable with a realistic amount of effort, while being good enough to not hamper our Cockpit development life.\n\n We [published these SLOs on our wiki](https://github.com/cockpit-project/cockpit/wiki/DevelopmentPrinciples#our-testsci-error-budget) to generate a sense of commitment and transparency.\n\n\n## Implement Service Level Indicators\n\nNow comes the time to meet the hard reality -- to pry these numbers out of production CI. Fortunately, most of the above SLIs (all but #2) can be derived directly from the [GitHub Statuses](https://docs.github.com/en/rest/reference/repos#statuses) history. For example, #5 is the time between \"Not yet tested\" and \"Testing in progress\" status changes, while #4 is the time between \"Testing in progress\" and any final (success, failure, error) status.\n\nOnly #2 requires scanning the actual test logs; our logs are in [TAP format](https://testanything.org/tap-specification.html), which makes it easy to scan for lines starting with `ok` or `not ok` and reading the test name and retry attempt/reason after that.\n\nThis evaluation happens in the [store-tests bots script](https://github.com/cockpit-project/bots/blob/main/store-tests). This gets called through a [webhook](https://docs.github.com/en/developers/webhooks-and-events/webhooks) for each *merged* PR. We deliberately do *not* count failures or long tests from intermediate force-pushes or abandoned PRs, as during that phase pretty much anything can (and does) go wrong. However, GitHub statuses do record test retries (for SLO #1).\n\n[`store-tests`](https://github.com/cockpit-project/bots/blob/main/store-tests) puts its results into an [SQLite database](https://sqlite.org/index.html) which gets [published on our logs server](https://logs-https-frontdoor.apps.ocp.ci.centos.org/test-results.db).\n\n## Visualizing SLIs and SLOs, take #1\n\nTo present the numbers in the database in a human friendly form, we started out with an \"all-in-one\" [tests.html](https://github.com/cockpit-project/bots/blob/main/tests.html). This uses [sql-wasm](https://github.com/ryan-codingintrigue/sql-wasm) to directly read the above SQLite database URL and the [chart](https://github.com/rook2pawn/node-chart) module to plot graphs. This got called the [CI weather report](https://logs-https-frontdoor.apps.ocp.ci.centos.org/tests.html?repo=cockpit-project%2Fcockpit#). The ingenious thing about it that it requires zero additional infrastructure and moving parts, and it has selectors and per-test subpages to drill down into any desirable detail. The major drawbacks are that it is *really* slow -- each page update needs to fetch the database again, which by now has swollen into a ~ 40 MB blob; and making changes to it is rather hard, as it involves a lot of coding.\n\n![CI weather report](/images/ci-weather-report.png)\n\n## Moving to Prometheus/Grafana\n\nWe recently got a requirement to combine our metrics with those of other teams, to get a high-level overview of the status of various RHEL teams. That just wasn't possible with the hand-woven all-in-one html. Due to that and the shortcomings from above, we moved to the industry-standard solutions.\n\n[Prometheus](https://prometheus.io/) collects metrics from an arbitrary number of sources, stores them in an internal database, and offers the [PromQL query language and API](https://prometheus.io/docs/prometheus/latest/querying/basics/) for generating time series, statistical calculations, or making predictions. Data sources need to export metrics in a fairly straightforward [text format](https://prometheus.io/docs/instrumenting/exposition_formats/), so we wrote a [prometheus-stats](https://github.com/cockpit-project/bots/blob/main/prometheus-stats) script which queries them from the same SQLite database, computes the metrics, and writes the Prometheus metrics to stdout. Our production metrics get [exported on our logs server](https://logs-https-frontdoor.apps.ocp.ci.centos.org/prometheus), but they are easy enough to generate locally as well in a [bots repository](https://github.com/cockpit-project/bots/) checkout:\n\n```\n$ curl -O https://logs-https-frontdoor.apps.ocp.ci.centos.org/test-results.db\n$ ./prometheus-stats\n# HELP queue_time_wait_seconds histogram of queue wait times\n# TYPE queue_time_wait_seconds histogram\nqueue_time_wait_seconds_bucket{le=\"300\"} 1720\nqueue_time_wait_seconds_bucket{le=\"3600\"} 2567\nqueue_time_wait_seconds_bucket{le=\"+Inf\"} 2646\nqueue_time_wait_seconds_sum 2438358\nqueue_time_wait_seconds_count 2646\n[...]\n```\n\n[Grafana](https://grafana.com/) builds graphs, dashboards, and alerts from Prometheus/PromQL. They are much easier and faster to create and iterate on than the static code from take #1. Grafana also offers variables, selector dropdowns, and time range selectors, so that you can restrict the view to a particular project repository only, or can switch between a recent view (last 24 hours) or a long-range evolution (like 30 days). However, this is not done yet: Compared to the weather report, you can't drill down into individual test case failures, nor get links to example logs.\n\nWe deploy Prometheus and Grafana to our Kubernetes cluster on CentOS CI. The resources, deployment scripts, and pre-defined dashboards live in our [Cockpituous infrastructure repository](https://github.com/cockpit-project/cockpituous/tree/main/metrics).\n\nThere are currently two Dashboards defined: [Cockpit CI](https://grafana-frontdoor.apps.ocp.ci.centos.org/d/ci/cockpit-ci) shows the straight SLIs and unstable tests, plus some extra information like how much space our test VM images use on S3.\n\nRecently we also added a more abstract [Error Budget](https://grafana-frontdoor.apps.ocp.ci.centos.org/d/budget/cockpit-ci-error-budget) dashboard, which shows the SLIs with a focus on and normalization to the defined SLO error budgets:\n\n![Grafana error budget](/images/grafana-error-budget.png)\n\n## Drawing conclusions\n\nThis error budget view now can guide our activity in an objective way. For example, a value of 50% like on \"SLI 4: percentage of tests with runtime > 1 h\" means that for that particular SLO we used up half of the error budget. The SLO is \"95% of all tests take no more than 1 hour to execute\", so the error budget is 5%, and the graph tells us that currently roughly 2.5% of tests take longer than one hour. That metric can still become twice as bad before we have to stop the line and go into \"infrastructure is on fire\" mode.\n\nOn the other hand, \"SLI 5: percentage of tests with queue time > 5 minutes\" is way beyond the budget. The [detailed graph](https://grafana-frontdoor.apps.ocp.ci.centos.org/d/ci/cockpit-ci?orgId=1&viewPanel=6&from=now-7d&to=now) tells us that it's not actually that bad, the average queue time is 5.17 minutes -- just slightly off. We used to have a queue time of a few seconds, so in our case this is an actual bug. We actually know the cause of that -- it will take a few hours to debug, but the details are not important for this post.\n\nBut for other cases, it could just be that the queue time has been like that for months, and nobody was bothered by it -- in that case it may be appropriate to redefine the SLO, and bump it to 10 minutes. The initial SLO was defined by gut feelings and polls as well, after all, and they should regularly be reviewed against the team's opinion whether they still accurarely represent \"happiness\".\n\n## Next Steps\n\nOur current state is a good foundation, but we are not done:\n\n * There are no alerts yet. Grafana has alerting support, but I have not looked at this at all. We want our infrastructure maintainers to get an email, and/or possibly an IRC bot message.\n \n * Compared to the weather report, the biggest missing feature in our Grafana boards are links to example test runs which violate the SLOs. The [OpenMetrics format](https://prometheus.io/docs/instrumenting/exposition_formats/#openmetrics-text-format) promises support for \"exemplars\" which fit exactly that use case, so we need to change our export accordingly, and figure out how to represent them in Grafana.\n\n * We need to define and follow a process how to react to exceeding the error budget:\n   - How many/which team members stop working on regular projects to move to infrastructure fixing?\n   - How does the team do a retrospective to determine why the error budget was exceeded?\n   - Once we fix the problem, it will take some time for the usual \"28 days\" view to abate and leave the alert zone, even though the problem is fixed; how do we represent that in the default view? How do we communicate this to other teams?\n\n * There are now two databases involved: Our own SQLite one, and Prometheus. It feels like it should be possible to get rid of our own one somehow, but computing the metrics does require a certain look-back window. It may be possible to simplify this once we retire the static weather report page.\n\n\n*[SLI]: Service Level Indicator\n*[SLIs]: Service Level Indicators\n*[SLO]: Service Level Objective\n*[SLOs]: Service Level Objectives\n*[PR]: Pull Request\n*[PRs]: Pull Requests\n"
  },
  {
    "path": "_posts/2021-08-04-cockpit-250.md",
    "content": "---\ntitle: Cockpit 250\nauthor: pitti\ndate: '2021-08-04'\ntags: cockpit, machines\nslug: cockpit-250\ncategory: release\nsummary: Cockpit with kpatch and VM migration support and session menu improvements\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 250 and cockpit-machines 249:\n\n\n## Shell: Improve admin switcher and session menu\n\nCockpit has a \"limited access\" mode with lowered privileges, where browsing generally works, but changing things that require administration rights generally does not.\n\nIf someone is stuck in \"limited access\" mode without knowing how to switch, it would appear that Cockpit is \"broken\" or cannot perform tasks it should be able to do. To make it more obvious how to switch modes, Cockpit now has several \"eye-catching\" changes to make switching easier to notice. These changes are in the shell, which is visible on every page within Cockpit, and the overview page's alert.\n\n- On the overview alert, a warning color has been used to draw attention\n- A lock icon has been used in both the overview alert and the shell privilege escalation icon\n- The shell's escalation action now resembles a button\n\n![panel-or8]({{ site.baseurl }}/images/250-shell-improve-admin-switcher-and-session-menu.png)\n\nAll of the above changes only affect \"limited access\" mode. Normal administration mode looks the same as before.\n\nThe menu on the top right is now called \"Session\" instead of showing an user icon. This clarifies that the settings in that menu apply to remote hosts as well, which possibly run as a different user.\n\n*Thanks to [Verhoeckx](https://github.com/Verhoeckx) for discussing and suggesting these design changes!*\n\n## Software Updates: Introduce basic kpatch support\n\nSome operating systems (Red Hat Enterprise Linux for now) support live kernel patching (\"kpatch\"). The Software updates page shows if kpatch is supported and if there are any patches active. You can enable kpatches for the currently running kernel and subscribe to patches for future kernel versions.\n\n![kpatch-or8]({{ site.baseurl }}/images/250-software-updates-introduce-basic-kpatch-support.png)\n\n## Machines: Migration of a virtual machine\n\nThe Machines page can now migrate a VM to a different machine. It supports live and temporary migration. Commonly, the VM's storage is on shared storage, which avoids having to copy the data to the remote machine and makes the migration process much faster and more robust. As it is not possible to automatically detect whether the storage is shared, the user has to explicitly tell whether the storage must be copied.\n\n![mig2-or8]({{ site.baseurl }}/images/250-machines-migration-of-a-virtual-machine.png)\n![mig1-or8]({{ site.baseurl }}/images/250-machines-migration-of-a-virtual-machine-2.png)\n\n\n## Try it out\n\nCockpit 250 and cockpit-machines 249 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/250)\n* [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-81e5ff92c6)\n* [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-638e9d41fc)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/249)\n* [cockpit-machines Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-eb47112baa)\n* [cockpit-machines Fedora 33](https://bodhi.fedoraproject.org/updates/FEDORA-2021-357c2a77f3)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2021-08-18-cockpit-251.md",
    "content": "---\ntitle: Cockpit 251\nauthor: garrett\ndate: '2021-08-18'\ntags: cockpit, machines\nslug: cockpit-251\ncategory: release\nsummary: 'Improved certificate usage, better logs filtering, and VM shared directory removal'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 251 and cockpit-machines 250:\n\n\n## Certificate and smart card authentication for ssh and sudo\n\nOnce you've logged into Cockpit with a client certificate, you'll likely need to switch to administative mode, or connect to remote machines through SSH. If your machine is part of a FreeIPA domain, you can now set up [constrained delegation rules](https://www.freeipa.org/page/V4/Service_Constraint_Delegation) so that the Cockpit certificate authentication gets forwarded to sudo and/or ssh. This is particularly useful if your user account does not have a password. Please see the [Client certification documentation](https://cockpit-project.org/guide/latest/cert-authentication.html) for details.\n\n## Logs: Easier-to-use filtering\n\nThe Logs page has friendlier filtering options. In previous versions, users had to know esoteric journald keywords to effectively find desired journal messages. The new version contains a dropdown with all possible fields, along with inline help.\n\n![Screenshot from 2021-08-09 13-11-59]({{ site.baseurl }}/images/251-logs-easier-to-use-filtering.png)\n\n## Machines: Shared directory removal\n\nCockpit Machines can now remove directory shares.\n\n![129880700-acc31a95-b306-4e9a-b58b-fb5996cce6b8]({{ site.baseurl }}/images/251-machines-shared-directory-removal.png)\n\n\n## Try it out\n\nCockpit 251 and cockpit-machines 250 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/251)\n* [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/?releases=F34&packages=cockpit)\n* [Cockpit Fedora 33](https://bodhi.fedoraproject.org/updates/?releases=F33&packages=cockpit)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/250)\n* [cockpit-machines Fedora 34](https://bodhi.fedoraproject.org/updates/?releases=F34&packages=cockpit-machines)\n* [cockpit-machines Fedora 33](https://bodhi.fedoraproject.org/updates/?releases=F33&packages=cockpit-machines)\n\n*[IPA]: identity management system (\"Identity, Policy, Audit\")*[SSH]: Secure Shell, a common protocol to securely connect to a remote computer"
  },
  {
    "path": "_posts/2021-09-01-cockpit-252.md",
    "content": "---\ntitle: Cockpit 252\nauthor: skobyda\ndate: '2021-09-01'\ntags: cockpit\nslug: cockpit-252\ncategory: release\nsummary: 'Remotectl utility dropped, introduced package version listing, improved presentation of encryption of a filesystem'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 252:\n\n\n## Webserver: Drop remotectl utility\n\n[Cockpit 241](https://cockpit-project.org/blog/cockpit-241.html) already stopped using the deprecated `remotectl` utility for creating certificates for the main `cockpit.service`, in favor of the much simpler `/usr/libexec/cockpit-certificate-ensure`. This version moves the remaining usage (containers and documentation) to that helper, and drops `remotectl`.\n\nIf you use scripts, playbooks, or similar direct invocations of `remotectl`, please consider removing that: Cockpit creates or refreshes a self-signed certificate on startup automatically if required. If you must pre-create it, please move your scripts to call\n`/usr/libexec/cockpit-certificate-ensure`. However, please note that this script is *not* a stable and supported public interface.\n\n## Shell: Show package versions in 'About web console' modal\n\n![Screenshot from 2021-08-30 14-07-52about]({{ site.baseurl }}/images/252-shell-show-package-versions-in-about-web-console-modal.png)\n\n## Storage: Encryption is presented as a property of a filesystem\n\nCockpit used to make the encryption layer of a encrypted filesystem explicit: It had its own row in the content table and it would be referred to in other places in the UI.  Now the encryption layer is hidden away and Cockpit pretends encryption is a inherent property of a Filesystem.\n\n![screenshot of encryption is presented as a property of a filesystem]({{ site.baseurl }}/images/252-storage-encryption-is-presented-as-a-property-of-a-filesystem.png)\n\n\n## Try it out\n\nCockpit 252 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/252)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-f7e6c767ec)\n* [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-8211d20195)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/251)\n* [cockpit-machines Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-e363e85ef7)\n* [cockpit-machines Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-07c8d95577)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/34)\n* [cockpit-podman Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-47627c3657)\n* [cockpit-podman Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-9cde7e476a)\n"
  },
  {
    "path": "_posts/2021-09-15-cockpit-253.md",
    "content": "---\ntitle: Cockpit 253\nauthor: garrett\ndate: '2021-09-15'\ntags: cockpit, machines\nslug: cockpit-253\ncategory: release\nsummary: 'Cockpit with SELinux and Virtual Machines improvements'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 253 and cockpit-machines 252:\n\n\n## SELinux: Dismiss multiple alerts\n\nSELinux alerts can now be selected and dismissed in bulk, which is simpler than having to expand and dismiss them individually. Having a clean alert state is especially helpful when building policies, as newer alerts become more obvious.\n\n![screenshot of dismiss multiple alerts]({{ site.baseurl }}/images/253-selinux-dismiss-multiple-alerts.png)\n\n## Machines: Add support for renaming VMs\n\nThe Machines page can rename virtual machines.\n\n![screenshot of add support for renaming vms]({{ site.baseurl }}/images/253-machines-add-support-for-renaming-vms.png)\n![screenshot of add support for renaming vms]({{ site.baseurl }}/images/253-machines-add-support-for-renaming-vms-2.png)\n\n## Try it out\n\nCockpit 253 and cockpit-machines 252 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/253)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-0361029ac6)\n* [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-daa1d318e6)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/252)\n* [cockpit-machines Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-6f908905a2)\n* [cockpit-machines Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-d7291a62d4)\n\n*[SELinux]: Security-Enhanced Linux, policies for enforcing access controls in Linux\n*[VM]: Virtual Machine\n*[VMs]: Virtual Machines\n"
  },
  {
    "path": "_posts/2021-09-29-cockpit-254.md",
    "content": "---\ntitle: Cockpit 254\nauthor: garrett\ndate: '2021-09-29'\ntags: cockpit, machines\nslug: cockpit-254\ncategory: release\nsummary: 'Login history improvements, Arch branding, and Machines with device support'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 254 and cockpit-machines 253:\n\n## Overview: Move last login to Health Card\n\nPreviously, last successful or failed logins were shown in a dismissable alert, which took a lot of space. Login information was moved to the Health card.\n\n![screenshot of move last login to health card]({{ site.baseurl }}/images/254-overview-move-last-login-to-health-card.png)\n\n\nA failed login:\n\n![screenshot of move last login to health card]({{ site.baseurl }}/images/254-overview-move-last-login-to-health-card-2.png)\n\n## Users: Login history\n\nThe user account details page now includes a list of your 15 most recent logins.\n\n![users-login-history]({{ site.baseurl }}/images/254-users-login-history.png)\n\n## Login: Arch Linux Branding\n\nCockpit now includes branding for the [Arch Linux distribution](https://archlinux.org/).\n\n![screenshot of arch linux branding]({{ site.baseurl }}/images/254-login-arch-linux-branding.png)\n\n## Webserver: Restrict frame embedding to same origin\n\nCockpit's web server now sets the [X-Frame-Options header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) to explicitly disallow frame embedding within a different origin. Thanks to cookie policy restrictions, this was already prevented in most cases, as embedded frames would always show the login page. With this new option, the browser directly forbids cross-origin embedding and shows an explanatory error page instead. (CVE-2021-3660)\n\n![254-webserver-restrict-frame-embedding-to-same-origin]({{ site.baseurl }}/images/254-webserver-restrict-frame-embedding-to-same-origin.png)\n\n## Machines: Support adding and removing host devices\n\nHost devices are physical devices on the machine running virtual machines. This includes devices from USB (mice, cameras, keyboards) and PCI (NICs, GPUs). Users can now assign and detach host devices for each VM. \n\nPlease note: When a device is assigned to a VM, it can no longer be used by the host.\n\n![254-machines-support-adding-and-removing-host-devices]({{ site.baseurl }}/images/254-machines-support-adding-and-removing-host-devices.png)\n![254-machines-support-adding-and-removing-host-devices-2]({{ site.baseurl }}/images/254-machines-support-adding-and-removing-host-devices-2.png)\n\n\n## Try it out\n\nCockpit 254 and cockpit-machines 253 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/254)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-55aee7fb50)\n* [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-6d84fa5ea2)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/252)\n* [cockpit-machines Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-94dbdd6c6d)\n* [cockpit-machines Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-6a5b94490b)\n\n*[CI]: continuous integration (testing)\n*[HTTP]: Hypertext Transport Protocol\n*[NIC]: Network Interface Card\n*[USB]: Universal Serial Bus, a protocol for hot-pluggable (and usually external) devices\n*[PCI]: Peripheral Component Interconnect, a bus for attaching devices\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2021-10-13-cockpit-255.md",
    "content": "---\ntitle: Cockpit 255\nauthor: garrett\ndate: '2021-10-13'\ntags: cockpit, machines\nslug: cockpit-255\ncategory: release\nsummary: 'Improvements with FreeIPA integration and virtual networks'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 255 and cockpit-machines 254:\n\n\n## FreeIPA-issued webserver certificates get auto-renewed\n\nWhen you join a [FreeIPA](https://www.freeipa.org) realm with Cockpit, it automatically requests a TLS certificate for its webserver from the FreeIPA domain controller. Browsers usually trust these certificates much more than the default self-signed ones. Cockpit now calls [ipa-getcert](https://linux.die.net/man/1/ipa-getcert) in such a way that the generated `/etc/cockpit/ws-certs.d/10-ipa.{cert,key}` certificate gets renewed automatically.\n\n## Machines: Support configuring static MAC → IP address mappings\n\nIt is often useful to assign a fixed IPv4 address to a particular VM. Cockpit can now add DHCP host entries to existing virtual networks. These entries map a specific MAC address to an IP address.\n\n![screenshot of support configuring static mac → ip address mappings]({{ site.baseurl }}/images/255-machines-support-configuring-static-mac-ip-address-mappings.png)\n\n![screenshot of support configuring static mac → ip address mappings]({{ site.baseurl }}/images/255-machines-support-configuring-static-mac-ip-address-mappings-2.png)\n\n\n## Try it out\n\nCockpit 255 and cockpit-machines 254 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/255)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-7dc34b336a)\n* [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-a7a8407de1)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/254)\n* [cockpit-machines Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-694efa1097)\n* [cockpit-machines Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-7ccf08dbe0)\n\n*[IPA]: identity management system (\"Identity, Policy, Audit\")\n*[TLS]: Transport Layer Security\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2021-10-27-cockpit-256.md",
    "content": "---\ntitle: Cockpit 256\nauthor: jelle\ndate: '2021-10-27'\ntags: cockpit\nslug: cockpit-256\ncategory: release\nsummary: ''\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 256 and cockpit-machines 255:\n\n\n##  Clean up old self-signed certificates\n\nOlder versions of cockpit used to generate self-signed TLS certificates with 100 year validity periods.  Modern web browsers reject TLS certificates with such long expiry dates, and cockpit moved to generating shorter-validity certificates a while ago.  This version additionally adds a check for long-validity certificates issued by old versions of cockpit and reissues them if they're found.\n\n## Storage: Add support for Stratis\n\nCockpit now supports the [Stratis](https://stratis-storage.github.io) local storage management technology.\n\n![menu]({{ site.baseurl }}/images/256-storage-add-support-for-stratis.png)\n\n![details]({{ site.baseurl }}/images/256-storage-add-support-for-stratis-2.png)\n\n\n## Try it out\n\nCockpit 256 and cockpit-machines 255 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/256)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-d0454f82b0)\n* [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-42ab01f71d)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/255)\n* [cockpit-machines Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-cd7d707018)\n* [cockpit-machines Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-0a0bce1577)\n\n*[TLS]: Transport Layer Security\n"
  },
  {
    "path": "_posts/2021-11-10-cockpit-257.md",
    "content": "---\ntitle: Cockpit 257\nauthor: garrett\ndate: '2021-11-10'\ntags: cockpit, machines, podman\nslug: cockpit-257\ncategory: release\nsummary: 'Certificate changes, systemd for users, virtual console selecting in Machines, a new container workflow for Podman'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 257, cockpit-machines 256, and cockpit-podman 36:\n\n\n## Support for reading TLS certificates with any permissions\n\nFormerly, `cockpit-tls`, the process responsible for handling encryption on HTTPS connections to cockpit, would directly read the certificate file for itself.  This required the private key file to be owned by the `cockpit-ws` user (or group) that this process ran as.  Users sometimes want to share the same key file with several different services, making this arrangement awkward.  It also required additional configuration steps in the case of automatically-issued certificates.\n\nCockpit now reads the certificate and key files as the root user, allowing them to be installed with any set of permissions.\n\n## cockpit-ws no longer supports merged certificates\n\nWhen running in a container, `cockpit-tls` cannot be used, and `cockpit-ws` must be run directly.\n\nWhen running in this mode, merged key and certificate files are no longer supported: you must switch to separate `.cert` and `.key` files. If you did not do any particular certificate setup, you can just remove `/etc/cockpit/ws-certs.d/0-self-signed.crt` and let the container re-create a fresh self-signed certificate on startup.\n\n## Services: Show user-owned systemd units\n\nIn addition to system system-wide units, systemd manages user-specific units as well. The Services page can now show and control these user instance units with the new \"System\"/\"User\" toggle. Changing user units does not require Administrator privileges.\n\n![140483853-7c31cd69-4d5d-4b37-8cdc-4498e1daf813]({{ site.baseurl }}/images/257-services-show-user-owned-systemd-units.png)\n\n## Machines: Support selecting between consoles of the same type\n\nVM configurations can specify multiple PTY consoles. A VM can have an emulated serial console and a virtio serial console. The console menu now shows alias identifiers, making it possible to choose between consoles of the same type.\n\n![140937551-4e7bb79d-54da-4bf7-9c67-b1ac85f1f074]({{ site.baseurl }}/images/257-machines-support-selecting-between-consoles-of-the-same-type.png)\n\n## Podman: New \"Create container\" workflow\n\nCreating a container is easier and more featureful. The new container creation workflow starts by clicking the \"Create container\" button, which shows a new dialog.\n\n![141087576-66ad8aaa-937f-44ae-99f9-738fd75ed146]({{ site.baseurl }}/images/257-podman-new-create-container-workflow.png)\n\nThe dialog itself shows local images, including manually created images and previously created images, and can download an image directly from a registry.\n\n![141087882-48f73144-549b-44d2-b3ad-bd007e2e3422]({{ site.baseurl }}/images/257-podman-new-create-container-workflow-2.png)\n\nA second tab contains optional system integration with port mapping, volume mapping, and environment variables.\n\n![141087968-5d7ee210-92cc-4efd-87f5-43569b9be60c]({{ site.baseurl }}/images/257-podman-new-create-container-workflow-3.png)\n\n## Podman: Prune unused images\n\nUnused images can now be cleaned up in cockpit-podman. This behaves similar to `podman image prune -a` and can delete unused system _and_ user container images at the same time.\n\n![139233630-1ca43c26-a276-4f9a-9ac5-5caf0d56b277]({{ site.baseurl }}/images/257-podman-prune-unused-images.png)\n\n![140961475-7dbd2501-5a3b-49e0-8edc-f5d5f1f7df53]({{ site.baseurl }}/images/257-podman-prune-unused-images-2.png)\n\n## Try it out\n\nCockpit 257, cockpit-machines 256, and cockpit-podman 36 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/257)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-562664e808)\n* [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-9b41f0e6c8)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/256)\n* [cockpit-machines Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-7616340d68)\n* [cockpit-machines Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-57970264be)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/36)\n* [cockpit-podman Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-2088f7eb4a)\n* [cockpit-podman Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-58b0f7c034)\n\n*[HTTP]: Hypertext Transport Protocol\n*[TLS]: Transport Layer Security\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2021-12-08-cockpit-259.md",
    "content": "---\ntitle: Cockpit 259\nauthor: garrett\ndate: '2021-12-08'\ntags: cockpit\nslug: cockpit-259\ncategory: release\nsummary: 'More information in storage table rows'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 259, cockpit-machines 258, and cockpit-podman 38:\n\n## Storage: More information in table rows\n\nTable rows representing filesystems now show more information. You can\nnow immediately see the mountpoint and the usage, and there are also\nlinks to the pages for volume groups.\n\n![screenshot of more information in table rows]({{ site.baseurl }}/images/259-storage-more-information-in-table-rows.png)\n\n## Cockpit Client\n\nCockpit now ships [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient) via [Flatpak](https://flatpak.org/).\n\nIf you are on a Linux desktop, this is now the most convenient and secure way (no open ports other than ssh) of accessing remote servers or your local machine with Cockpit.\n\n## Try it out\n\nCockpit 259, cockpit-machines 238, and cockpit-podman 38 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/259)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-e6cb254fc8)\n* [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-13201d3694)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/258)\n* [cockpit-machines Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-9c0e644bda)\n* [cockpit-machines Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-3f69584f6c)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/38)\n* [cockpit-podman Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2021-a25919f639)\n* [cockpit-podman Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2021-5af66d25e8)\n"
  },
  {
    "path": "_posts/2022-01-05-cockpit-260.md",
    "content": "---\ntitle: Cockpit 260\nauthor: garrett\ndate: '2022-01-05'\ntags: cockpit, podman\nslug: cockpit-260\ncategory: release\nsummary: 'Client improvements, podman restart policy and pod container creation'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 260 and cockpit-podman 39:\n\n\n## Certificate login validation: Action required on updates\n\nEarlier Cockpit/sssd versions did not check trust or revocation status of a presented client certificate, and thus certificate/smart card login was secure and supported only when matching the entire binary certificate against the Identity Management's database. With sssd 2.6.1 and Cockpit 260, the certificate signature and revocation status is now validated against the CA [configured in sssd](https://www.mankier.com/5/sssd.conf#Services_Sections-PAM_configuration_options), and any non-trusted certificate is rejected. This includes the case when the local sssd has *no* configured CA, which may break certificate logins after updating cockpit and sssd.\n\nThus if you use certificate login, you need to set up the trusted CA in sssd. Please see the [certificate authentication documentation](https://cockpit-project.org/guide/latest/cert-authentication.html#certauth-server-cockpitconf) for details.\n\nThis issue was assigned [CVE-2021-3698](https://access.redhat.com/security/cve/CVE-2021-3698).\n\n## Client: Show previously used hosts\n\nCockpit client now shows list of hosts that were used before so you can log in with one click. It is also possible to remove unwanted hosts from this list.\n\n![Screenshot from 2021-12-10 08-09-06]({{ site.baseurl }}/images/260-client-show-previously-used-hosts.png)\n\n## Client: Support port specification\n\nCockpit Client now supports specifying the port number when connecting, with the usual syntax like `user@host.example.net:22222`.  This is the same form used in Cockpit bastion host configurations.\n\n## Podman: Create container in pod\n\nIt is now possible to create a container in an existing pod using the `Create container in pod` button.\n\n![screenshot of ## create container in pod]({{ site.baseurl }}/images/260-create-container-in-pod.png)\n\nCreate container dialog now shows in which pod the container is created\n\n![screenshot of ## create container in pod]({{ site.baseurl }}/images/260-create-container-in-pod-2.png)\n\n## Podman: Set restart policy\n\nFor system containers it is now possible to set a restart policy for new containers.\n\n![screenshot of ## podman restart policy]({{ site.baseurl }}/images/260-podman-restart-policy.png)\n\n## Podman: Allow inserting multiple environment variables\n\nPodman users can now insert multiple environment variables in bulk by copy pasting an list of environment files the variables have to be formatted as FOO=bar separated by newlines.\n\n## bridge: Warning on missing cockpit-system package\n\nPreviously, when attempting to connect to a system which had `cockpit-bridge` installed, but not `cockpit-system`, you'd get a generic \"Not found\" error, with no hints about how to fix that.\n\ncockpit-bridge now detects this problem and issues a more helpful message.\n\n![screenshot of warning on missing cockpit-system package]({{ site.baseurl }}/images/260-bridge-warning-on-missing-cockpit-system-package.png)\n\n\n## Try it out\n\nCockpit 260 and cockpit-podman 39 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/260)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-de63f0423c)\n* [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2022-675c38e70e)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/39)\n* [cockpit-podman Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-bda238b5d3)\n* [cockpit-podman Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2022-43a48969ca)\n"
  },
  {
    "path": "_posts/2022-01-25-cockpit-261.md",
    "content": "---\ntitle: Cockpit 261\nauthor: marusak\ndate: '2022-01-25'\ntags: cockpit, podman\nslug: cockpit-261\ncategory: release\nsummary: 'Unmounting of busy storage devices and new Podman features'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 261 and cockpit-podman 40:\n\n\n## Storage: Unmounting or deleting a busy filesystem is now supported\n\nCockpit can now stop processes and services that keep a filesystem busy before unmounting or destroying a filesystem.\n\nThis is accompanied by a general improvement in how destructive actions are summarized in their dialogs.\n\n![screenshot of unmounting or deleting a busy filesystem is now supported]({{ site.baseurl }}/images/261-storage-unmounting-or-deleting-a-busy-filesystem-is-now-supported.png)\n\n![screenshot of unmounting or deleting a busy filesystem is now supported]({{ site.baseurl }}/images/261-storage-unmounting-or-deleting-a-busy-filesystem-is-now-supported-2.png)\n\n\n## Podman: Add pause/resume to containers\n\nAdd the pause and resume options — already available for pods — to\nindividual containers. Also make the order of the menu options the same\nfor pods and containers and add \"Force restart\" to the pod actions.\n\n## Podman: Add option to pull the latest image when creating a new container\n\nWhen the `:latest` tag of an image is available locally, but a newer version is available on the image registry, checking the \"pull latest image\" checkbox will now pull the latest version before creating the new container\n\n\n![screenshot of ## add option to pull the latest image when creating a new container]({{ site.baseurl }}/images/261-add-option-to-pull-the-latest-image-when-creating-a-new-container.png)\n\n\n## Try it out\n\nCockpit 261 and cockpit-podman 40 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/261)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-ea4aea1385)\n* [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2022-ca051bce3d)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/40)\n* [cockpit-podman Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-a4a60897b9)\n* [cockpit-podman Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2022-a4a60897b9)\n\n"
  },
  {
    "path": "_posts/2022-02-02-cockpit-262.md",
    "content": "---\ntitle: Cockpit 262\nauthor: pitti\ndate: '2022-02-02'\ntags: cockpit\nslug: cockpit-262\ncategory: release\nsummary: 'Health card and firewall service improvements'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 262:\n\n\n## Overview: Show scheduled shutdowns\n\nThe Health card shows a scheduled reboot or poweroff. This can also be cancelled.\n\n![152010075-40f21085-31fb-4e14-a82c-1456c0cfea19]({{ site.baseurl }}/images/262-overview-show-scheduled-shutdowns.png)\n\n\n## Networking: Add firewall service description\n\nCustom firewall ports can now include a small description for the system administrator.\n\n![zone]({{ site.baseurl }}/images/262-networking-add-firewall-service-description.png)\n\n## Try it out\n\nCockpit 262 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/262)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-e60f2d4527)\n* [Cockpit Fedora 34](https://bodhi.fedoraproject.org/updates/FEDORA-2022-39155b6e66)\n"
  },
  {
    "path": "_posts/2022-02-03-pixel-tests-update.md",
    "content": "---\ntitle: Pixel testing update\nauthor: mvo\ndate: 2022-02-03 10:00\ntags: cockpit\nslug: pixel-testing-update\ncategory: tutorial\ncomments: 'true'\n---\n\nSince May last year, the Cockpit integration tests contain \"pixel\ntests\", as described [here](pixel-testing.html).  Let's have a look at\nwhat has happened since then.\n\n## Mobile layout\n\nKaterina has made it so that all our integration tests run with two\nsizes of the browser: one time with the old \"desktop\" size\n(1920x1280), and again with a \"mobile\" size (414x1920). This has\nforced us to look more closely at how Cockpit behaves in such a narrow\nscreen, and we have since fixed it up quite a bit.\n\nBefore this, we had relied on people manually testing Cockpit in a\nmobile layout.  This was done occasionally, but now the mobile layout\nis almost a first class citizen, and I am certain we will keep fixing\nCockpit until we are fully happy with it.  My feeling is that this\nwould not have happened without automated pixel testing.\n\nA recent example is [this pull\nrequest](https://github.com/cockpit-project/cockpit-podman/pull/902).\nWe did know about the broken mobile layout of the images list, but the\nthing that kicked us to actually fix it was the enabling of \"mobile\"\npixel tests in the cockpit-podman repository.  Having to commit a\nobviously terrible reference image is unpleasant enough to finally sit\ndown and fix the thing.\n\nOf course, it helped that we had enough experience from fixing the\nmobile layout of Cockpit, and that's how the rising tide lifts all the\nboats: Soon everyone in the team will not only care about the mobile\nlayout, but also know how to fix any issues with it. We have managed\nto push the mobile layout over the threshold where it becomes\nrewarding to keep it in good shape, instead of it being so annyoing\nthat we would rather ignore it.\n\n## Some numbers\n\nRight now, we have 52 pixel tests in Cockpit itself, 20 in\nCockpit-machines, and 5 in Cockpit-podman.  Each pixel test has a\nreference image for three layouts, so we have 231 of them, totalling\nabout 10 MiB.  The Git repository with all their history is about 22\nMiB, for nine months of pixel testing.  (The main Cockpit repository is\nabout 110 MiB, for about nine years of hacking.)\n\nPixel tests are kind of slow, up to a few seconds per image\ncomparison.  They might increase the running time of our tests by a\ncouple of minutes.  We will have to measure this more carefully.\n\n## Reproducing pixels\n\nUnsurprisingly, it is non-trivial to make sure that the integration\ntests always perform a given pixel test with exactly the same result.\nWe know that we had to battle rendering issues from the start, but it\ntook us a bit to figure out the following:\n\n - Elements need to be scrolled into view before we can test their\n   pixels.  Obvious, but it needed to actually happen before we\n   realized it.\n\n - There are some animations, and we need to make sure that we don't\n   take a pixel test mid-animation.\n\n - When the Shell of Cockpit is changed, the content area for pages\n   like Networking might change size.  This is a problem for external\n   projects that don't control the version of the Cockpit shell.  We\n   worked around this by giving the content iframe a fixed size (by\n   making the browser window slightly bigger or smaller if necessary).\n\n - We would miss failed pixels when a test ran into a known issue. A\n   known issue would cause the test to be skipped, and one would have\n   to look very closely to spot that it also had a failing pixel\n   test. This means that we sometimes forgot to update some reference\n   images, and would later be surprised by how we could have missed\n   them.\n\n - As we change tests, we would accumulate unused reference images.\n   The bots now force us to clean up properly.\n\n - Even though the actual DOM rendering is suprisingly deterministic,\n   one or two pixels in a million still come out slightly differently,\n   from time to time.  We have no better idea but to allow a low\n   number of imperfections per pixel test.\n\nWith every change, we are more certain that we can get the pixel test\ncosts under control.  We might never reach a point where we can stop\ntweaking the pixel test machinery, but the same is true about our CI\ntesting machinery in general.\n\n## Why don't we hate them?\n\nI was expecting that adding pixel tests to Cockpit would be a hard\nsell, but we all seem to like them.  That's awesome!  What a team!\n\nI was afraid that pixel tests would be very unreliable because\nbrowsers would not be nearly pixel perfect enough.  But it turns out\nthat they are very good at this, actually, even across versions.  We\nhad to switch off font hinting, and results are not consistent between\nrunning the tests locally and runnning them in the cloud, but pixels\nare almost never changing randomly from one run to the next.\n\nThe unreliability comes mostly from not getting the DOM into the exact\nsame state every time a given pixel test runs. This has always been a\nproblem with our tests and we are pretty good at dealing with it.\n\nHowever, while the traditional tests were just code in the main repo,\npixel tests are binary files in a Git submodule. Submodules can be\nvery confusing, and we tried to hide most of it behind a script.  And\nGithub is actually pretty good with images.\n\nOne thing we have learned is to update reference images only very late\nin the life of a pull request. Resolving merge conflicts of binary\nfiles in a submodule is just not fun.\n\nI think we all like them because the value that we derive from pixel\ntests is well worth their cost. It feels awesome to officially replace\nan image of a sucky part of Cockpit with a nice one while fixing the\ncode, and to show off a new feature with a couple of screenshots that\nyou know will be kept from regressing.\n\nThe original goal, updating Patternfly and not having to worry about\nmissing visual regressions, has been reached.\n\nSo I would say the future looks good for pixel tests.  We are still\nadding more, and we have recently added a whole new browser size with\nit's own set of 77 new reference images.  We keep them working, and\nthey keep Cockpit pretty and us honest.\n\nI count that as a success!  And a lot of thanks to the team for being\nso willing to experiment.  Especially to Katerina for being even more\nexcited about pixel tests in the beginning than I was. 😁\n"
  },
  {
    "path": "_posts/2022-02-16-cockpit-263.md",
    "content": "---\ntitle: Cockpit 263\nauthor: garrett\ndate: '2022-02-16'\ntags: cockpit\nslug: cockpit-263\ncategory: release\nsummary: 'Browser history fixes (back/forward buttons)'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 263:\n\n\n\n## Back and forward browser buttons work as expected\n\nCockpit used to interfere with browser history. Clicking the back button would frequently get into a loop. Browser history handling is now fixed, so navigating back works as expected.\n\nAdditionally, back and forward buttons have been added to [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient), the desktop app to connect to Cockpit servers using SSH.\n\n\n## Try it out\n\nCockpit 263 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/263)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-7b7b2119dc)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-79368331c2)\n"
  },
  {
    "path": "_posts/2022-03-16-cockpit-265.md",
    "content": "---\ntitle: Cockpit 265\nauthor: skobyda\ndate: '2022-03-16'\ntags: cockpit, machines\nslug: cockpit-265\ncategory: release\nsummary: 'Animated lists, X-Forwarded-For support, crypto policies, disk serial number, metrics showing busiest CPU core, manifest overrides location'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 265 and cockpit-machines 264:\n\n\n## Animate new rows in lists\n\nWhen new items appear on a page, they are highlighted for a short while to make it easier to notice them.\n\n![Peek 2022-03-15 07-47]({{ site.baseurl }}/images/265-animate-new-rows-in-lists.gif)\n\n## Support for `X-Forwarded-For`\n\nWhen run in a configuration involving a reverse proxy server, Cockpit can now report the client IP address as provided to it by the proxy server, rather than using the IP of the proxy server itself.  This impacts what appears in system login logs, for example, and may have an impact on authentication, depending on which pam modules are in use.\n\nSupport for this feature must be explicitly enabled via the new `ForwardedForHeader` option in the [configuration file](https://cockpit-project.org/guide/latest/cockpit.conf.5.html).\n\n## Manifest overrides in /etc and ~/.config directories\n\n[Manifest override files](https://cockpit-project.org/guide/latest/packages.html#package-replace) are a way to customize or hide a Cockpit page's menu entries. Until now these needed to be put next to the `manifest.json` which they modify, for example `/usr/share/cockpit/systemd/override.json`. However, `/usr/share/` is package manager territory, and admins should not (and in some cases cannot) write files there. With this Cockpit version, these overrides can now be placed into `/etc/cockpit/systemd.override.json` for global customizations, or `~/.config/cockpit/systemd.override.json` for user-specific ones.\n\n## Crypto policies support\n\nCockpit now has basic support for displaying and changing a subset of crypto policies (default, future, legacy). The current configured crypto policy is shown in the \"Configuration\" card.\n\n![Crypto policies card]({{ site.baseurl }}/images/265-crypto-policies-support.png)\n\nCrypto policy changes can be applied immediately or later. When \"Apply only\" is selected, the Health card shows that a reboot is required to fully apply the changed crypto policy.\n\n![Crypto policies modal]({{ site.baseurl }}/images/265-crypto-policies-support-2.png)\n\n## Metrics: Show busiest CPU core\n\nOn multi-core systems, the Metrics page now shows an additional usage bar for the CPU core with the highest usage. This points out bottlenecks and performance problems which happen because only a few cores (or even a single one) get fully used, while many others are mostly idle. In that case, the average CPU usage will be low.\n\n![screenshot of show busiest cpu core]({{ site.baseurl }}/images/265-metrics-show-busiest-cpu-core.png)\n\n## Machines: Disk serial number\n\nA disk identifier can now be specified for attached disks. This is the identifier that appears for the disk in /dev/disk/by-id on Linux systems and might be useful for multipath storage setups. It may also be useful with proprietary software which is licensed to specific disk serial numbers (which is sometimes seen on Windows).\n\n![Disk serial number modal]({{ site.baseurl }}/images/265-machines-disk-serial-number.png)\n\n\n## Try it out\n\nCockpit 265 and cockpit-machines 264 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/265)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-ad93e6cdcb)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-ec9612ac99)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/264)\n* [cockpit-machines Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-7e1cbde0f7)\n* [cockpit-machines Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-2cd2b4d57d)\n\n*[CPU]: Central Processing Unit, the \"brain\" of a computer\n*[repo]: repository\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2022-03-30-cockpit-266.md",
    "content": "---\ntitle: Cockpit 266\nauthor: garrett\ndate: '2022-03-30'\ntags: cockpit\nslug: cockpit-266\ncategory: release\nsummary: ''\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 266:\n\n\n## Standardize on SI-based units for data sizes and rates\n\nPhysical storage, network devices, and network transmission speeds have all been sold and used in decimal units for a long time. As of this release, all sizes and rates are now shown in SI units (International System of Units), such as \"MB\" or \"kB/s\". This aligns Cockpit with what most users expect. It also avoids some inconsistencies, such as the Metrics page showing available/used RAM in decimal units, but the memory usage of individual services in binary units.\n\nOnly total RAM size on the Overview, the size of individual RAM modules on the Hardware Details page, and the size of KDump memory are shown in binary units such as MiB or GiB.\n\n![stats]({{ site.baseurl }}/images/266-standardize-on-si-based-units-for-data-sizes-and-rates.png)\n\n\n## Try it out\n\nCockpit 266 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/266)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/?releases=F36&packages=cockpit)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/?releases=F35&packages=cockpit)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n*[RAM]: Random Access Memory"
  },
  {
    "path": "_posts/2022-04-13-cockpit-267.md",
    "content": "---\ntitle: Cockpit 267\nauthor: pitti\ndate: '2022-04-13'\ntags: cockpit, machines\nslug: cockpit-267\ncategory: release\nsummary: ''\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 267 and cockpit-machines 266:\n\n\n## FIPS crypto policy support\n\nThe Federal Information Processing Standard (FIPS) is a computer security standard developed by the U.S. Government and industry working group to validate the quality of cryptographic modules. See the official FIPS publications at [NIST Computer Security Resource Center](https://csrc.nist.gov/publications/fips).\n\nIn Red Hat Enterprise Linux, CentOS Stream, and Fedora Linux, the crypto policy dialog can now enable or disable FIPS mode, using the [fips-mode-setup command](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/security_hardening/assembly_installing-a-rhel-8-system-with-fips-mode-enabled_security-hardening). Cockpit will also validate the consistency of the kernel and user-space configuration, and can reapply FIPS when settings are out of sync.\n\n![screenshot of fips crypto policy support]({{ site.baseurl }}/images/267-fips-crypto-policy-support.png)\n\n## Machines: Redesign VM creation\n\nThe virtual machine creation dialog has been reorganized using two tabs: a mandatory \"Details\" configuration and an optional \"Automation\" configuration. The automation section can set passwords and create an account on supported operating systems when either \"Download an OS\" or \"Cloud base image\" are selected.\n\nClicking on \"Create and run\" will create, immediately start, and install the VM. Clicking on \"Create and edit\" will create the VM in a \"shut-off\" state and redirect the user to the details page, where the VM may be further customized before starting installation.\n\n![details_tab]({{ site.baseurl }}/images/267-machines-redesign-vm-creation.png)\n\n![automation_tab]({{ site.baseurl }}/images/267-machines-redesign-vm-creation-2.png)\n\n## Machines: Remove static hosts from virtual network's DHCP\n\nThe \"static host\" entries now have a \"remove\" action.\n\n![network_overview]({{ site.baseurl }}/images/267-machines-remove-static-hosts-from-virtual-network-s-dhcp.png)\n\n\n## Try it out\n\nCockpit 267 and cockpit-machines 266 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/267)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-9da2abe257)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-70c1d3d182)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/266)\n* [cockpit-machines Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-6112b9e895)\n* [cockpit-machines Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-adfdc882ed)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n*[FIPS]: Federal Information Processing Standard\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2022-04-28-cockpit-268.md",
    "content": "---\ntitle: Cockpit 268.1\nauthor: garrett\ndate: '2022-04-28'\ntags: cockpit\nslug: cockpit-268\ncategory: release\nsummary: 'The software page gets a kpatch button'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 268:\n\n\n## Software Updates: Only install kpatches\n\nLive patch a kernel without having to reboot or restart services with the new \"Install kpatch updates\" button. This allows patching of urgent kernel vulnerabilities without rebooting.\n\n![kpatch]({{ site.baseurl }}/images/268-software-updates-only-install-kpatches.png)\n\n\n## Try it out\n\nCockpit 268, cockpit-machines 267 and cockpit-podman 47 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/268.1)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-8424dd3406)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-52ac2f1c54)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/267)\n* [cockpit-machines Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-f7e9fedee3)\n* [cockpit-machines Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-6a723bb16e)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/47)\n* [cockpit-podman Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-e4f3bfc436)\n* [cockpit-podman Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-ab108a14c9)\n\n"
  },
  {
    "path": "_posts/2022-05-12-cockpit-269.md",
    "content": "---\ntitle: Cockpit 269\nauthor: garrett\ndate: '2022-05-12'\ntags: cockpit, machines\nslug: cockpit-269\ncategory: release\nsummary: 'Dark mode for Cockpit Client, metrics usage shows containers, default fallback name for new VMs'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 269 and cockpit-machines 268:\n\n\n## Dark mode for Cockpit Client\n\nThe chrome of [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient) now follows the system dark style preference.  We're working on adding dark mode for Cockpit itself in the near future.\n\n![cockpit client, in dark mode compared to light mode]({{ site.baseurl }}/images/269-cockpit-client-dark.png)\n\n## Metrics: Show Podman containers in top CPU and memory lists\n\nCurrent metrics cards for CPU and memory now show [Podman](https://podman.io/) containers, in addition to systemd services. \n\n![container memory usage]({{ site.baseurl }}/images/269-metrics-show-podman-containers-in-top-cpu-and-memory-lists.png)\n\n## Machines: Provide default name for new VMs\n\nIf no name is specified for a new virtual machine, generate a unique name based on the name of the operating system. The autogenerated name is visible only after the operating system is selected.\n\n![create VM dialog with a generated default name]({{ site.baseurl }}/images/269-machines-provide-default-name-for-new-vms.png)\n\n\n## Try it out\n\nCockpit 269 and cockpit-machines 269 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/269)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-8204559683)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-911bd0f4a3)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/269)\n* [cockpit-machines Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-4b47be5825)\n* [cockpit-machines Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-fb2e44c08b)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n*[CPU]: Central Processing Unit, the \"brain\" of a computer\n*[VM]: Virtual Machine\n*[VMs]: Virtual Machines\n"
  },
  {
    "path": "_posts/2022-05-24-cockpit-270.md",
    "content": "---\ntitle: Cockpit 270\nauthor: garrett\ndate: '2022-05-24'\ntags: cockpit, machines, podman\nslug: cockpit-270\ncategory: release\nsummary: 'Timer deletions, improved system diagnostics, better remove & deletion dialogs for VMs, container renaming, and container health checks'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 270, cockpit-machines 269, and cockpit-podman 48:\n\n\n## Services: User-created timer deletion\n\nUser-created systemd timers (in `/etc/systemd/system`) can now be deleted.\n \n![screenshot of delete in the timer menu]({{ site.baseurl }}/images/270-services-user-created-timer-deletion.png)\n\n![screenshot of user-created timer deletion dialog]({{ site.baseurl }}/images/270-services-user-created-timer-deletion-2.png)\n\n## System Diagnostics: Working with diagnostic reports has been improved\n\nThe Diagnostic Reports page now lists all reports that have been created. Reports can be downloaded and removed from the list. When creating a new report, several options can be specified.\n\n![system diagnostics screenshot]({{ site.baseurl }}/images/270-system-diagnostics-working-with-diagnostic-reports-has-been-improved.png)\n\n## Machines: Redesign content removal dialogs\n\nDialogs for deleting resources on the Machines page now show details about which resources are about to be deleted. \n\nFor example: Removing host devices from the VM shows the host device with identifying information such as vendor, product, and slot number.\n\n![screenshot of removing host devices]({{ site.baseurl }}/images/270-machines-remove-device.png)\n\nAnother example: When deleting a storage pool, optional deletion of volumes now shows which volumes would be deleted.\n\n![screenshot of deleting a storage pool]({{ site.baseurl }}/images/270-machines-delete-pool.png)\n\n## Podman: Container renaming\n\nContainer names can be changed from the container's menu.\n\n![screenshot of rename dialog]({{ site.baseurl }}/images/270-podman-container-renaming.png)\n\n_Thanks to Pavel Stržínek for this feature!_\n\n## Podman: Health check support\n\nHealth checks can be set up when creating a container. In container details, the current health check result and history can be viewed. Additionally, in the details, health checks can be manually triggered.\n\n![screenshot of health checks in Cockpit-Podman]({{ site.baseurl }}/images/270-support-for-health-checks.png)\n\n\n## Try it out\n\nCockpit 270, cockpit-machines 269, and cockpit-podman 48 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/270)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-d1b9fc4e30)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-ed88e19a91)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/269)\n* [cockpit-machines Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-249a94b0af)\n* [cockpit-machines Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-aeb2edb3a9)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/48)\n* [cockpit-podman Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-bd43bce242)\n* [cockpit-podman Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-60a9b137db)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n*[repo]: repository\n*[VM]: Virtual Machine"
  },
  {
    "path": "_posts/2022-06-08-cockpit-271.md",
    "content": "---\ntitle: Cockpit 271\nauthor: garrett\ndate: '2022-06-08'\ntags: cockpit\nslug: cockpit-271\ncategory: release\nsummary: 'Container names on the metrics page'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 271, cockpit-machines 270.1 and cockpit-podman 49.1:\n\n\n## Metrics: Show container names\n\nInstead of just showing a container ID, Cockpit now displays Podman container names in the CPU and Memory usage cards on the \"Metrics and history\" page.\n\nAdditionally, after clicking a container name on the Metrics page, you'll see just the container you clicked on within Cockpit-Podman, thanks to improved filtering.\n\n![screenshot of ## show container names on the metrics page]({{ site.baseurl }}/images/271-show-container-names-on-the-metrics-page.png)\n\n\n## Try it out\n\nCockpit 271, cockpit-machines 270.1 and cockpit-podman 49.1 is available now:\n\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/271)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-4869d82c66)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-80d2aa8e21)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/270.1)\n* [cockpit-machines Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-f627536f09)\n* [cockpit-machines Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-fde99ff139)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/49.1)\n* [cockpit-podman Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-46d3943e7e)\n* [cockpit-podman Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-dc55d16cc1)\n\n*[CPU]: Central Processing Unit, the \"brain\" of a computer\n"
  },
  {
    "path": "_posts/2022-06-23-cockpit-272.md",
    "content": "---\ntitle: Cockpit 272\nauthor: garrett\ndate: '2022-06-23'\ntags: cockpit\nslug: cockpit-272\ncategory: release\nsummary: 'Edit custom firewall ports, pin favorite services, dark login support, and unprivilaged cockpit/ws mode'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 272:\n\n## Firewall: Edit custom services\n\nThe Firewall page is able to open custom ports by creating custom services. This release adds the ability to edit custom services.\n\n![edit-custom]({{ site.baseurl }}/images/272-firewall-edit-custom-services.png)\n\n## Services: Pin services as favorites\n\nThe services page now allows users to pin any service to the top of the services list.\n\n![pin-2]({{ site.baseurl }}/images/272-services-pin-services-as-favorites.png)\n\nTo pin a service, navigate to its detail page and click \"Pin unit\" in the menu next to its name.\n\n![pin]({{ site.baseurl }}/images/272-services-pin-services-as-favorites-2.png)\n\n## Login: Dark mode\n\nThe login page now has a dark mode which changes with your system's dark settings. Most desktops have a setting for this in \"appearance\" area in system settings, including GNOME, KDE, Windows, macOS, Android, and iOS/iPadOS.\n\nHere's [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient), which [also recently got dark mode a few releases ago](https://cockpit-project.org/blog/cockpit-269.html), in the standard light mode:\n\n![Screenshot from 2022-06-22 18-42-47]({{ site.baseurl }}/images/272-login-dark-mode.png)\n\nAnd after switching to dark settings, it looks like this:\n\n![Screenshot from 2022-06-22 18-42-59]({{ site.baseurl }}/images/272-login-dark-mode-2.png)\n\nWe’re still working on adding dark mode for Cockpit once you've logged in.\n\n## Unprivileged cockpit/ws container mode\n\nThe [cockpit/ws container](https://quay.io/repository/cockpit/ws) can now run in unprivileged mode.\n\nIt presents an unbranded variant of login page that always asks for a host name. Connections are made with SSH.\n\nThis mode is suitable for deploying to, e.g., Kubernetes or similar environments, where you don't have or want privileged containers. In this \"bastion host mode\", you can have Cockpit for servers in your data center without opening an extra port for `cockpit-ws`.\n\nCurrently, username + password and \"classic RSA\" type SSH keys are supported. See the container documentation for details.\n\n## Try it out\n\nCockpit 272 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/272)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-b1b932456b)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/FEDORA-2022-f70c5381e2)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n*[OS]: Operating System\n*[repo]: repository\n*[SSH]: Secure Shell, a common protocol to securely connect to a remote computer"
  },
  {
    "path": "_posts/2022-07-20-cockpit-273.md",
    "content": "---\ntitle: Cockpit 273\nauthor: garrett\ndate: '2022-07-20'\ntags: cockpit, machines\nslug: cockpit-273\ncategory: release\nsummary: CPU temperature, easier manual IP configuration, auto-reboot after software updates, install RHEL VMs\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 273 and cockpit-machines 272:\n\n## Metrics: Display CPU temperature\n\nThe metrics page now displays the CPU temperature and includes a warning icon when the system becomes too hot.\n\n![cpu-temp-warn]({{ site.baseurl }}/images/273-metrics-display-cpu-temperature.png)\n\n## Networking: Suggest netmask and gateway addresses\n\nWhen adding a manual IPv4 address to a network interface, the dialog now fills in plausible values for the net mask (based on the network class) and gateway (usually ending with .1 or .254).\n\n![ipv4-helper-animation]({{ site.baseurl }}/images/273-networking-suggest-netmask-and-gateway-addresses.gif)\n\n_Thanks to Gil Obradors for contributing this feature!_\n\n## Software Updates: Optionally reboot after updating\n\nWhile updating a system, there is a new option to automatically reboot after the update process succeeds.\n\n![screenshot of optionally reboot after updating]({{ site.baseurl }}/images/273-software-updates-optionally-reboot-after-updating.png)\n\n## cockpit/ws container: Support modern SSH keys\n\n[Cockpit 272](https://cockpit-project.org/blog/cockpit-272.html) introduced [cockpit/ws container](https://quay.io/repository/cockpit/ws) support for authenticating with classic RSA PEM type SSH keys. This was improved to support all key types, in particular the \"OpenSSH\" format or EC types.\n\n## Machines: Download RHEL images\n\nYou can now easily create Red Hat Enterprise Linux VMs. The create dialog links to the page to get a download token tied to your Red Hat subscription, and uses the token to download the selected RHEL VM image.\n\n![vm-create-rhel]({{ site.baseurl }}/images/273-machines-download-rhel-images.png)\n\n\n## Try it out\n\nCockpit 273 and cockpit-machines 272 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/273)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/?releases=F36&packages=cockpit)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/?releases=F35&packages=cockpit)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/272)\n* [cockpit-machines Fedora 36](https://bodhi.fedoraproject.org/updates/?releases=F36&packages=cockpit-machines)\n* [cockpit-machines Fedora 35](https://bodhi.fedoraproject.org/updates/?releases=F35&packages=cockpit-machines)\n\n*[CPU]: Central Processing Unit, the \"brain\" of a computer\n*[repo]: repository\n*[RHEL]: Red Hat Enterprise Linux\n*[SSH]: Secure Shell, a common protocol to securely connect to a remote computer\n*[VM]: Virtual Machine\n*[VMs]: Virtual Machines\n"
  },
  {
    "path": "_posts/2022-08-25-cockpit-275.md",
    "content": "---\ntitle: Cockpit 275\nauthor: jelle\ndate: '2022-08-25'\ntags: cockpit, podman\nslug: cockpit-275\ncategory: release\nsummary: Support for alternatives to sudo, image history, restart policy, container ports, volumes and environments\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 275 and cockpit-podman 52:\n\n\n## Shell: Support for alternatives to sudo\n\nCockpit has always had the theoretical ability to run arbitrary programs to gain administrative access, by adding them to a package manifest.  However, the UI would always use \"sudo\". Now, if multiple programs are defined, the UI will prompt for which one to use.\n\nBy default, Cockpit will still only use \"sudo\", so unless you actually add more programs via a manifest, there will be no visible change in the UI.\n\n\n## Podman: Image history\n\nThe image detail view now has a new tab which shows the image history similar to `podman image history`.\n\n![screenshot of ## image history]({{ site.baseurl }}/images/275-image-history.png)\n\n## Podman: Restart policy available for users with lingering enabled\n\nAlthough lingering is not recommended, cockpit-podman now supports setting a restart policy when a user has enabled lingering.\n\n## Podman: Display ports, volumes and environment variables\n\nPublished ports, mounted volumes and environment variables are now visible in container integration tab.\nBy default only variables set by user are shown. After clicking `Show more` all variables are visible.\n\n![containers-integration]({{ site.baseurl }}/images/275-display-ports-volumes-and-environment-variables.png)\n\n\n## Try it out\n\nCockpit 275 and cockpit-podman 52 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/275)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/?releases=F36&packages=cockpit)\n* [Cockpit Fedora 35](https://bodhi.fedoraproject.org/updates/?releases=F35&packages=cockpit)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/52)\n* [cockpit-podman Fedora 36](https://bodhi.fedoraproject.org/updates/?releases=F36&packages=cockpit-podman)\n* [cockpit-podman Fedora 35](https://bodhi.fedoraproject.org/updates/?releases=F35&packages=cockpit-podman)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n"
  },
  {
    "path": "_posts/2022-09-22-cockpit-277.md",
    "content": "---\ntitle: Cockpit 277\nauthor: garrett\ndate: '2022-09-22'\ntags: cockpit, machines, podman\nslug: cockpit-277\ncategory: release\nsummary: 'Login fixes, RHEL downloading improvements, Podman containers visible by default'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 277, cockpit-machines 275, and cockpit-podman 54:\n\n\n## Login: Improve password manager compatibility\n\nThe HTML of the login page has been adjusted to be more compatible with password managers in popular browsers. Usernames and passwords are more likely to be prefilled or selectable, depending on the password manager and browser.\n\n_Thanks to [Jacek Tomasiak](https://github.com/skazi0) for pointing this out and providing a fix!_\n\n## Login: Fix \"This web browser is too old\" error with upcoming browsers\n\nNewer, upcoming browser versions have improved next-level support for `:is()` and `:where()` selectors. Cockpit was checking for support an empty usage which passed on browsers in the earlier (current as of writing) implementation. However, browsers have recently updated their parsing support for \"[Forgiving Selector Parsing](https://developer.mozilla.org/en-US/docs/Web/CSS/:is#forgiving_selector_parsing)\", which caused the newer development versions of Firefox, Chrome, and WebKit to fail this check, preventing the browsers from logging into Cockpit.\n\nThe check has now been adjusted so current and upcoming browser versions all pass.\n\nAdditionally, hotfixes for older versions of Cockpit have been published for various distributions. If you have an error while trying to log in with a new browser on an older Cockpit version, please upgrade your version of Cockpit.\n\nUpdates have been issued for the following distributions and versions:\n\n  - ✅ **CentOS Stream 8 & 9**: Fixed.\n  - ✅ **Fedora**: Fixed in ≥ 36.\n  - ⌛ **RHEL 8.6 & 9.0** are affected, fixes are not yet published.\n  - ✅ **RHEL** versions older than 8.6 are *not* affected.\n  - ✅ **Debian**: Fixed in testing and backports. Stable (11 and earlier)  are *not* affected.\n  - ✅ **Ubuntu Kinetic** (current devel series) and the backport for 22.04 LTS got fixed. \n  - ⌛ **Ubuntu 22.04 LTS** is still affected, but will be fixed soon.\n\n_Huge thanks to [Emilio Cobos Álvarez](https://github.com/emilio) for bringing this to our attention and sending a PR with a fix!_\n\n## Machines: RHEL offline token management improvements\n\nDownloading Red Hat Enterprise Linux directly from within Cockpit's Machines page requires an offline token. It's now validated on entry.\n\n![demo1]({{ site.baseurl }}/images/277-machines-rhel-offline-token-management-improvements.gif)\n\nValid tokens are saved in browser LocalStorage and re-validated and re-used the next time a machine image is downloaded.\n\n![demo2]({{ site.baseurl }}/images/277-machines-rhel-offline-token-management-improvements-2.gif)\n\n## Podman: Show all containers by default\n\nCockpit-podman now shows all containers by default. This is especially useful for seeing containers that are stopped or restarting.\n\n\n## Try it out\n\nCockpit 277, cockpit-machines 275, and cockpit-podman 54 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/277)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2022-c0ec7a8253)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-a80ce9a9a5)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/275)\n* [cockpit-machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2022-910c7c7686)\n* [cockpit-machines Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-1ed4f71302)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/54)\n* [cockpit-podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2022-7b2348ff9f)\n* [cockpit-podman Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-156cda8c46)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n*[OS]: Operating System\n*[repo]: repository\n*[RHEL]: Red Hat Enterprise Linux"
  },
  {
    "path": "_posts/2022-10-18-cockpit-278.md",
    "content": "---\ntitle: Cockpit 278\nauthor: jelle\ndate: '2022-10-19'\ntags: cockpit, podman\nslug: cockpit-278\ncategory: release\nsummary: 'Multiple disk throughput in metrics, stats in Cockpit Podman pods, create new Pod'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 278 and cockpit-podman 55:\n\n\n## Metrics: Display individual disk read/write usage\n\nMetrics can show individual disk throughput of multiple disks.\n![screenshot of display individual disk read/write usage]({{ site.baseurl }}/images/278-metrics-display-individual-disk-read-write-usage.png)\n\n\n## Pod CPU, memory, port and volume details\n\nPodman now displays CPU, memory usage, ports, and volumes of the containers in a pod.\n\n![screenshot of ## pod cpu, memory, port and volume details]({{ site.baseurl }}/images/278-pod-cpu-memory-port-and-volume-details.png)\n\nClicking on the port icon shows the port mapping of the pod.\n\n![screenshot of ## pod cpu, memory, port and volume details]({{ site.baseurl }}/images/278-pod-cpu-memory-port-and-volume-details-2.png)\n\n## Create new pod support\n\nPodman can now create pods, including optional port and volume mappings.\n\n![screenshot of ## ability to create new pod group]({{ site.baseurl }}/images/278-ability-to-create-new-pod-group.png)\n\n\n![Screenshot from 2022-10-04 11-53-51]({{ site.baseurl }}/images/278-ability-to-create-new-pod-group-2.png)\n\n\n## Try it out\n\nCockpit 278 and cockpit-podman 55 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/278)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2022-957c7eaa0d)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-614e5cb4e7)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/55)\n* [cockpit-podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2022-d1924d2873)\n* [cockpit-podman Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-8e6b0d9122)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n*[CPU]: Central Processing Unit, the \"brain\" of a computer\n"
  },
  {
    "path": "_posts/2022-10-20-login-issues.md",
    "content": "---\ntitle: \"Login issues with newer browsers\"\nauthor: garrett\ntags: cockpit\n---\n\n## Quick summary\n\n**_Last updated on 2022-11-09**: All major distributions should now have fixed packages._\n\nIf you're experiencing an issue logging in to Cockpit with an error about `:where():is()` support:\n\n- In most cases, update your servers. [Cockpit 277](cockpit-277), released last month, has the fix.\n- After updating, if you see the error, it may be cached. Reload the page. In some cases, you may even need to hold down shift, just to be sure. (`Shift`+`Ctrl`+`R` or `Shift`+`F5` or hold down Shift while clicking the refresh icon)\n\nUpdating Cockpit should work for Arch, CentOS Stream, Debian, Fedora, openSUSE, Ubuntu, Red Hat Enterprise Linux (and derivatives, such as Alma Linux and Rocky Linux), and likely other distributions that ship Cockpit.\n\nIf updating still doesn't work for your distribution, then hopefully it will work very soon. For the time being, please [look at the bottom of this post for some workarounds](#workarounds).\n\n## Summary\n\nLogging in with new versions of browsers into a few older versions of Cockpit is currently broken due to a check in the login code. This check used to pass in all browsers, but very recently every browser has changed the way they parse the string. Firefox release 106 — released this week — has this parsing change; all other browsers will have it in upcoming versions too.\n\nWe fixed this bug as soon as it was discovered (a month ago) and pushed [a new release of Cockpit](cockpit-277) and also backported it as a hotfix to all the \"stable\" slower-moving distributions.\n\nAll distributions have had the fix for a around a month. Most distributions have accepted and published the fix, including Arch Linux, CentOS Stream 8 & 9, Debian, Ubuntu, Fedora, openSUSE Tumbleweed, and Red Hat Linux Enterprise Linux 8.7 and 9.1.\n\nDue to the nature of enterprise/LTS distributions the fixes have not landed yet in Red Hat Enterprise Linux 8.6 & 9.0, Alma Linux, and Rocky Linux.\n\n## Affected browsers\n\nRight now (2022-10-20): Using Firefox 106 with Cockpit is affected. However, Chrome, Edge, Brave, and any other Chromium-based browser will have versions in the very near future which will also be affected. WebKit-based browsers, such as Safari and GNOME Web will likely be affected soon as well.\n\nFirefox ESR (Extended Support Release) is slower-moving and is on 102.x and is not affected, nor will it be affected until Q3 2023 (2023-07-04 specifically, according to [the Firefox release schedule](https://wiki.mozilla.org/Release_Management/Calendar)).\n\n## Workarounds\n\n### If packages are not yet available for your distribution\n\nWe suggest using an official package, but if packages are not yet available for your distribution, we have a simple, quick fix.\n\nThis sed command adds the two characters to the webpacked JS file for the login page. Run it as an administrator (`root` account) on a server with Cockpit installed:\n\n```\nsed -i 's/is():where()/is(*):where(*)/' /usr/share/cockpit/static/login.js\n```\n\nIt works on every distribution that has Cockpit's `login.js` in `/usr/share/cockpit/static/`. If your distribution has the file elsewhere, then change the path accordingly.\n"
  },
  {
    "path": "_posts/2022-11-03-cockpit-279.md",
    "content": "---\ntitle: Cockpit 279\nauthor: garrett\ndate: '2022-11-03'\ntags: cockpit, machines\nslug: cockpit-279\ncategory: release\nsummary: 'Dark mode, insert and eject disc media for VMs, and allow trim on VM disks'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 279 and cockpit-machines 277:\n\n\n## Dark mode support\n\nCockpit now switches to a dark theme when system dark mode is enabled.\n\nWhile many people just think it looks cool, dark mode is also an accessibility setting which helps people with various eyesight conditions and migraines. Dark mode can be easier to use in a dark environment as well.\n\n![light to dark animation]({{ site.baseurl }}/images/279-dark-mode-support.gif)\n\nMost modern desktops and operating systems have system-level controls to switch between light and dark modes.\n\n- [**GNOME** 42 added dark mode support](https://release.gnome.org/42/) in the \"Settings\" app, under \"Appearance\". [GNOME 43](https://release.gnome.org/43/) went a step further and added a toggle in the menu at the top-right of the screen. GNOME is the default desktop of distributions such as Fedora Linux, Red Hat Enterprise Linux, CentOS Stream, Ubuntu, Intel Clear Linux*, and several others.\n- **KDE** ships with a light and dark theme and has a switch in settings. There is [a bug between KDE and Chromium](https://bugs.chromium.org/p/chromium/issues/detail?id=998903), however, but [it does have a workaround](https://www.reddit.com/r/kde/comments/wjnuk3/enable_kde_dark_mode_so_that_apps_website_detect/). Firefox is fine by default.\n- [**Windows 10**](https://support.microsoft.com/en-us/windows/change-colors-in-windows-d26ef4d6-819a-581c-1581-493cfcc005fe#WindowsVersion=Windows_10) and [**Windows 11**](https://support.microsoft.com/en-us/windows/change-colors-in-windows-d26ef4d6-819a-581c-1581-493cfcc005fe#WindowsVersion=Windows_11) both have light and dark mode settings in the [Windows Settings app under \"Personalization\" > \"Colors\"](https://blogs.windows.com/wp-content/uploads/prod/sites/2/2019/03/c994efd5af9c359253e4d200115e2981.gif).\n- [**macOS** has auto, dark, and light modes](https://support.apple.com/en-us/HT208976) in the settings app.\n- [**iPhones** and **iPads** support light and dark modes](https://support.apple.com/en-us/HT210332) in settings and control center, and can auto-adjust based on a schedule.\n- [**Android** 9 (2018) and up have dark mode support](https://support.google.com/pixelphone/answer/7169926?hl=en), and recent versions can adjust on a schedule. Some other popular devices such as Samsung and OnePlus have had dark mode support for some time as well.\n- **Browsers** such as Firefox, Chrome, and Safari have the option to manually set dark or light mode or use the system setting. On Linux, if the standard desktop setting is not supported by a desktop, most browsers will usually guess based on the system theme (dark text on light background or vice versa).\n- [**Cockpit Client**](https://flathub.org/apps/details/org.cockpit_project.CockpitClient), the native Linux desktop app, has dark and light mode support. It supports the system setting and passes this information to Cockpit.\n\n## Allow TRIM/UNMAP requests by default for newly added disks\n\n\"Trim\" is a method to reduce space used by data on a disk.\n\nWhen creating a new VM or adding a new disk to a VM, Cockpit Machines configures libvirt to respect an operating system's trim commands.\n\nPlease note that this change only allows trim requests to be sent. It doesn't set up any periodic trim mechanism. Most Linux distributions are already set up to send trim commands for SSDs and disk images by default. Other recent versions of operating systems, such as Windows, also sends trim commands. Some older operating systems and distributions do not send trim and would require manual configuration to use this space-saving option.\n\n## Insert and eject CD & DVD media\n\nCD and DVD media can be inserted and ejected while a VM is running.\n\n![Screenshot from 2022-11-03 00-44-56]({{ site.baseurl }}/images/279-insert-and-eject-cd-dvd-media.png)\n\n![Screenshot from 2022-11-03 00-47-06]({{ site.baseurl }}/images/279-insert-and-eject-cd-dvd-media-2.png)\n\n\n## Try it out\n\nCockpit 279 and cockpit-machines 277 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/279)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2022-6d41f89647)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-9dd5ded435)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/277)\n* [cockpit-machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2022-c10ca09579)\n* [cockpit-machines Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-75729ed52d)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n*[OS]: Operating System\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2022-11-16-cockpit-280.md",
    "content": "---\ntitle: Cockpit 280\nauthor: garrett\ndate: '2022-11-16'\ntags: cockpit\nslug: cockpit-280\ncategory: release\nsummary: 'Disallow root login by default'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 280:\n\n\n## Disallow root login by default\nOn all operating systems, logging in as root with a username/password via SSH has been disallowed for a long time. Cockpit now also disallows it by default on new installations, but still allows it on upgrades for backwards compatibility. You can configure this in `/etc/cockpit/disallowed-users`.\n\n\n## Try it out\n\nCockpit 280 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/280)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2022-fbe5e7a3cf)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-68ab2e0405)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n*[SSH]: Secure Shell, a common protocol to securely connect to a remote computer\n"
  },
  {
    "path": "_posts/2022-12-01-cockpit-281.md",
    "content": "---\ntitle: Cockpit 281\nauthor: garrett\ndate: '2022-12-01'\ntags: cockpit, machines\nslug: cockpit-281\ncategory: release\nsummary: 'Style switcher and disk autodetection'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 281 and cockpit-machines 279:\n\n\n## Add style switcher\n\nOverride your system's style with Cockpit's new style switcher. It's great for the times when you might want a dark Cockpit but your system is in light mode. Or vice versa.\n\nAdditionally, some browsers have issues picking up on the correct system dark mode setting, so this lets you manually set the mode you prefer.\n\nYou can find the style switcher in the session menu.\n\n![Screenshot from 2022-12-01 18-14-22]({{ site.baseurl }}/images/281-add-style-switcher.png)\n\n## Machines: Autodetect disk image type in custom path\n\nCockpit Machines now detects the format of disks added using \"custom path\". Raw and qcow formatted disk images are supported. However, qcow2 images with a backing file are currently not supported.\n\n\n## Try it out\n\nCockpit 281 and cockpit-machines 279 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/281)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2022-3ac87b0700)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-01f43fdd53)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/279)\n* [cockpit-machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2022-3d1a053edf)\n* [cockpit-machines Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-86b857a50d)\n"
  },
  {
    "path": "_posts/2022-12-14-cockpit-282.md",
    "content": "---\ntitle: Cockpit 282\nauthor: garrett\ndate: '2022-12-14'\ntags: cockpit\nslug: cockpit-282\ncategory: release\nsummary: 'Accounts page redesign and right-to-left language support'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 282:\n\n\n## Accounts: Redesign and include groups\n\nThe Accounts page has been redesigned. Groups are listed at the top of the page and the list of users is enhanced with details and filtering. Additionally, a user's groups can be edited while viewing details for the user.\n\n![screenshot of redesign and include groups]({{ site.baseurl }}/images/282-accounts-redesign-and-include-groups.png)\n\n![screenshot of redesign and include groups]({{ site.baseurl }}/images/282-accounts-redesign-and-include-groups-2.png)\n\n## Right-to-left language support\n\nRight-to-left language support has been enabled for languages that require it. When selecting a RTL language from the list, the layout will shift to be right-aligned.\n\nWe have also started modifying Cockpit and PatternFly to work better with RTL languages. However, there are still some alignment and spacing issues. We will continue to work to fix the more obvious problems.\n\nIf you know Hebrew (Cockpit's most complete RTL translation) or other RTL languages, please help us improve the implementation and translations by [filing issues on GitHub](https://github.com/cockpit-project/cockpit/issues/new?labels=bug,i18n), sending pull requests, and/or [improving translations on weblate](https://translate.fedoraproject.org/projects/cockpit/main/).\n\n\n## Try it out\n\nCockpit 282 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/282)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2022-14210d1ef5)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2022-9eabd9cf61)\n\n*[repo]: repository"
  },
  {
    "path": "_posts/2023-01-12-cockpit-283.md",
    "content": "---\ntitle: Cockpit 283\nauthor: garrett\ndate: '2023-01-12'\ntags: cockpit, machines\nslug: cockpit-283\ncategory: release\nsummary: 'Minutely timers, system & session VM summary, virtual watchdog for VMs'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 283 and cockpit-machines 281:\n\n\n## Services: Create timer to run every minute\n\nIn the Timers part of Services page, the create timer dialog can create systemd timers to run in \"minutely\" mode, which runs a command every minute on the specified second.\n\n_Huge thanks to [Daniel Haas (dphaas2004)](https://github.com/dphaas2004) for [this feature](https://github.com/cockpit-project/cockpit/pull/17592#issue-1317035572)!_\n\n![screenshot of create timer to run every minute]({{ site.baseurl }}/images/283-services-create-timer-to-run-every-minute.png)\n\n## Machines: Summarize system and user session differences\n\nThere are several differences when running a virtual machine at the system level versus running a VM in a user session. Cockpit Machines now explains the pros and cons of each inside a popup in the Create VM modal dialog.\n\n![screenshot of summarize system and user session differences]({{ site.baseurl }}/images/283-machines-summarize-system-and-user-session-differences.png)\n\n## Machines: Virtual watchdog device support\n\nWatchdog devices are typically hardware devices that work with an operating system to reboot a machine with it stops responding.\n\nCockpit Machines now has support for adding a virtual software-based watchdog device to a machine.\n\nPlease note that the watchdog device _also_ needs to be configured within the guest operating system to be used.\n\n![screenshot of virtual watchdog device support]({{ site.baseurl }}/images/283-machines-virtual-watchdog-device-support.png)\n\n## Try it out\n\nCockpit 283 and cockpit-machines 281 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/283)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-74586bb92c)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2023-8bc12f90dd)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/281)\n* [cockpit-machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-49b3964047)\n* [cockpit-machines Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2023-3b424a9b80)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/60)\n* [cockpit-podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-e680d8b5cb)\n* [cockpit-podman Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2023-c0a825e37f)\n\n*[API]: Application Programming Interface\n*[VM]: Virtual Machine"
  },
  {
    "path": "_posts/2023-01-25-cockpit-284.md",
    "content": "---\ntitle: Cockpit 284\nauthor: pitti\ndate: '2023-01-25'\ntags: cockpit, machines\nslug: cockpit-284\ncategory: release\nsummary: 'User logs, NBDE, forceful snapshot reverting, and improved default container command'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 284, cockpit-machines 282, and cockpit-podman 61:\n\n\n## Services: Show logs for user units\n\nThe Services page now shows journal logs for user systemd services.\n\n![screenshot of show logs for user units]({{ site.baseurl }}/images/284-services-show-logs-for-user-units.png)\n\n*Many thanks to [Timothy Johnson](https://github.com/t1m0thyj) for this contribution!*\n\n## Storage: Set up NBDE\n\nIt is possible (and unfortunately likely) that a system is misconfigured and can not mount filesystems during boot that rely on Clevis to unlock them. Cockpit can now fix this when adding a keyserver to a encrypted filesystem.\n\n![screenshot of set up a system to use nbde]({{ site.baseurl }}/images/284-storage-set-up-a-system-to-use-nbde.png)\n\n## Machines: Option to forcefully revert a snapshot\n\nThere are situations where a snapshot revert involves extra risk and the user should either consider not reverting snapshot, or force it. The few most common cases are:\n- Snapshot that lacks full domain information for reverting configuration. In this case, the user should be sure that snapshot is compatible with the current configuration (if it is not, the domain will likely fail to run).\n- Reverting from a running domain to an active state where a new hypervisor has to be created rather than reusing the existing hypervisor.\n- Snapshot of inactive VM which also has a managed saved state. This requires forceful revert because the snapshot does not contain a memory state and will therefore not replace the existing memory state. This ends up switching a disk underneath a running system and can cause filesystem corruption or crashes due to swap content mismatches when run.\n\n![Screenshot from 2023-01-24 15-37-22]({{ site.baseurl }}/images/284-machines-option-to-forcefully-revert-a-snapshot.png)\n\n## Podman: Use container image's default command\n\nNewly created containers now use the container image's suggested command by default. Just as before, this command can be changed when creating a container in `cockpit-podman`. Previously, the command always defaulted to suggest using `sh`.\n\n\n## Try it out\n\nCockpit 284, cockpit-machines 282, and cockpit-podman 61 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/284)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-7bc8f746cd)\n* [Cockpit Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2023-7950dba0f6)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/282)\n* [cockpit-machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-26387fe37c)\n* [cockpit-machines Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2023-02142ab4aa)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/61)\n* [cockpit-podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-944b01ac33)\n* [cockpit-podman Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2023-45017bdb00)\n\n*[NBDE]: network-bound disk encryption\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2023-02-08-cockpit-285.md",
    "content": "---\ntitle: Cockpit 285\nauthor: garrett\ndate: '2023-02-08'\ntags: cockpit\nslug: cockpit-285\ncategory: release\nsummary: Group filtering and creation, cryptographic subpolicies \n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 285:\n\n\n## Accounts: Group filtering and creation\n\nUsers can now create a new group.\n\n![Screenshot from 2023-02-08 17-59-46]({{ site.baseurl }}/images/285-accounts-group-improvements.png)\n\nFiltering has been added to groups, supporting both Name and GID (group ID).\n\n![screenshot of group improvements]({{ site.baseurl }}/images/285-accounts-group-improvements-2.png)\n\n## Cryptographic subpolicies\n\nA limited set of cryptographic policies with subpolicies are now in the list of cryptographic choices on Red Hat Enterprise Linux, CentOS Stream, Fedora, and related distributions. Subpolicies extend a standard cryptographic policy by either being more permissive or restrictive than the original policy. Examples include allowing SHA1 or using stricter requirements such as OSPP (Operating System Protection Profile, Common Criteria).\n\n![Screenshot from 2023-02-08 09-05-10]({{ site.baseurl }}/images/285-support-a-subset-of-cryptographic-policies-with-subpolicies.png)\n\n\n## Try it out\n\nCockpit 285 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/285)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-b2e6448cf5)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/283)\n* [cockpit-machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-e1c4b6e2ef)\n* [cockpit-machines Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2023-8f3e0c8d5a)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/62)\n* [cockpit-podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-94d443ecb8)\n* [cockpit-podman Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2023-1c6ec9ef3d)\n* [cockpit-ostree Source Tarball](https://github.com/cockpit-project/cockpit-ostree/releases/tag/192)\n* [cockpit-ostree Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-9f0b552efb)\n* [cockpit-ostree Fedora 36](https://bodhi.fedoraproject.org/updates/FEDORA-2023-416be6f1bd)\n\n*[OS]: Operating System\n*[RHEL]: Red Hat Enterprise Linux"
  },
  {
    "path": "_posts/2023-02-22-cockpit-286.md",
    "content": "---\ntitle: Cockpit 286\nauthor: garrett\ndate: '2023-02-22'\ntags: cockpit\nslug: cockpit-286\ncategory: release\nsummary: 'Toggle resource visibility in the metrics page'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 286, Cockpit-machines 284, and\nCockpit-podman 63:\n\n\n## Metrics: Toggle visibility of resource usage graphs\n\nOn the Metrics page, which can be found by following the link from the Overview, you can see a historical graph of CPU, memory, storage IO, and network. This release adds the ability to toggle the visibility of individual types of resources in the graph.\n\n![screenshot of control visibility of the resource usage graphs]({{ site.baseurl }}/images/286-metrics-page-control-visibility-of-the-resource-usage-graphs.png)\n\n\n## Try it out\n\nCockpit 286 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/286)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-e1378454aa)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-4dde14263a)\n\nCockpit-machines 284 is available now:\n\n* [Cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/284)\n* [Cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-233c626524)\n* [Cockpit-machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-d8cc5c9432)\n\nCockpit-podman 63 is available now:\n\n* [Cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/63)\n* [Cockpit-podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-6da2389155)\n* [Cockpit-podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-4a481332d2)\n"
  },
  {
    "path": "_posts/2023-03-09-cockpit-287.md",
    "content": "---\ntitle: Cockpit 287\nauthor: garrett\ndate: '2023-03-09'\ntags: cockpit, podman\nslug: cockpit-287\ncategory: release\nsummary: 'Pinned services update, esbuild developer information'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 287 and cockpit-podman 64:\n\n\n## Services: Pinned units need to be re-done\n\nThe data storage for \"pinned\" systemd units has changed. After upgrading to this Cockpit version, you need to re-pin units.\n\n## Development: Cockpit now supports the esbuild bundler\n\n[esbuild](https://esbuild.github.io/) is a much faster bundler alternative for [webpack](https://webpack.js.org/). It also  natively understands [JSX](https://reactjs.org/docs/introducing-jsx.html), so that it is not necessary any more to use [babel](https://babeljs.io/). Cockpit's shared components and bundler plugins in [pkg/lib/](https://github.com/cockpit-project/cockpit/tree/main/pkg/lib) now support both eslint and webpack, so that projects can pick either. [cockpit-podman](https://github.com/cockpit-project/cockpit-podman) moved to esbuild in [this commit](https://github.com/cockpit-project/cockpit-podman/commit/d48f58297f66d2f6390aa85b54883d9be980850b). You may choose to do the same for your project.\n\n\n## Try it out\n\nCockpit 287 and cockpit-podman 64 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/287)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-6987aaacad)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-2e47853ed4)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/285)\n* [cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-99b4679f77)\n* [cockpit-machines Fedora 37]https://bodhi.fedoraproject.org/updates/FEDORA-2023-9893be2f68()\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/64)\n* [cockpit-podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-82b8596f0f)\n* [cockpit-podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-ff01f5ff9e)\n\n"
  },
  {
    "path": "_posts/2023-03-22-cockpit-288.md",
    "content": "---\ntitle: Cockpit 288\nauthor: kkoukiou\ndate: '2023-03-22'\ntags: cockpit, machines, podman\nslug: cockpit-288\ncategory: release\nsummary: 'Metrics redesign, accounts page improvements, virtual machines cloud base editing, services page speed ups, chronyd manual time servers'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 288, cockpit-machines 286, and cockpit-podman 65:\n\n## Accounts: Show shell and home directory on detail page\n\nAccount detail pages show the home directory and shell for an account.\n\n![details page for an account, showing the newly added shell and home directory entries]({{ site.baseurl }}/images/288-accounts-show-shell-and-home-directory.png)\n\n## Accounts: Custom user ID during account creation\n\nA custom user ID can now be specified during account creation. It defaults to the next available user ID on the system.\n\n![account creation dialog showing an entry for user ID]({{ site.baseurl }}/images/288-accounts-custom-user-id-during-account-creation.png)\n\n## Overview: Support additional timeservers with chronyd\n\nCockpit can now configure additional time servers when chronyd is used to synchronize the clock. Previously, this was only supported with systemd-timesyncd.\n\n![screenshot of support for additional timeservers with chronyd]({{ site.baseurl }}/images/288-overview-support-for-additional-timeservers-with-chronyd.png)\n\n## Metrics: Show longer time span by default\n\nThe PCP metrics graphs have been redesigned to only show a summary of events for each hour, so that more data fits on the page. The hours can be expanded to get more details.\n\n![screenshot of new design with more info in default view]({{ site.baseurl }}/images/288-metrics-new-design-with-more-info-in-default-view.png)\n\n## Storage: Mounting filesystems at boot time\n\nFilesystems created in Cockpit are usually not used for the main operating system, so they are often supplemental. As such, they now default to `nofail`, to allow a server to boot even if the additional filesystem is not mounted.\n\nThe new \"at boot\" option provides several choices with explanations of when the filesystem would be mounted and what would happen if it was not mounted.\n\n![screenshot of the \"nofail\" and \"_netdev\" options are exposed as a dropdown]({{ site.baseurl }}/images/288-storage-the-nofail-and-netdev-options-are-exposed-as-a-dropdown.png)\n\n## Machines: Create VM based on cloud image and start it later\n\nA VM created from a \"cloud base\" image can now use the \"Create and edit\" mode. This is a way to edit all virtual machine properties (bootloader, boot order, disks, networking, etc.) before the VM is installed.\n\n## API removal: Remove cockpit.dbus.publish() and .meta()\n\nThe `cockpit.js` library dropped `cockpit.dbus.publish()` and `cockpit.dbus.meta()`, which were meant to create a D-Bus server object from inside a Cockpit page. No [known Cockpit project](https://cockpit-project.org/applications.html) has ever used these functions, and we are not aware of a good use case.\n\nIf you are using this API, please [let us know](https://github.com/cockpit-project/cockpit/issues)!\n\n## Try it out\n\nCockpit 288, cockpit-machines 286, and cockpit-podman 65 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/288)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-6741936c44)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-7372072c3f)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/286)\n* [cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-dc57efee43)\n* [cockpit-machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-fb892a5b15)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/65)\n* [cockpit-podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-18b5f87527)\n* [cockpit-podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-b6a77df4df)\n\n*[API]: Application Programming Interface\n*[PCP]: Performance Co-Pilot\n*[VM]: Virtual Machine\n*[UID]: User ID\n"
  },
  {
    "path": "_posts/2023-03-29-matrix-channel.md",
    "content": "---\ntitle: \"Moving online discussion to Matrix\"\nauthor: lis\ntags: cockpit\n---\n\nEffective today, the Cockpit Project is moving our primary online discussion forum from IRC to Matrix.\n\nYou can now find us in [`#cockpit:fedoraproject.org`](https://matrix.to/#/#cockpit:fedoraproject.org).  You can follow the link to login using an existing Matrix account, or easily create a new one using a variety of single sign-on parters (including GitHub and GitLab).\n\nThe old IRC channel on libera.chat has been discontinued. It is no longer possible to write messages there.  We’ve elected not to bridge the channel, mostly on account of recent reliability issues.\n\nHonestly, we’re a bit sad to be leaving IRC after so long.  Matrix is a secure (end-to-end encrypted) and decentralized (server federated) platform with open specifications and many Free Software implementations of both clients and servers.  It has a strong IRC-based heritage.  It was a natural choice for our project.\n\nWe look forward to seeing you there!\n"
  },
  {
    "path": "_posts/2023-04-06-cockpit-289.md",
    "content": "---\ntitle: Cockpit 289\nauthor: garrett\ndate: '2023-04-06'\ntags: cockpit, machines, podman\nslug: cockpit-289\ncategory: release\nsummary: 'Accounts password improvements, metrics improves colors, system virtualization check, and Podman gets health check actions and a sortable container list'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 289, cockpit-machines 287, and cockpit-podman 66:\n\n\n## Metrics: Indicate high usage and use colorblind-friendly colors\n\nGraphs on the metrics page indicate high usage by using a darker variant of the color. Additionaly, colors have been adjusted to use a colorblind-optimized subset of PatternFly chart colors.\n\n![228601347-df99586b-3c21-467f-a74d-1c0f020c2afc]({{ site.baseurl }}/images/289-metrics-indicate-extreme-usage-and-use-colorblind-friendly-colors.png)\n\n## Accounts: Improve password validation\n\nWhen creating an account, password validation actively performs a check on every keystroke, once the same numbers of character have been met. Additionally, weak passwords are now shown with a warning to discourage usage, but can still be overridden in most cases.\n\n![Screenshot from 2023-04-05 12-41-47]({{ site.baseurl }}/images/289-accounts-improve-password-validation.png)\n\n## Machines: Show an alert when virtualization is disabled in BIOS/EFI\n\nCockpit-Machines displays a full-page alert when virtualization is disabled in the BIOS/EFI settings, preventing potential issues when running a VM.\n\n![screenshot of show an alert when virtualization is disabled in bios/efi]({{ site.baseurl }}/images/289-machines-show-an-alert-when-virtualization-is-disabled-in-bios-efi.png)\n\n_Thanks to Subho Ghosh for this contribution!_\n\n## Podman: Custom healthcheck actions\n\nWhen health checks fail, Cockpit-Podman can now optionally restart, stop, or force stop a container. This feature requires Podman 4.3 or higher.\n\n![screenshot of custom healthcheck actions]({{ site.baseurl }}/images/289-podman-custom-healthcheck-actions.png)\n\n## Podman: Container list can be sorted\n\nCockpit-Podman's container list now supports sorting by name, owner, CPU, memory, and state.\n\n![screenshot of container list can be sorted]({{ site.baseurl }}/images/289-podman-container-list-can-be-sorted.png)\n\n\n## Try it out\n\nCockpit 289, cockpit-machines 287, and cockpit-podman 66 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/289)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-1a8140e161)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-f27bb11ca0)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/287)\n* [cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-47a24b2d85)\n* [cockpit-machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-2ffbc6367b)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/65)\n* [cockpit-podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-e4f5cd6177)\n* [cockpit-podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-e0ccd4e3c8)\n\n*[CPU]: Central Processing Unit, the \"brain\" of a computer\n*[OS]: Operating System\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2023-04-19-cockpit-290.md",
    "content": "---\ntitle: Cockpit 290\nauthor: pitti\ndate: '2023-04-19'\ntags: cockpit, machines, podman\nslug: cockpit-290\ncategory: release\nsummary: 'webserver hardening, VM shutdown indicator, VM storage file cleanup'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 290, cockpit-machines 288, and cockpit-podman 67:\n\n\n## webserver: Disallow direct URL logins with `LoginTo=false`\n\n[cockpit.conf](https://cockpit-project.org/guide/latest/cockpit.conf.5.html) has a `LoginTo=` option. This allows the admin to disable the login page's \"Connect to:\" functionality for directly logging into a remote host through SSH. Setting it to `false` previously still left the possibility of a remote login through directly specifying an appropriate URL. With this Cockpit version, `LoginTo=false` disallows logins through remote URLs as well.\n\nIf cockpit-ws is exposed to the public internet, and also has access to a private internal network, it is recommended to explicitly set `LoginTo=false`. This prevents unauthenticated remote attackers from scanning the internal network for existing machines and open ports.\n\n## Machines: Indicate need for shutdown\n\nThe VM list and detail pages now display a \"changes pending\" status label to indicate that the VM needs to be shut down for recent configuration changes to take effect. Clicking the label lists the specific changes.\n\n![screenshot of indicate need for shutdown]({{ site.baseurl }}/images/290-machines-indicate-need-for-shutdown.png)\n\n## Machines: Delete storage file when detaching disk\n\nWhen detaching a disk from a VM, the underlying storage file can now be deleted as well.\n\n![Screenshot from 2023-04-18 15-13-08]({{ site.baseurl }}/images/290-machines-delete-storage-file-when-detaching-disk.png)\n\n\n## Try it out\n\nCockpit 290 and cockpit-machines 288 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/290)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-bc7e3718bc)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-363cf1cea2)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/288)\n* [cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-e58c52135a)\n* [cockpit-machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-b2688e6dd9)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/67)\n* [cockpit-podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-d584b2a229)\n* [cockpit-podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-e898a1a22e)\n\n*[SSH]: Secure Shell, a common protocol to securely connect to a remote computer\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2023-05-03-cockpit-291.md",
    "content": "---\ntitle: Cockpit 291\nauthor: mvollmer\ndate: '2023-05-03'\ntags: cockpit, machines, podman\nslug: cockpit-291\ncategory: release\nsummary: 'PatternFly 5, create VMs with raw disks, VM CPU editing refinements'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from cockpit 291, cockpit-machines 289.1, and cockpit-podman 68:\n\n\n## Update to PatternFly 5 alpha\n\nCockpit is now an \"early adopter\" of PatternFly 5. Everything should look the same. We ensured all functional and visual tests pass.\n\nWhile this should not affect anyone using Cockpit, it definitely will affect everyone developing for Cockpit. Read more on [our PatternFly 5 blog post](https://cockpit-project.org/blog/patternfly-v5-alpha.html).\n\n## Machines: VM creation supports raw disk format\n\nDuring virtual machine creation, there is now a raw disk option in the storage format selection.\n\n![Screenshot from 2023-05-03 12-32-48]({{ site.baseurl }}/images/291-option-to-use-raw-volume-during-vm-creation.png)\n\n## Machines: Redesign virtual machine CPU configuration\n\nThe CPU model dialog and vCPU topology have been merged into a single overview entry and dialog. Additionally, a few minor improvements have been added, including vCPU maximum and vCPU count now being number inputs.\n\n![Screenshot from 2023-05-03 12-32-03]({{ site.baseurl }}/images/291-redesign-vm-s-cpu-configuration.png)\n\n![Screenshot from 2023-05-03 12-40-15]({{ site.baseurl }}/images/291-redesign-vm-s-cpu-configuration-2.png)\n\n\n## Try it out\n\nCockpit 291, cockpit-machines 289.1, and cockpit-podman 68 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/291)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-7c385a140e)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-914cfed0e7)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/289.1)\n* [cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-f73576a710)\n* [cockpit-machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-44a39665df)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/68)\n* [cockpit-podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-78662c9117)\n* [cockpit-podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-b1b46b4120)\n\n*[CPU]: Central Processing Unit, the \"brain\" of a computer\n*[VM]: Virtual Machine"
  },
  {
    "path": "_posts/2023-05-03-patternfly-v5-alpha.md",
    "content": "# Cockpit upgraded to PatternFly 5 alpha\n\nPatternFly team has been working with “all hands on deck” on the version 5. That new major release is still scheduled for June. They have conducted two rounds of alpha testing so far and they've gone pretty well. Meanwhile PatternFly 4 has been in development freeze for a while as the team is focusing on the new version.\n\n**Cockpit has decided to go ahead with an early adoption of PatternFly 5.** The motivation for adopting PatternFly 5 can be summarized in several key points. Firstly, the early adoption of PatternFly 5 is advantageous for the PatternFly team. Secondly, as PatternFly 5 is still in its alpha phase, it is more receptive to significant changes. Thirdly, the high code coverage of Cockpit, with its integration and image comparison testing, provides confidence in being one of the early adopters without compromising product quality. Finally, PatternFly 4 is in development freeze, which hinders the ability to utilize the latest features and fixes found in PatternFly 5.\n\nIt’s important to note that PatternFly 5 is not introducing drastic UI changes that the user would be able to notice, like the PatternFly 3 to PatternFly 4 upgrade did. It’s quite accurate to perceive this major release as an evolution of PatternFly 4, with enhancements and bug fixes.\n\nSome of the Cockpit team’s most awaited changes that have user impact from PatternFly 5 include improved dark theme support and using gap instead of margins for spacing, something that brings us one step closer to better RTL (Right to left) language support.\n\n\n## Upgrade strategy for Cockpit projects\n\nPatternFly 5 is already being used in [the main cockpit repository](https://github.com/cockpit-project/cockpit/). Cockpit projects  which live in separate repositories can still co-exist with Cockpit packages which have already been ported to PatternFly 5. However there is a limitation with the usage of the [shared Cockpit components library](https://github.com/cockpit-project/cockpit/tree/main/pkg/lib/). Since the library has already been updated to PatternFly 5, consumer plugins cannot use the latest shared library without upgrading their codebase to PatternFly 5 as well.\n\nIf you want to join Cockpit as an early adopter of PatternFly 5, use the following steps to upgrade.\n\n\n# Upgrading to PatternFly 5\n\n\n## Installing PatternFly 5\n\nRun the following commands to install PatternFly 5 alpha:\n\n``` sh\nnpm install --save \\\n    @patternfly/patternfly@alpha \\\n    @patternfly/react-core@alpha \\\n    @patternfly/react-icons@alpha \\\n    @patternfly/react-table@alpha \\\n    @patternfly/react-styles@alpha\n```\n\nThe PatternFly team has developed a script to help with the upgrade process from `@patternfly/react-core@4.x.x` to `5.x.x`.  Run the following command to install the [pf-codemods](https://github.com/patternfly/pf-codemods/) script:\n\n``` sh\nnpm install @patternfly/pf-codemods\n```\n\nFollow the [usage guidelines](https://github.com/patternfly/pf-codemods/#usage) and run the script for automatically doing part of the changes needed for the upgrade to PatternFly 5. However, running this script will not cover all required changes e  and will leave your codebase in an incomplete upgrade state.\n\nRead the error messages that the script will generate one by one and make sure everything is addressed either by auto-fixes from the script or by manual intervention.\n\nIf you want to make multiple commits with isolated logical changes rather than one all-included commits you can use the [`–only` argument](https://github.com/patternfly/pf-codemods/#options) to run a specific rule at a time.\n\n\n## Cockpit overrides for PatternFly 5\n\nCockpit has been maintaining a file for [CSS overrides for PatternFly 4](https://github.com/cockpit-project/cockpit/blob/289/pkg/lib/patternfly/patternfly-4-overrides.scss) containing fixes not yet included upstream in PatternFly and also some special customizations for Cockpit. This file has been renamed to [patternfly-5-overrides.scss](https://github.com/cockpit-project/cockpit/blob/main/pkg/lib/patternfly/patternfly-5-overrides.scss) and should be imported by all Cockpit plugins similarly to the PatternFly 4 overrides. The suggested way to import this file is indirectly by importing [page.scss](https://github.com/cockpit-project/cockpit/tree/main/pkg/lib/page.scss). See an [example](https://github.com/cockpit-project/cockpit-machines/blob/main/src/machines.scss#L1) of importing this file in Cockpit Machines repository.\n\n\n## Examples of external Cockpit plugins upgraded\n\nPR for cockpit-machines: [https://github.com/cockpit-project/cockpit-machines/pull/1052](https://github.com/cockpit-project/cockpit-machines/pull/1052)\n\nPR for cockpit-podman: [https://github.com/cockpit-project/cockpit-podman/pull/1266](https://github.com/cockpit-project/cockpit-podman/pull/1266)\n"
  },
  {
    "path": "_posts/2023-05-16-cockpit-292.md",
    "content": "---\ntitle: Cockpit 292\nauthor: pitti\ndate: '2023-05-16'\ntags: cockpit, machines\nslug: cockpit-292\ncategory: release\nsummary: 'Per-service disk IO, right-to-left language fixes, robust VM watchdog changes'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 292 and cockpit-machines 290:\n\n\n## Metrics: Add disk I/O per service\n\nThe \"Disks\" usage metrics card now shows the active read and write bandwidth for the top 5 consumers by systemd unit. This is similar to the already existing per-service CPU and RAM usage.\n\n![metrics-disks-io-cgroups]({{ site.baseurl }}/images/292-metrics-add-disk-io-per-service.png)\n\n## Machines: Add watchdogs which require reboot\n\nIn some cases, adding a watchdog to a running VM fails. When that happens, the changes can only be applied through rebooting the VM. The \"Add watchdog\" dialog now supports this case.\n\n![234253257-d6bc8d91-7b66-4ef7-b9df-79d554f92b0b]({{ site.baseurl }}/images/292-machines-apply-watchdog-changes-on-next-boot-if-hotplug-fails.png)\n## Several right-to-left language fixes\n\nIn [Cockpit 282](https://cockpit-project.org/blog/cockpit-282.html), the first round of RTL support arrived. This release of Cockpit further dramatically improves RTL support.\n\n_A big thanks to [Ahmed Abdelatty](https://github.com/ahmedr2001/) for kickstarting this most recent round of improvements!_\n\n\n## Try it out\n\nCockpit 292, cockpit-machines 290, cockpit-podman 69, and cockpit-ostree 193 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/292)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-636e748ae9)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-603a5a4abc)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/290)\n* [cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-eb3f0741df)\n* [cockpit-machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-c5ffcaae0d)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/69)\n* [cockpit-podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-a1c1894f12)\n* [cockpit-podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-b1b46b4120)\n* [cockpit-ostree Source Tarball](https://github.com/cockpit-project/cockpit-ostree/releases/tag/193)\n* [cockpit-ostree Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-9c114ab681)\n* [cockpit-ostree Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-f401c4af8b)\n\n*[CPU]: Central Processing Unit, the \"brain\" of a computer\n*[RAM]: Random Access Memory\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2023-06-01-cockpit-293.md",
    "content": "---\ntitle: Cockpit 293\nauthor: jelle\ndate: '2023-06-01'\ntags: machines, podman\nslug: cockpit-293\ncategory: release\nsummary: 'VM vsock devices and pruning of unused podman containers'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from cockpit-machines 291 and cockpit-podman 70:\n\n\n##  Vsock device support\n\nVirtual socket support enables communication between the host and guest over a socket. Cockpit Machines now has support for setting up such a device.\n\n![vsock-edit]({{ site.baseurl }}/images/293-vsock-device-support.png)\n\nThe user can choose to configure a custom identifier, or let have it assigned automatically upon a VM's boot. The identifier is used by the host to uniquely identify vsock of a specific guest.\n\n![vsock-edit-dialog]({{ site.baseurl }}/images/293-vsock-device-support-2.png)\n\nPlease note that vsock still requires special vsock-aware software (e.g. socat) to communicate over the socket.\n\n## Podman: Support for pruning unused containers\n\nSimilar to `podman container prune`, cockpit-podman now has a \"prune\" dialog for bulk deletion of stopped and exited containers. This dialog provides the option to unselect containers while displaying container names, creation dates, and owner information to help ensure the intended containers are selected for deletion.\n\n![screenshot of support for pruning unused containers]({{ site.baseurl }}/images/293-podman-support-for-pruning-unused-containers.png)\n\n\n## Try it out\n\ncockpit-machines 291 and cockpit-podman 70 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/291)\n* [cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-660dc65689)\n* [cockpit-machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-81fda75565)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/70)\n* [cockpit-podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-d3ed5e2d5b)\n* [cockpit-podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-7acba90d38)\n"
  },
  {
    "path": "_posts/2023-06-14-cockpit-294.md",
    "content": "---\ntitle: Cockpit 294\nauthor: jelle\ndate: '2023-06-14'\ntags: cockpit\nslug: cockpit-294\ncategory: release\nsummary: 'Python bridge'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 294:\n\n\n## Introducing the Python bridge\n\nThe primary process in a Cockpit Linux session is called `cockpit-bridge`. It translates operating system interfaces to a JSON stream protocol, which is used by Cockpit browser pages. \n\nRecently, `cockpit-bridge` has been rewritten in Python. The rewrite is now complete enough to start rolling it out.\n\n- In Release 294, the Python bridge will be used on Debian unstable/testing and Fedora Rawhide (release ≥ 39).\n- As the Python bridge undergoes further stabilization, it will gradually become available on additional distributions.\n- The old C bridge will be retained for RHEL/CentOS 8 and Ubuntu 22.04 LTS, to avoid any potential risks.\n\nDespite careful testing, the new bridge may cause some regressions or instability. Please [let us know](https://github.com/cockpit-project/cockpit/issues/new?template=bug_report.yml) if you run into any trouble!\n\nIn addition to improving maintainability, the Python bridge will enable some exciting new features. For example: Using Cockpit with machines that do not have Cockpit packages installed.\n\nThis functionality is already available in Cockpit Client as a preview release on `flathub-beta`:\n\n```\nflatpak install flathub-beta org.cockpit_project.CockpitClient\nflatpak run --branch=beta org.cockpit_project.CockpitClient\n```\n\nSee the [instructions for using `flathub-beta`](https://discourse.flathub.org/t/how-to-use-flathub-beta/2111) for more information.\n\n\n## Try it out\n\nCockpit 294 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/294)\n* [cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-c00baddb1c)\n* [cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-b500a949c8)\n* [cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-d28920270e)\n\n\n*[OS]: Operating System\n*[repo]: repository\n*[RHEL]: Red Hat Enterprise Linux\n"
  },
  {
    "path": "_posts/2023-06-28-cockpit-295.md",
    "content": "---\ntitle: Cockpit 295\nauthor: lis\ndate: '2023-06-28'\ntags: machines\nslug: cockpit-295\ncategory: release\nsummary: 'Cockpit Client on any server, UI changes for VMs'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from cockpit 295 and cockpit-machines 293:\n\n## Cockpit Client can now connect to servers without Cockpit installed\n\nAlong with the last release of Cockpit, we introduced a version of Cockpit Client to `flathub-beta` which was capable of connecting to servers, even if they don't have Cockpit installed.  This is enabled by the new Python bridge and requires at least Python 3.6 to be installed on the server being connected to.  You also need to be able to connect to the server via SSH.\n\nThis new feature has now graduated to the [official Flathub release](https://flathub.org/apps/org.cockpit_project.CockpitClient).\n\nThe ability to connect to systems without Cockpit installed also makes another feature of Cockpit Client more interesting: if you type \"localhost\" in the \"Connect to:\" box then you can now use Cockpit as a UI for your local computer.\n\nCockpit Client is still mostly a proof of concept, but we hope to start improving it.  Expect to see progress in coming releases.\n\n## Machines: Show virtual interface's TAP device\n\nNetwork interfaces attached to VMs have a corresponding TAP device on the host, which represents the VM's low-level connection to the host's network environment.  This device is now shown in the \"Network interfaces\" list for the virtual machine.\n\n![Screenshot from 2023-06-26 12-43-15]({{ site.baseurl }}/images/295-show-virtual-interface-s-tap-device.png)\n\n## Machines: Confirm shutdown actions\n\nAsk for confirmation for every action which can cause downtime.  The dialog also shows the current uptime of the VM to help the user ensure that they have selected the intended VM.\n\n![248766553-adebffd9-af32-4f24-9121-45ba8bc06540]({{ site.baseurl }}/images/295-machines-confirm-shutdown-actions.png)\n\n\n## Try it out\n\nCockpit 295 and cockpit-machines 293 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [cockpit Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/295)\n* [cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-86e1c89fff)\n* [cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-71a683d759)\n\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/293)\n* [cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-321097a133)\n* [cockpit-machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-c522f0ce3b)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2023-07-26-cockpit-297.md",
    "content": "---\ntitle: Cockpit 297\nauthor: skobyda\ndate: '2023-07-26'\ntags: cockpit, podman\nslug: cockpit-297\ncategory: release\nsummary: \"Support for changing user shell, Python bridge in Fedora 38 and CentOS Stream/RHEL 9, Show container's latest checkpoint\"\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 297 and cockpit-podman 73:\n\n\n## Users: Support for changing user shells\n\nAdministrators can now change user default shells on the Accounts page.\n\n![screenshot of ## allow administrators to change the user shell]({{ site.baseurl }}/images/297-allow-administrators-to-change-the-user-shell.png)\n\n![screenshot of ## allow administrators to change the user shell]({{ site.baseurl }}/images/297-allow-administrators-to-change-the-user-shell-2.png)\n\n## Use the Python bridge in Fedora 38 and CentOS Stream 9\n\nThe rewritten Python bridge, introduced in [Cockpit 294](https://cockpit-project.org/blog/cockpit-294.html), is now used on Fedora 38 and CentOS Stream 9. Please [let us know](https://github.com/cockpit-project/cockpit/issues/new?template=bug_report.yml) if you run into any trouble!\n\n\n## Podman: Show the time of the latest container checkpoint\n\n![screenshot of ## show time of containers latest checkpoint]({{ site.baseurl }}/images/297-podman-show-time-of-containers-latest-checkpoint.png)\n\n## Try it out\n\nCockpit 297 and cockpit-podman 73 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/297)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-34f212e4ae)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-75a630fff3)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/73)\n* [cockpit-podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-3288094edb)\n* [cockpit-podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-b922ea5b16)\n\n*[OS]: Operating System\n*[repo]: repository\n"
  },
  {
    "path": "_posts/2023-08-01-tmt-cross-project-testing.md",
    "content": "---\ntitle: Cross-project testing with tmt and Packit\nauthor: pitti\ndate: 2023-08-01\ncategory: howto\ntags: qa testing reverse-dependency gating distribution tmt packit\n---\n\n## Motivation\n\nAll Cockpit projects have been running [gating tests with Packit and tmt](./fmf-unified-testing.html) in upstream PRs and Fedora/CentOS/RHEL for over two years now. That resolved most of our previous woes about broken gating tests after upstream releases.\n\nHowever, even after several years of tmt tests, Fedora still does not use these tests for gating properly, in the sense that any package update can easily break *other* packages, i.e. packages which depend on the one being updated. That sets up a very bad motivation: By improving their gating tests, a package maintainer can only make their *own* life harder, but their dependencies can still break them all the time. A better approach is when each proposed package update runs the tests of all their dependencies, and is held back if there is any regression. That is generally called **\"reverse dependency testing\"**, and is what e.g. Debian or Ubuntu have practiced for many years.\n\nAs Cockpit is sitting pretty much at the top of the dependency tree, we feel that pain a lot: we find [hundreds of regressions](https://github.com/cockpit-project/bots/issues?q=is%3Aissue+label%3Aknownissue) through our tests. We also [track them in bugzilla](https://bugzilla.redhat.com/buglist.cgi?bug_status=__open__&bug_status=__closed__&f1=status_whiteboard&list_id=12879603&o1=substring&query_format=advanced&v1=CockpitTest) now. Each time that happens, it often takes hours to find the responsible package update, create a standalone reproducer, report a bug, and then either finding a workaround or creating a [\"naughty pattern\"](https://github.com/cockpit-project/bots/tree/main/naughty) to ignore the problem -- but of course that only takes care of unbreaking our test runs, users are still affected by the regression.\n\nUnfortunately it is technically hard to actually do reverse dependency testing in general in Fedora [†](#footnotes). But also, it is too late at the distro level anyway: At that point the new upstream release which includes the regresssion was already done, and the culprit landed possibly weeks ago already, so that it disappeared from every developer's minds already.\n\nIt's [far more efficient](https://en.wikipedia.org/wiki/Shift-left_testing) to flag regressions in a project's consumers right in the pull request that introduces them, *before* it lands: That is the cheapest and most effective time to know what change caused this, the context is in the developer's head, and it avoids the weeks-long cycle of finding the regression, bugzilla, and finding some time to actually fix it. 10 of our known issues have been open since [2021 or earlier](https://github.com/cockpit-project/bots/issues?q=is%3Aissue+is%3Aopen+label%3Aknownissue+created%3A%3C2022-01-01)! [‡](#footnotes)\n\n## Packit and tmt to the rescue\n\nIt turns out that modern [Packit](https://packit.dev/) and [tmt](https://tmt.readthedocs.io/) know enough tricks to actually do this. The high-level strategy is:\n\n 1. Configure Packit to build every commit of your main branch, i.e. every merged PR, into a dedicated [COPR](https://copr.fedorainfracloud.org/) repository. That is not just useful for CI, but also for human users: They can easily test the latest fixes or features before you officially release them.\n\n 2. Identify some strategic dependencies of your project which potentially or actually break your tests often.\n\n 3. For each of these, add a tmt test plan for your project, and configure a separate Packit test job to run it for each PR. These run as a separate status, so it makes it very clear if/when a proposed change in the dependency breaks your project.\n\n## RPM repository for each commit\n\nThe prerequisite to run tests from your main branch is that they run against the corresponding code, and not against some random older version from some Linux distribution. For a project's own tests, packit builds rpms from a PR automatically, but you need to set this up yourself to test an external project.\n\nThe canonical way to set this up is with a COPR. Go to <https://copr.fedorainfracloud.org> and create a \"New Project\" in your organization or user. Fill in the \"1. Project information\" section and mark your desired distro releases in \"2. Build options\". At the bottom, also fill in the \"Packit allowed forge projects\", i.e. allow the Packit service to interact with your project's pull requests. Example:\n\n![packit allowed forge projects](/images/packit-allowed-forge-projects.png)\n\nTake a look at [Cockpit's \"main-builds\" COPR](https://copr.fedorainfracloud.org/coprs/g/cockpit/main-builds/) for an example.\n\nThen configure `packit.yaml` in your project to do a [build for each commit](https://packit.dev/docs/configuration/upstream/copr_build#supported-triggers) that lands on your \"main\" branch; that may have a different name for your project of course. For example, [cockpit-podman did this](https://github.com/cockpit-project/cockpit-podman/pull/1365):\n\n```yaml\n- job: copr_build\n  trigger: commit\n  branch: \"^main$\"\n  owner: \"@cockpit\"\n  project: \"main-builds\"\n  preserve_project: True\n```\n\nAfter landing that, check your COPR's \"Builds\" page that you actually get a successful package build. The first run will fail, you will get a notification email and have to approve the \"packit\" COPR user to trigger builds in your COPR. Alternatively, you can [set up the permission in advance](https://packit.dev/docs/configuration/upstream/copr_build#using-a-custom-copr-project).\n\n## Enable your test in a dependency project\n\nThis is the step which requires buy-in from the project to which you want to add your tests. That conversation needs to include some agreement how test failures are handled, who will look at them and in which time frame, and similar commitments. Possibly also a link to this blog post to provide the background and motivation 😀.\n\nAdd a new `plans/yourproject.fmf` test plan to the dependency which selects the\ntests you want to run from your project. Unfortunately you cannot yet [auto-import all plans](https://github.com/teemtee/tmt/issues/1770), but first of all the plan structure doesn't tend to change often, and second this may actually be useful to select a subset of tests that apply to the tested dependency.\n\nSo this is mostly a copy of your project's main test plan, with one modification: they should not run by default, but only in a \"revdeps\" tmt context. For triggering cockpit-podman's tests, this can look like this:\n```yaml\n# reverse dependency test\nenabled: false\n\nadjust+:\n  when: revdeps == yes\n  enabled: true\n\ndiscover:\n    how: fmf\n    url: https://github.com/cockpit-project/cockpit-podman\n    ref: \"main\"\nexecute:\n    how: tmt\n\n/podman-system:\n    summary: Run cockpit-podman system tests\n    discover+:\n        test: /test/browser/system\n\n# ... possibly more test plans here\n```\n\nConversely, you should mark the main test plan for the dependency project to *not* run in the \"revdeps\" scenario, to keep them apart in the PR statuses and log views:\n\n```yaml\nadjust+:\n  when: revdeps == yes\n  enabled: false\n```\n\nFinally, plug it all together: Tell `packit.yaml` to run the \"revdeps\" context test plan on current Fedora against your \"builds from main\" COPR, by specifying [tf_extra_params](https://packit.dev/docs/configuration/upstream/tests#optional-parameters). You can of course choose more/different `target`s, as long as your COPR has matching builds for them. Also give it a meaningful `identifier`, so that you can tell the statuses apart. Also enable [automatic failure notifications](https://packit.dev/docs/configuration/#notifications) to ping some people from your team when the tests fail, so that you can work with the PR author to resolve the regression:\n\n```yaml\n  # On current Fedora, run reverse dependency tests against https://copr.fedorainfracloud.org/coprs/g/cockpit/main-builds/\n  - job: tests\n    identifier: revdeps\n    trigger: pull_request\n    notifications:\n      failure_comment:\n        message: \"revdeps tests failed for commit {commit_sha}. @userone, @otheruser, please check\"\n    targets:\n      - fedora-latest-stable\n    tf_extra_params:\n      environments:\n        - artifacts:\n          - type: repository-file\n            id: https://copr.fedorainfracloud.org/coprs/g/cockpit/main-builds/repo/fedora-$releasever/group_cockpit-main-builds-fedora-$releasever.repo\n          tmt:\n            context:\n              revdeps: \"yes\"\n```\n\nThis will result in a new packit test status where you can see the result and logs:\n\n![packit revdeps test status](/images/packit-revdeps-test-status.png)\n\nFor an example, see this [cockpit PR](https://github.com/cockpit-project/cockpit/pull/19155) which enables this. This approach was developed and tested extensively [in an experimental PR](https://github.com/cockpit-project/cockpit/pull/19117).\n\n## Conclusion\n\nThis demonstrates that it is possible today to do upstream cross-project testing for reverse dependency gating, without any extra privileges, secrets, or self-managed infrastructure. I truly believe that this approach on a bigger scale will lead to fewer regressions, less frustration, and avoid long and annoying bugzilla/fix/release turnaround cycles. It can increase velocity across the FOSS landscape in the same way as pervasive reverse dependency testing increased stability and velocity in Debian and Ubuntu.\n\nMany thanks to [Karel Srot](https://github.com/kkaarreell) who knows a lot about tmt, [Laura Barcziová](https://github.com/lbarcziova) and [Frantisek Lachman](https://github.com/lachmanfrantisek) from Packit, and [Miroslav Vadkerti](https://github.com/thrix) from Testing Farm for their great help with figuring out all the details here!\n\n## Footnotes\n\n† This is due to the way tmt tests are defined: Their entry point is not in the srpm, but in their dist-git repository, but there is no efficient and robust way to get the dist-git commit that matches the package version that is currently visible to `dnf install`. Of course there can be heuristics like iterating over the commits until you find the right one; but (1) this is ugly, and (2) more importantly, this is first and foremost a political decision, and there currently does not seem to be much desire to actually do this in Fedora and CentOS stream.\n\n‡ Our known issues auto-close once they get fixed, so all open ones are guarenteed to still happen in recent operating systems.\n\n## Current users\n - [podman](https://github.com/containers/podman/blob/main/.packit.yaml) PRs run [cockpit-podman](https://github.com/cockpit-project/cockpit-podman/)'s tests; and already [found a regression](https://github.com/containers/podman/pull/19888#issuecomment-1711548343) which was corrected immediately without landing on main or in a release.\n - [udisks](https://github.com/storaged-project/udisks/blob/master/.packit.yaml) PRs run [cockpit](https://github.com/cockpit-project/cockpit)'s storage tests.\n\n## Revisions\n\n - 2023-08-01: Original post\n - 2023-09-20: Add failure notifications and current users\n\n*[PR]: Pull request\n*[PRs]: Pull requests\n"
  },
  {
    "path": "_posts/2023-08-09-cockpit-298.md",
    "content": "---\ntitle: Cockpit 298\nauthor: jelle\ndate: '2023-08-09'\ntags: cockpit\nslug: cockpit-298\ncategory: release\nsummary: 'PatternFly 5 support, Stratis pool NBDE Support'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 298:\n\n## PatternFly 5\n\nCockpit, Cockpit-Podman, Cockpit-Machines and Cockpit-OSTree now all use [PatternFly 5](https://www.patternfly.org/get-started/release-highlights/).\n\n## Storage: Stratis pools can be bound to Tang servers\n\nStratis pools can now use Tang server for encryption, either in addition to or instead of a passphrase.\n\n![screenshot of stratis pools can now be bound to a tang server]({{ site.baseurl }}/images/298-storage-stratis-pools-can-now-be-bound-to-a-tang-server.png)\n\n\n## Try it out\n\nCockpit 298 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/298)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-c054c64fce)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-f3b3f454df)\n* [Cockpit-Podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-8c8c9d4038)\n* [Cockpit-Podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-3de0727278)\n* [Cockpit-Machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-24ce36a56f)\n* [Cockpit-Machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-722f7c12eb)\n* [Cockpit-OSTree Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-e4328bfe60)\n* [Cockpit-OSTree Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-db1466c00d)\n"
  },
  {
    "path": "_posts/2023-08-23-cockpit-299.md",
    "content": "---\ntitle: Cockpit 299\nauthor: tmatus\ndate: '2023-08-23'\ntags: cockpit\nslug: cockpit-299\ncategory: release\nsummary: 'Stratis support for no-overprovisioning and adding encrypted caches, Show location of kdump'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 299:\n\n\n## Kdump: Show location of kdump to verify the successful configuration test\n\nYou can now see the location where kdump can be found if testing of kdump settings is successful.\n\n![Screenshot from 2023-08-23 11-17-45]({{ site.baseurl }}/images/299-kdump-show-location-of-kdump-to-verify-the-successful-configuration-test.png)\n\n## Storage: Support for no-overprovisioning with Stratis\n\nA Stratis pool can be put into a \"no-overprovisioning\" mode where the bad effects of running out\nof space can be avoided via careful management of filesystem sizes. Cockpit now supports this mode.\n\n## Storage: Cockpit can now add caches to encrypted Stratis pools\n\nEncrypted caches are a new feature in Stratis 3.5, and now you can use it also from Cockpit.\nRead more about Stratis cache in [Stratis release notes](https://stratis-storage.github.io/stratis-release-notes-3-5-0/).\n\n![Screenshot from 2023-08-25 13-50-29]({{ site.baseurl }}/images/299-storage-cockpit-can-now-add-caches-to-encrypted-stratis-pools.png)\n\n\n## Try it out\n\nCockpit 299 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/299)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-bbb476ce91)\n* [Cockpit Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-1ab32d4881)\n* [Cockpit-Podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-ede2e8fbe7)\n* [Cockpit-Podman Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-2491631273)\n* [Cockpit-Machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-aba610b480)\n* [Cockpit-Machines Fedora 37](https://bodhi.fedoraproject.org/updates/FEDORA-2023-e9d20ee70e)\n"
  },
  {
    "path": "_posts/2023-09-06-cockpit-300.md",
    "content": "---\ntitle: Cockpit 300\nauthor: pitti\ndate: '2023-09-06'\ntags: cockpit\nslug: cockpit-300\ncategory: release\nsummary: 'growing Stratis pools'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nToday we celebrate the 300th release of Cockpit 🎉. This is brought to you live\nfrom a developer team gathering in the beautiful city of Nürnberg, Germany -- home of\nworld-famous visual artists like [Albrecht Dürer](https://en.wikipedia.org/wiki/Albrecht_D%C3%BCrer)\nand [Garrett LeSage](https://github.com/garrett/)!\n\n![group photo]({{ site.baseurl }}/images/300-group-photo.jpg)\n\nToday's versions primarily fix bugs, as they are the final stabilization for\nthe upcoming Red Hat Enterprise Linux releases. But we also have one nice new\nfeature for you.\n\n## Storage: Support for growing block devices of a Stratis pool\n\nCockpit can now grow logical volumes that are used as block devices in a Stratis pool. Also, if a Stratis block device grows for any reason, Cockpit will notify you about this and can extend the pool to use all of it.\n\n![screenshot of support for growing block devices of a stratis pool]({{ site.baseurl }}/images/300-storage-support-for-growing-block-devices-of-a-stratis-pool.png)\n\n## Try it out\n\nCockpit 300 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/300)\n* [Cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-62a3bf42b2)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-81d0e23e81)\n\n* [Cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/XXX)\n* [Cockpit-podman Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-f2ff4ad409)\n* [Cockpit-podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-8f9763a585)\n\n* [Cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/XXX)\n* [Cockpit-machines Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-11609113ba)\n* [Cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-8ed6b60cbb)\n\n* [Cockpit-ostree Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/XXX)\n* [Cockpit-ostree Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-c805979081)\n* [Cockpit-ostree Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-54423898bf)\n"
  },
  {
    "path": "_posts/2023-09-20-cockpit-301.md",
    "content": "---\ntitle: Cockpit 301\nauthor: jelle\ndate: '2023-09-20'\ntags: cockpit\nslug: cockpit-301\ncategory: release\nsummary: 'Link to network interface details from metrics and Wireguard support'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 301:\n\n\n## Metrics: Link to network interface details\n\nThe interface names in the current network I/O card are now clickable links which lead to the detail view of the \"Networking\" page.\n\n![screenshot of link to network interface details]({{ site.baseurl }}/images/301-metrics-link-to-network-interface-details.png)\n\n_Thanks to [leomoty](https://github.com/leomoty/) for this improvement!_\n\n## Networking: Add support for WireGuard\n\nThe Networking page can now create and edit [WireGuard VPN](https://www.wireguard.com/) connections.\n\n![screenshot of add support for wireguard]({{ site.baseurl }}/images/301-networking-add-support-for-wireguard.png)\n\n![screenshot of add support for wireguard]({{ site.baseurl }}/images/301-networking-add-support-for-wireguard-2.png)\n\n_Many thanks to [Subho Ghosh](https://github.com/subhoghoshX) for adding this feature as part of his [Google Summer of Code](https://summerofcode.withgoogle.com/) project! And thanks to [Gil Obradors](https://github.com/gil-obradors) for his initial work._\n\n\n## Try it out\n\nCockpit 301 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/301)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-15c074a031)\n* [Cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-22db412e5e)\n\n* [Cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/77)\n* [Cockpit-podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-751f8bb5d0)\n* [Cockpit-podman Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-5fb734ce86)\n\n* [Cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/299)\n* [Cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-8dcb519f98)\n* [Cockpit-machines Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-ce9f0307ad)\n"
  },
  {
    "path": "_posts/2023-10-05-cockpit-302.md",
    "content": "---\ntitle: Cockpit 302\nauthor: lis\ndate: '2023-10-05'\ntags: cockpit\nslug: cockpit-302\ncategory: release\nsummary: 'Partition resizing'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 302 and cockpit-podman 78:\n\n## Storage: Partitions can be resized\n\nCockpit can now also resize partitions, including their content such as filesystems or LUKS containers.\n\n![Storage page with shrink and grow buttons](/images/302-partition-resize.png)\n\n## Podman: Label Toolbox and Distrobox containers\n\nPodman now shows a visual label in the list of containers to differentiate [Toolbox](https://containertoolbx.org/) and [Distrobox](https://github.com/89luca89/distrobox) containers from other containers.\n\n![Podman container list with labels](/images/302-podman-labels.png)\n\n## Try it out\n\nCockpit 302 and cockpit-podman 78 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/302)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-9dfde954f6)\n* [Cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-f1125a84fd)\n\n* [Cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/78)\n* [Cockpit-podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-6ad9efb0ca)\n* [Cockpit-podman Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-110f7d94f3)\n"
  },
  {
    "path": "_posts/2023-10-18-cockpit-303.md",
    "content": "---\ntitle: Cockpit 303\nauthor: pitti\ndate: '2023-10-18'\ntags: cockpit, machines\nslug: cockpit-303\ncategory: release\nsummary: 'Detect missing AppStream metadata, VM creation with SSH keys'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 303 and cockpit-machines 300:\n\n\n## Apps: Detect missing AppStream metadata\n\nIf the [AppStream](https://www.freedesktop.org/software/appstream/docs/index.html) metadata is not installed, the \"Apps\" page cannot show available Cockpit extensions. The page detects this now, and offers to install the metadata.\n\n![screenshot of detect missing appstream metadata]({{ site.baseurl }}/images/303-apps-detect-missing-appstream-metadata.png)\n\n![screenshot of detect missing appstream metadata]({{ site.baseurl }}/images/303-apps-detect-missing-appstream-metadata-2.png)\n\n_Thanks to [leomoty](https://github.com/leomoty/) for designing this improvement!_\n\n## Machines: Add SSH keys to VM creation dialog\n\nWhen creating a new VM, cockpit-machines now offers the option to provide your SSH public key. This is stored in the `~/.ssh/authorized_keys` file of the designated non-root user, enabling immediate SSH access to the user account right after creating the VM.\n\n![screenshot of add ssh keys to vm creation dialog]({{ site.baseurl }}/images/303-machines-add-ssh-keys-to-vm-creation-dialog.png)\n\n\n## Try it out\n\nCockpit 303 and cockpit-machines 300 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/303)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-aeb3179cf6)\n* [Cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-34fce52f0f)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/300)\n* [cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-8000527351)\n* [cockpit-machines Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-5d093f85ea)\n\n*[SSH]: Secure Shell, a common protocol to securely connect to a remote computer\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2023-11-01-cockpit-304.md",
    "content": "---\ntitle: Cockpit 304\nauthor: jelle\ndate: '2023-11-01'\ntags: cockpit\nslug: cockpit-304\ncategory: release\nsummary: 'LVM2 RAID support'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 304:\n\n\n## Storage: Support for RAID layouts with LVM2\n\nOn recent operating systems such as Fedora 39, Cockpit can now create LVM2 logical volumes with RAID layouts, display how they are stored on their physical volumes, and help you repair them.\n\n![screenshot of support for raid layouts with lvm2]({{ site.baseurl }}/images/304-storage-support-for-raid-layouts-with-lvm2.png)\n\n![screenshot of support for raid layouts with lvm2]({{ site.baseurl }}/images/304-storage-support-for-raid-layouts-with-lvm2-2.png)\n\n\n## Try it out\n\nCockpit 304 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/304)\n* [Cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-19c39abcfc)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-85e4d0038f)\n\n*[LVM]: Logical Volume Manager\n*[RAID]: Redundant Array of Inexpensive Disks\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2023-11-29-cockpit-306.md",
    "content": "---\ntitle: Cockpit 306\nauthor: pitti\ndate: '2023-11-29'\ntags: cockpit, machines, podman, ostree\nslug: cockpit-306\ncategory: release\nsummary: 'kdump automation, OSTree redesign, deleting intermediate podman images'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 306, cockpit-machines 303, cockpit-podman 82, and cockpit-ostree 198.1:\n\n\n## Kdump: Add Ansible/shell automation\n\nThe Kdump page can generate an [Ansible](https://www.ansible.com/automation) role or a shell script for replicating the current kdump configuration on other machines.\n\n![screenshot of the kdump page with an Ansible button]({{ site.baseurl }}/images/306-kdump-add-ansible-shell-automation.png)\n\n![screenshot of shell automation dialog with the \"Ansible\" tab selected and the \"shell script\" tab unselected]({{ site.baseurl }}/images/306-kdump-add-ansible-shell-automation-2.png)\n\n## OSTree: Redesign, with new features\n\nThe OSTree page for software updates has been redesigned and includes several new features.\n\nUpdate status is now listed in the \"Status\" card, and details about the current OSTree repository and branch are visible in the \"OSTree source\" card.\n\n![new design of the OSTree page, showing off the status card]({{ site.baseurl }}/images/306-ostree-redesign-with-new-features-status-clean-up-reset-and-pin.png)\n\nUnused deployments and package cache can be removed in using the \"clean up\" action.\n\n![screenshot of the clean up modal dialog, with cache selected and deployments unselected by default]({{ site.baseurl }}/images/306-ostree-redesign-with-new-features-status-clean-up-reset-and-pin-2.png)\n\nA new \"Reset\" feature has been added, which can remove layered and overriden packages.\n\n![reset modal dialog]({{ site.baseurl }}/images/306-ostree-redesign-with-new-features-status-clean-up-reset-and-pin-3.png)\n\nDeployments can be pinned to persist even when new deployments trigger an auto-cleanup and unpinned.\n\n![screenshot showing a pinned deployment]({{ site.baseurl }}/images/306-ostree-redesign-with-new-features-status-clean-up-reset-and-pin-4.png)\n## Machines: Change \"Add disk\" default behavior\n\nThe \"Always attach\" Persistent option will now be set by default.\n\n## Podman: Delete intermediate images\n\nIntermediate images have no tags or other identifiers. They are usually intermediate layers from building container images or leftovers from moved tags. Intermediate images can now be deleted within Cockpit Podman.\n\n![screenshot of the \"delete intermediate images\" modal dialog]({{ site.baseurl }}/images/306-podman-delete-intermediate-images.png)\n\n## Try it out\n\nCockpit 306, cockpit-machines 303, cockpit-podman 82, and cockpit-ostree 198.1 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/306)\n* [Cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-4d96c042db)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-341915a0cc)\n* [cockpit-machines Source Tarball]()\n* [cockpit-machines Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-3bf577c576)\n* [cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-727c91dbd4)\n* [cockpit-ostree Source Tarball](https://github.com/cockpit-project/cockpit-ostree/releases/tag/198.1)\n* [cockpit-ostree Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-cf8edd8c6c)\n* [cockpit-ostree Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-e0d8c37bc8)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/82)\n* [cockpit-podman Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-1d879a2b9c)\n* [cockpit-podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-ec90e7ae52)\n\n*[OS]: Operating System\n*[repo]: repository\n"
  },
  {
    "path": "_posts/2023-12-14-cockpit-307.md",
    "content": "---\ntitle: Cockpit 307\nauthor: mvollmer\ndate: '2023-12-15'\ntags: cockpit, machines\nslug: cockpit-307\ncategory: release\nsummary: 'Storage redesign'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 307:\n\n## Storage redesign\n\nThe Storage page has been redesigned with the goal of making more things visible in all views. The overview page now shows all storage objects in a table and almost all operations can be performed on them right from the table.\n\nClicking on a row navigates to a page dedicated to the object in that row, with more information and in some cases, additional actions.\n\nFuture releases will continue to improve the Storage page by adding filtering options and extending the actions and dialogs.\n\n![screenshot of ## storage redesign]({{ site.baseurl }}/images/307-storage-redesign.png)\n\n## Try it out\n\nCockpit 307 and cockpit-machines 304 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/307)\n* [Cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-b17fb083f2)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-1bbf4060ec)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/304)\n* [cockpit-machines Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2023-c0853394ba)\n* [cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2023-5f86ffb62c)\n"
  },
  {
    "path": "_posts/2024-01-18-cockpit-309.md",
    "content": "---\ntitle: Cockpit 309\nauthor: lis\ndate: '2024-01-18'\ntags: cockpit\nslug: cockpit-309\ncategory: release\nsummary: 'Initial Btrfs support'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 309, cockpit-machines 305,\ncockpit-podman 83, and cockpit-ostree 199:\n\n## Initial Btrfs support\n\nCockpit now supports showing and mounting Btrfs subvolumes, and also handles multi-device Btrfs volumes.\n\nBtrfs subvolume overview:\n\n![screenshot of btrfs subvolume overview page]({{ site.baseurl }}/images/309-btrfs-subvolume-overview.png)\n\nBtrfs volume details:\n\n![screenshot of btrfs volume details page]({{ site.baseurl }}/images/309-btrfs-volume-details.png)\n\n## Try it out\n\nCockpit 309, cockpit-machines 305, cockpit-podman 83, and cockpit-ostree 199\nare available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/309)\n* [Cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-6f7b1a314d)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2024-d2bff51992)\n\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/305)\n* [cockpit-machines Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-631477a3c6)\n* [cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2024-24d7803523)\n\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/83)\n* [cockpit-podman Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-f637f5eec8)\n* [cockpit-podman Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2024-72bb8556f1)\n\n* [cockpit-ostree Source Tarball](https://github.com/cockpit-project/cockpit-ostree/releases/tag/199)\n* [cockpit-ostree Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-6cd029b4be)\n* [cockpit-ostree Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2024-a0306b4a31)\n"
  },
  {
    "path": "_posts/2024-01-31-cockpit-310.md",
    "content": "---\ntitle: Cockpit 310\nauthor: mvo\ndate: '2024-01-31'\ntags: cockpit, machines\nslug: cockpit-310\ncategory: release\nsummary: 'Btrfs creation, swap device support, virtual machine SPICE migration, and external VM snapshots'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 310 and cockpit-machines 306:\n\n## Storage: Create btrfs filesystems and subvolumes\n\nCockpit's Storage page continues to support more btrfs features. It can now create new btrfs filesystems and subvolumes.\n\n## Storage: Improved support for swap\n\nCockpit can now format block devices as swap and maintain a fstab entry for each.\n\n## Machines: Action to Replace SPICE devices\n\nSome VM host machines don't support [SPICE features](https://www.spice-space.org/spice-user-manual.html). In particular, Red Hat Enterprise Linux 9 does not support SPICE at all. Other operating systems might not have SPICE packages either.```\n\nVirtual machines that use SPICE now have a \"Replace SPICE support\" action, which is useful for adjusting machines on systems that do not have SPICE support, or preparing a VM to be ready to run on a new host after migration. Replacing SPICE converts SPICE graphics to VNC, \"qxl\" video to \"vga\", and drops spice devices which do not have a replacement, such as audio and USB passthrough.\n\nThis action can be selected from the VM's menu on the machines list.\n\n![screenshot of action to replace spice devices]({{ site.baseurl }}/images/310-machines-action-to-replace-spice-devices.png)\n\nWhen a host does not have SPICE support, but the VM is configured for SPICE, then Cockpit will show an alert to explain the issue and provide a way to run the \"replace SPICE\" action. This may occur if a machine was migrated without replacing SPICE or if the host system was upgraded to a new version of a distribution that no longer supports SPICE.\n\n![screenshot of action to replace spice devices]({{ site.baseurl }}/images/310-machines-action-to-replace-spice-devices-2.png)\n\n## Machines: External snapshot support\n\n\"External\" VM snapshots are more reliable and flexible than the \"internal\" format. External snapshots also work for raw disk images, not just for qcow2. Additionally, the internal format was [declared deprecated in RHEL 8](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/8.4_release_notes/deprecated_functionality#deprecated-functionality_virtualization).\n\nCockpit Machines uses the external snapshot format when using libvirt 9.9.0 or later. This is currently available in Fedora Rawhide, CentOS 9 Stream, Arch Linux, Debian Unstable, and Debian Testing.\n\nThe memory snapshot file location can be changed while the VM is running:\n\n![screenshot of external changes]({{ site.baseurl }}/images/310-external-snapshots.png)\n\n\n## Try it out\n\nCockpit 310 and cockpit-machines 306 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/310)\n* [Cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-74c8bd3c4c)\n* [Cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2024-f44114a0f9)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/306)\n* [cockpit-machines Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-07d3bd2cd6)\n* [cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2024-679fde542a)\n"
  },
  {
    "path": "_posts/2024-02-14-cockpit-311.md",
    "content": "---\ntitle: Cockpit 311\nauthor: jelle\ndate: '2024-02-14'\ntags: machines\nslug: cockpit-311\ncategory: release\nsummary: 'SPICE device replacement for multiple machines, storage pool support for pre-formatted block devices'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from cockpit-machines 307:\n\n\n## Machines: Replace SPICE for multiple machines\n\n\"Replace SPICE devices\" was introduced in [Cockpit 310](https://cockpit-project.org/blog/cockpit-310.html) to adjust VMs using SPICE to run on a host without SPICE capability. When opened from the context menu of a VM on the overview list, the dialog now offers to convert multiple VMs in a single step.\n\n![screenshot of the \"Replace SPICE devices\" dialog with options to include multiple machines]({{ site.baseurl }}/images/311-machines-mass-spice-conversion.png)\n\n## Machines: Add storage pool support for pre-formatted block devices\n\nVirtual machine storage pools now support pre-formatted block devices. This is a more robust alternative to \"physical disk devices\", as it avoids the guest OS seeing the device on its own, [which may lead to unintentional reformatting of a raw disk device](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/configuring_and_managing_virtualization/managing-storage-for-virtual-machines_configuring-and-managing-virtualization#proc_creating-disk-based-storage-pools-using-the-web-console_assembly_managing-virtual-machine-storage-pools-using-the-web-console).\n\n![Virtual machine creation modal dialog with \"pre-formatted block device\" selected]({{ site.baseurl }}/images/311-machines-add-support-for-pre-formatted-block-device-storage-pool-type.png)\n\n_Thanks to Haruka Ohata for this contribution!_\n\n\n## Try it out\n\ncockpit-machines 307 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/311)\n* [cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-be44af3059)\n* [cockpit Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2024-7b0bc52005)\n\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/307)\n* [cockpit-machines Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-88b4add47e)\n* [cockpit-machines Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-2990bb998a)\n* [cockpit-machines Fedora 38](https://bodhi.fedoraproject.org/updates/FEDORA-2024-811e2c68fd)\n\n\n*[VM]: Virtual Machine\n*[VMs]: Virtual Machines\n"
  },
  {
    "path": "_posts/2024-03-27-cockpit-314.md",
    "content": "---\ntitle: Cockpit 314\nauthor: mvo\ndate: '2024-03-27'\ntags: cockpit, ostree\nslug: cockpit-314\ncategory: release\nsummary: 'read-only encryption improvements, OCI container origins'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 314 and cockpit-ostree 201:\n\n## Diagnostic reports: Fix command injection vulnerability with crafted report names\n\n[Cockpit 270](https://cockpit-project.org/blog/cockpit-270.html)\nintroduced a possible local privilege escalation vulnerability with\ndeleting diagnostic reports (sosreport). Files in /var/tmp/ are\ncontrollable by any user. In particular, an unprivileged user could\ncreate an sosreport* file containing a `'` and a shell command, which\nwould then run with root privileges when the admin Cockpit user tried\nto delete the report.\n\nThis Cockpit version fixes the problem by removing the files with\ndirect system calls instead of a shell command.\n\nThis is tracked as [CVE-2024-2947](https://www.cve.org/CVERecord?id=CVE-2024-2947).\nIf you need to backport this to older cockpit versions, you can apply\nthe [upstream patch](https://github.com/cockpit-project/cockpit/commit/9c4cc9b6df632082538b53bdc8ee9ec1c5cad4da).\n\nIf you cannot update or patch, then check the displayed report file\nnames for non-standard characters, in particular `'`, `$`, `(` and \\`,\nand don't use Cockpit's Diagnostic reports page to delete them.\n\n## Storage: Improvements to read-only encrypted filesystems\n\nCockpit now unlocks encrypted filesystems with a \"read-only\"\nencryption layer when the filesystem itself is mounted read-only.\n\n## Ostree: Show OCI container origin\n\ncockpit-ostree now detects and shows the origin, repository, and\nbranch name of [native container repositories](https://coreos.github.io/rpm-ostree/container/)\nin both the \"OSTree source\" card and the deployment list:\n\n![screenshot of show oci container origin]({{ site.baseurl }}/images/314-ostree-show-oci-container-origin.png)\n\n![screenshot of show oci container origin]({{ site.baseurl }}/images/314-ostree-show-oci-container-origin-2.png)\n\n## Try it out\n\nCockpit 314 and cockpit-ostree 201 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/314)\n* [Cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-6065341780)\n* [Cockpit Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-4e95f130fc)\n* [cockpit-ostree Source Tarball](https://github.com/cockpit-project/cockpit-ostree/releases/tag/201)\n* [cockpit-ostree Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-80a6144d2d)\n* [cockpit-ostree Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-a1d54f64d2)\n"
  },
  {
    "path": "_posts/2024-04-24-cockpit-316.md",
    "content": "---\ntitle: Cockpit 316\nauthor: jelle\ndate: '2024-04-25'\ntags: cockpit, machines, ostree, podman\nslug: cockpit-316\ncategory: release\nsummary: 'cockpit.js format_bytes API changes'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 316, cockpit-machines 312, and cockpit-podman 87:\n\n\n## cockpit.js API: Fix format_bytes() units\n\nThe [`cockpit.format_bytes()`](https://cockpit-project.org/guide/latest/cockpit-util.html#cockpit-format-bytes) function now writes the unit for kilobytes as SI conformant \"kB\" instead of \"KB\" when formatting decimal (base-10) sizes. It also uses the unit \"B\" (bytes) for numbers less than 1000 instead of no unit at all.\n\nNote that many projects, in particular the ones based on current [starter-kit](https://github.com/cockpit-project/starter-kit), bundle `cockpit.js` and usually also pin down a specific git commit from cockpit.git. So these projects won't immediately pick up the change, but should update the cockpit library import and possibly adjust their usage of `format_bytes()`.\n\n## Try it out\n\nCockpit 316, cockpit-machines 312, cockpit-ostree 202 and cockpit-podman 87 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/316)\n* [cockpit Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-bc42ae090a)\n* [cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-c61ce9706d)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/312)\n* [cockpit-machines Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-2326dec3de)\n* [cockpit-machines Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-700df9e0b4)\n* [cockpit-ostree Source Tarball](https://github.com/cockpit-project/cockpit-ostree/releases/tag/202)\n* [cockpit-ostree Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-e8e706ec17)\n* [cockpit-ostree Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-40beb7bdae)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/87)\n* [cockpit-podman Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-bba9077d43)\n* [cockpit-podman Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-17dc45708b)\n\n\n*[API]: Application Programming Interface\n*[CPU]: Central Processing Unit, the \"brain\" of a computer\n"
  },
  {
    "path": "_posts/2024-05-28-cockpit-317.md",
    "content": "---\ntitle: Cockpit 317\nauthor: jelle\ndate: '2024-05-28'\ntags: cockpit, machines, files\nslug: cockpit-317\ncategory: release\nsummary: 'webserver system user changes, Grafana setup now prefers Valkey instead of Redis'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 317:\n\n\n## webserver: System user changes\n\nCockpit has changed how the system user is handled. All supported distributions use the same system user names. We don't test, support, or recommend running the web server as root, which had previously been the default with an upstream build and install. Hence, the following `./configure` options related to static users have been removed:\n - `--with-cockpit-user`\n - `--with-cockpit-group`\n - `--with-cockpit-ws-instance-user`\n - `--with-cockpit-ws-instance-group`\n\nThe `cockpit-ws` system user is no longer statically created, but created transiently and on-demand via [systemd's `DynamicUser` feature](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#DynamicUser=). If you would like to remove the previously-used static system user:\n 1. Upgrade to Cockpit 317 or later\n 2. Run `systemctl stop cockpit`\n 3. Run `userdel -r cockpit-ws`\n\nThe `cockpit-wsinstance` system user is now declared through [systemd-sysusers](https://www.freedesktop.org/software/systemd/man/latest/sysusers.d.html#).\n\n## Metrics: Grafana setup now prefers Valkey\n\nThe [Grafana metrics setup](https://cockpit-project.org/blog/pcp-grafana.html) now prefers using [valkey](https://valkey.io/) over [redis](https://redis.io/) on Fedora. See the [Fedora change proposal](https://fedoraproject.org/wiki/Changes/Replace_Redis_With_Valkey) for details.\n\n## Try it out\n\nCockpit 317 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/317)\n* [Cockpit Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-42da7bcbbc)\n"
  },
  {
    "path": "_posts/2024-06-10-first-cockpit-files-release.md",
    "content": "---\ntitle: \"Cockpit Files: the first release\"\nauthor: jelle\ndate: 2024-06-10\ncategory: release\ntags: cockpit files manager browser\n---\n\nLast Friday, we released the first version of Cockpit Files: a plugin for Cockpit to manage files on your server through your web browser. Cockpit Files was initially started by Google Summer of Code (GSoC) student [Mahmoud Hamdy](https://github.com/MahmoudHamdy02) and is now under active development by the Cockpit team. The goal is to replace the functionality of the [cockpit-navigator](https://github.com/45drives/cockpit-navigator/) plugin from 45Drives and include automated testing per commit, a standard PatternFly-based interface, and consistency with the rest of Cockpit.\n\nThis initial release already contains several features, including:\n\n- downloading files\n- uploading files\n- copy and paste\n- renaming files and directories\n- creating directories\n- editing permissions\n- icon view, with several filetypes\n- details view\n- sorting\n\n## Screenshots\n\nThe default overview of Cockpit files is an icon based folder view of your home directory.\n\n![Cockpit Files overview](/images/cockpit-files-1-overview.png)\n{:.screenshot.left}\n\nAlternatively you can view it as a list and sort on one of the columns.\n\n![Cockpit Files list view](/images/cockpit-files-1-listview.png)\n{:.screenshot.left}\n\nMultiple files can be uploaded to your server at once.\n\n![Cockpit Files upload](/images/cockpit-files-1-upload.png)\n{:.screenshot.left}\n\n## Try it out\n\nDevelopment builds to try out Cockpit Files are available for Fedora using [our 3rd party Copr repository for Cockpit Files](https://copr.fedorainfracloud.org/coprs/g/cockpit/main-builds/package/cockpit-files).\n\nIn the future we expect Cockpit Files to be available as an installable package in Arch Linux, Debian and Fedora.\n\nWhile Cockpit Files is still relatively new, features that are currently shipped are expected to work. Please file bug reports and feature requests on our [issue tracker](https://github.com/cockpit-project/cockpit-files/issues).\n\n## Looking to the future\n\nWe have a lot planned and already thinking about additional features such as:\n\n- a basic file editor, intended for simple configuration files\n- cut support, for moving files\n- basic SELinux integration\n- basic Access Control Lists (ACL) integration\n- symbolic link creation\n- ...and have several other ideas in store\n"
  },
  {
    "path": "_posts/2024-06-12-cockpit-318.md",
    "content": "---\ntitle: Cockpit 318\nauthor: pitti\ndate: '2024-06-12'\ntags: cockpit\nslug: cockpit-318\ncategory: release\nsummary: 'Storage deletion confirmation, remove i686 support'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 318:\n\n\n## Storage: Extra confirmation before deleting non-empty partitions in Anaconda's Web UI\n\nWhen using Cockpit to manually configure storage during installation with the Web UI version of the Anaconda installer, operations typically involve empty partitions. For instance, someone might delete and recreate a partition with a different size or filesystem type. Since no actual data is deleted in these cases, such actions are usually harmless.\n\nHowever, existing partitions with valuable data or other operating systems might also be present. To prevent accidental deletion, Cockpit now checks for files within a partition before deleting it and asks for additional confirmation if files are found.\n\n![screenshot of extra confirmation before deleting non-empty partitions in anaconda's web ui]({{ site.baseurl }}/images/318-storage-extra-confirmation-before-deleting-non-empty-partitions-in-anaconda-s-web-ui.png)\n\n## Discontinue Intel 32-bit Support in Fedora, CentOS, and RHEL\n\nBeginning with Fedora 41 (currently in development as rawhide), Cockpit will no longer be built for the Intel 32-bit architecture (i686).\n\n## cockpit.js: Get user primary group ID\n\nThe [cockpit.user()](https://cockpit-project.org/guide/latest/cockpit-login.html#cockpit-user) API call now returns a new field `gid` with the user's primary group ID.\n\n## Try it out\n\nCockpit 318 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/318)\n* [Cockpit Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-36700dc910)\n* [Cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/314)\n* [Cockpit-machines Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-73cda163ca)\n* [Cockpit-machines Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-f1e0a94ad8)\n\n*[API]: Application Programming Interface\n*[OS]: Operating System\n*[RHEL]: Red Hat Enterprise Linux\n"
  },
  {
    "path": "_posts/2024-06-26-cockpit-319.md",
    "content": "---\ntitle: Cockpit 319\nauthor:\ndate: '2024-06-26'\ntags: cockpit, podman, files\nslug: cockpit-319\ncategory: release\nsummary: 'btrfs snapshots, podman image pull, files bookmark support'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 319, cockpit-machines 315, cockpit-podman 90, and cockpit-files 2:\n\n\n## Storage: Btrfs snapshots\n\nSubvolume snapshots are now listed on subvolume detail pages.\n\n![screenshot of ## show snapshots of a subvolume in the detail view]({{ site.baseurl }}/images/319-show-snapshots-of-a-subvolume-in-the-detail-view.png)\n{:.screenshot}\n\nSnapshot origins are shown in the snapshots detail view.\n\n![screenshot of ## show snapshots of a subvolume in the detail view]({{ site.baseurl }}/images/319-show-snapshots-of-a-subvolume-in-the-detail-view-2.png)\n{:.screenshot.left}\n\n\n## Podman: Add image pull action\n\nUse the \"Pull\" option in an image's context menu to update it to the latest available version.\n\n![screenshot of add image pull action]({{ site.baseurl }}/images/319-podman-add-image-pull-action.png)\n{:.screenshot.left}\n\n\n## Files: Bookmark support\n\nNavigate to saved locations or add the current directory to bookmarks using the new bookmarks button.\n\n![Screenshot from 2024-06-10 04-26-39]({{ site.baseurl }}/images/319-bookmark-support.png)\n{:.screenshot.left}\n\n## Try it out\n\nCockpit 319, cockpit-machines 315, cockpit-podman 90, and cockpit-files 2 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/319)\n* [cockpit Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-5a7a6635de)\n* [cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-0b9fb03da5)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/90)\n* [cockpit-podman Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-050e51f81d)\n* [cockpit-podman Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-cd30de6a57)\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/2)\n* [cockpit-files Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-9d0bcb54c5)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/315)\n* [cockpit-machines Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-d22ba42be3)\n* [cockpit-machines Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-838ac0c2f9)\n\n"
  },
  {
    "path": "_posts/2024-07-03-cockpit-320.md",
    "content": "---\ntitle: Cockpit 320\nauthor: pitti\ndate: '2024-07-03'\ntags: cockpit\nslug: cockpit-320\ncategory: release\nsummary: 'CVE-2024-6126 pam-ssh-add vulnerability'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 320:\n\n\n## pam-ssh-add: Fix insecure killing of session ssh-agent [CVE-2024-6126]\n\n### Affected systems\n* **Debian, Ubuntu, and other Debian-derived distributions**: These distributions enable the deprecated `user_readenv` option by default in [the `pam_env` PAM module](https://man7.org/linux/man-pages/man8/pam_env.8.html).\n* **Fedora, CentOS, RHEL, Arch, OpenSUSE**: Not affected by default. Only systems where the `user_readenv` option has been manually enabled.\n* **Other Linux distributions**: Check `grep -r user_readenv /etc/pam.d`. If there is no output, you are not affected. Otherwise check if the \"cockpit\" PAM module directly or indirectly uses that option.\n\nThis is tracked as [CVE-2024-6126](https://www.cve.org/CVERecord?id=CVE-2024-6126).\n\n### Impact\n\nCockpit's `pam_ssh_add` module had a vulnerability when `user_readenv` is enabled on the system, as it inherits the settings from the system in `/etc/pam.d/cockpit`.\n\nThis could cause a Denial of Service if a locally-authenticated user could craft a `~/.pam_environment` file which would kill an arbitrary process on the system with root privileges when logging out of a Cockpit session.\n\n### Fix\n\n- Upgrade to **Cockpit version 320** to fix this issue.\n- For older Cockpit versions, a [backportable patch is available](https://github.com/cockpit-project/cockpit/commit/08965365ac311f906a520cbf65427742d5f84ba4).\n\n### Workaround\n\nIf you cannot upgrade to Cockpit 320 or use the patch linked above, and may have potentially malicious local users on a system running Cockpit, you can mitigate this vulnerability:\n\n- Remove the `user_readenv=1` option from the `pam_env.so` line in `/etc/pam.d/cockpit`.\n\nThis will disable reading any extra environment variables in user's `~/.pam_environment` files, which is most commonly used to set a local environment different from the system default.\n\n### Acknowledgments\n\nMany thanks to [Paolo Perego](https://github.com/thesp0nge) for discovering, and [Luna Dragon](https://github.com/Lunarequest/) for reporting this issue!\n\n## Try it out\n\nCockpit 320 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/320)\n* [Cockpit Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-d8bbe82ac1)\n* [Cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-9eb3674b7c)\n\n*[RHEL]: Red Hat Enterprise Linux\n"
  },
  {
    "path": "_posts/2024-08-08-cockpit-322.md",
    "content": "---\ntitle: Cockpit 322\nauthor: mvo\ndate: '2024-08-08'\ntags: cockpit\nslug: cockpit-322\ncategory: release\nsummary: 'Host switcher is now deprecated and Cockpit Files adds permissions in details view'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 322 and cockpit-files 5:\n\n## Shell: Deprecate host switching\n\nThe \"host switcher\" at the top-left corner of Cockpit enables\nconnections to multiple machines using SSH, runs a Cockpit session on\neach connected machine, and lets you switch between them.\n\nAlthough this feature is useful, when numerous hosts are active, they\ncan potentially interact with each other in ways that might not be\nexpected within an SSH trust boundary. For example, when connecting to\nan untrusted host from another host, it's assumed that the untrusted\nhost should not have access or control over the originating\nhost. However, due to web technology limitations, hosts may affect one\nanother through [direct remote\nchannels](https://issues.redhat.com/browse/COCKPIT-870), [iframe\ntraversal](https://issues.redhat.com/browse/RHEL-4032), [cache\npoisoning](https://issues.redhat.com/browse/RHEL-4037), and other\nmeans.\n\nAfter several months of research into current web technologies, we\nfound no way to prevent these concerns. Therefore, the Cockpit team\nintends to disable the host switcher feature.\n\nAs a first step, the host switcher will be disabled by default in:\n- Fedora 41 and later\n- Debian Unstable and Testing\n- CentOS Stream 10\n- Red Hat Enterprise Linux 10\n- Arch Linux\n\nThe host switcher will stay as-is in current stable Linux\ndistributions. This includes Red Hat Enterprise Linux 9, CentOS Stream\n9, Fedora 39 and 40, Debian 12 \"Bookworm\", and Ubuntu 22.04 LTS and\n24.04 LTS.\n\n### Alternatives\n\n* The login page offers a \"Connect to:\" field which will directly\n  connect to another host using SSH. This is safe as long as you only\n  connect to a single host within a browser session. This will always\n  be supported. However, this only supports user/password or Kerberos\n  authentication, not SSH keys.\n\n* On a Linux desktop, consider using the [Cockpit Client\n  flatpak](https://flathub.org/apps/details/org.cockpit_project.CockpitClient). It\n  supports password and SSH key authentication to any SSH host and can\n  even provide a Cockpit session for machines which don't have *any*\n  Cockpit packages installed.\n\n* For custom pages that use channels (commands, file operations, D-Bus\n  calls, etc.) on a remote machine, use the\n  [cockpit-connect-ssh](https://github.com/cockpit-project/cockpit/blob/main/pkg/lib/cockpit-connect-ssh.tsx)\n  library to set up the SSH connection instead of relying on the host\n  switcher.\n\n### Mitigation\n\nIn the short term, you can re-enable host switcher functionality with\nthe `AllowMultiHost` option in\n[cockpit.conf](https://cockpit-project.org/guide/latest/cockpit.conf.5.html):\n\n```ini\n[WebService]\nAllowMultiHost=yes\n```\n\n## Files: Permissions column in details view\n\nA sortable permissions column is now available in the details view. It shows permissions grouped by who it applies to and further explains permissions using tooltips.\n\n![screenshot of files in a detail view with a tooltip to explain permissions]({{ site.baseurl }}/images/322-display-file-permissions.png)\n{:.screenshot}\n\n\n## Try it out\n\nCockpit 322 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/322)\n* [Cockpit Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-2d323b91ba)\n* [Cockpit Fedora 39](https://bodhi.fedoraproject.org/updates/FEDORA-2024-1a7bf6c0fb)\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/6)\n* [cockpit-files Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-2333ef152c)\n\n*[OS]: Operating System\n*[RHEL]: Red Hat Enterprise Linux\n*[SSH]: Secure Shell, a common protocol to securely connect to a remote computer\n"
  },
  {
    "path": "_posts/2024-09-04-cockpit-324.md",
    "content": "---\ntitle: Cockpit 324\nauthor: jelle\ndate: '2024-09-04'\ntags: podman, files\nslug: cockpit-324\ncategory: release\nsummary: 'Show port ranges in Cockpit Podman; view and edit files in Cockpit Files'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from cockpit-podman 94 and cockpit-files 7:\n\n\n## Podman: Show ports as ranges\n\nIn container and pod details, Cockpit Podman shows contiguous ports as a range when they use the same protocol, host, or host IP.\n\n![screenshot of ## show container/pod ports as ranges]({{ site.baseurl }}/images/324-show-container-pod-ports-as-ranges.png)\n\n## Files: Viewing and editing text files\n\nCockpit Files now supports viewing and editing small text files, perfect for quickly editing configuration files. Right click a file and select \"Open text file\" to edit.\n\n![screenshot of ## viewer/editor for text files]({{ site.baseurl }}/images/324-viewer-editor-for-text-files.png)\n\nViewing a configuration file:\n\n![screenshot of ## viewer/editor for text files]({{ site.baseurl }}/images/324-viewer-editor-for-text-files-2.png)\n\nEdit a configuration file:\n\n![screenshot of ## viewer/editor for text files]({{ site.baseurl }}/images/324-viewer-editor-for-text-files-3.png)\n\nIf a file is changed on disk while editing, a warning will appear:\n\n![screenshot of ## viewer/editor for text files]({{ site.baseurl }}/images/324-viewer-editor-for-text-files-4.png)\n\n## Try it out\n\ncockpit-podman 94 and cockpit-files 7 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/94)\n* [cockpit-podman Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-699f6f1637)\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/7)\n* [cockpit-files Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-934472ed30)\n"
  },
  {
    "path": "_posts/2024-09-25-cockpit-325.md",
    "content": "---\ntitle: Cockpit 325\nauthor: pitti\ndate: '2024-09-25'\ntags: cockpit, machines\nslug: cockpit-325\ncategory: release\nsummary: 'VM snapshot improvements, VM descriptions'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 325 and cockpit-machines 320:\n\n## Machines: Improvements to snapshots of running machines\n\nWhen creating a snapshot of a running machine,  Cockpit asks where to store its memory file. This has improved in several ways:\n\n - Only a directory needs to be specified; Cockpit will generate a filename.\n - The snapshot dialog remembers the storage path, making future snapshots easier.\n - Space estimates are shown, including a warning if there isn't enough storage available.\n\n![screenshot]({{ site.baseurl }}/images/325-machines-improvements-to-snapshots-of-running-machines.png)\n\n## Machines: Support for VM descriptions\n\nCockpit can now show and change the descriptions of virtual machines.\n\n![screenshot-page]({{ site.baseurl }}/images/325-machines-support-for-vm-descriptions.png)\n\n![screenshot]({{ site.baseurl }}/images/325-machines-support-for-vm-descriptions-2.png)\n\n\n## Try it out\n\nCockpit 325 and cockpit-machines 320 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/325)\n* [Cockpit Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2024-02d099aec8)\n* [Cockpit Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-03b4931a30)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/320)\n* [cockpit-machines Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2024-f24bc00c34)\n* [cockpit-machines Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-25809c2c11)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2024-10-08-cockpit-326.md",
    "content": "---\ntitle: Cockpit 326\nauthor: mvo\ndate: '2024-10-08'\ntags: cockpit, podman, files\nslug: cockpit-326\ncategory: release\nsummary: 'The cockpit/ws container now supports connections to hosts without Cockpit installed and has ssh key support, cockpit-pcp package replaced with native PCP support in bridge, Storage gains support for the Stratis virtual filesystem, cockpit-podman supports registries without a search API, and cockpit-files gains a keyboard shortcuts dialog'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 326, cockpit-podman 96, and cockpit-files 9:\n\n## cockpit/ws container: Connect to any Linux server\n\nThe [quay.io/cockpit/ws](https://quay.io/repository/cockpit/ws) container provides Cockpit's web server in environments such as Kubernetes and [Fedora CoreOS](https://fedoraproject.org/coreos/), connecting to a remote machine via `ssh`.\n\nNow, the cockpit/ws container gained the ability to connect to _any_ Linux server, even those without Cockpit installed. This provides a convenient way to perform basic administration tasks remotely. This is similar to the [Cockpit Client flatpak](https://flathub.org/apps/org.cockpit_project.CockpitClient) ([available since release 295](https://cockpit-project.org/blog/cockpit-295.html)), but can run anywhere an OCI container can run.\n\nCurrently, the following pages are available when connecting to a server without Cockpit: Overview, Metrics, Terminal, Accounts, and Networking.  More pages will be added soon, after vetting them for this use.\n\n## cockpit/ws container: Support host-specific SSH keys\n\nThe [cockpit/ws](https://quay.io/repository/cockpit/ws) container now supports adding multiple SSH private keys.\n\nIn addition to the existing `$COCKPIT_SSH_KEY_PATH` environment variable, you can now set host specific `$COCKPIT_SSH_KEY_PATH_{HOSTNAME}` variables, where `{HOSTNAME}` is the host name (in capital letters) used in the `Connect to:` field of the login page.\n\n_Thanks to [benniekiss](https://github.com/benniekiss) for contributing this feature!_\n\n## Bridge supports PCP; cockpit-pcp package is now obsolete\n\nThe Python cockpit-bridge, introduced in Cockpit 294, now implements PCP functionality. As a result, the separate cockpit-pcp package is now obsolete.\n\n## Storage: Manage Stratis virtual filesystem sizes\n\nCockpit supports seting a default and maximum size limit for Stratis virtual filesystems, both during creation and when making adjustments.\n\n![screenshot of support for managing virtual stratis filesystem sizes]({{ site.baseurl }}/images/326-storage-support-for-managing-virtual-stratis-filesystem-sizes.png)\n\n\n## Podman: pull images from registries without search API\n\nContainer creation now supports registries lacking a search API, including GitHub's container registry (ghcr.io). You can also select a specific tag for images.\n\n![screenshot of pull images from registries without search api]({{ site.baseurl }}/images/326-podman-pull-images-from-registries-without-search-api-.png)\n\n\n## Files: basic keyboard shortcuts\n\n![screenshot of basic keyboard shortcuts]({{ site.baseurl\n}}/images/326-files-basic-keyboard-shortcuts.png)\n\n## Try it out\n\nCockpit 326, cockpit-podman 96, and cockpit-files 9 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/326)\n* [Cockpit Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2024-087e30f1c6)\n* [Cockpit Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-0dcc1335a0)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/96)\n* [cockpit-podman Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2024-c6fefeea2b)\n* [cockpit-podman Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-c80bcbe899)\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/9)\n* [cockpit-files Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2024-54c247d999)\n* [cockpit-files Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-18636d14d6)\n\n*[API]: Application Programming Interface\n*[CI]: continuous integration (testing)\n*[OS]: Operating System\n*[repo]: repository\n*[SSH]: Secure Shell, a common protocol to securely connect to a remote computer\n"
  },
  {
    "path": "_posts/2024-10-23-cockpit-327.md",
    "content": "---\ntitle: Cockpit 327\nauthor: pitti\ndate: '2024-10-23'\ntags: cockpit\nslug: cockpit-327\ncategory: release\nsummary: 'connect to similar servers without Cockpit installed'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 327:\n\n\n## Connect to similar servers without Cockpit installed\n\nSupport for connecting to remote machines without Cockpit installed now extends to the standard Linux distribution packages.\n\nThe [Cockpit Client flatpak](https://flathub.org/apps/org.cockpit_project.CockpitClient) has been capable of connecting to remote machines without Cockpit installed since its beginning in [release 295](https://cockpit-project.org/blog/cockpit-295.html) and the [cockpit/ws container](https://quay.io/repository/cockpit/ws) since [version 326](https://cockpit-project.org/blog/cockpit-326.html) recently added this functionality.\n\nTo ensure compatibility and safety, package-installed versions of Cockpit only allow connections to remote machines without Cockpit running the same operating system version. Future releases may relax this limitation.\n\n\n## Try it out\n\nCockpit 327 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/327)\n* [Cockpit Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2024-3f7ada978a)\n* [Cockpit Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-fa89092e0b)\n\n*[OS]: Operating System\n*[repo]: repository\n"
  },
  {
    "path": "_posts/2024-11-06-cockpit-328.md",
    "content": "---\ntitle: Cockpit 328\nauthor:\ndate: '2024-11-06'\ntags: machines, files\nslug: cockpit-328\ncategory: release\nsummary: 'Add a TPM to a VM, change permissions for enclosed files, and view SELinux content of a file'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from cockpit-machines 323 and cockpit-files 11:\n\n\n## Machines: TPM improvements\n\nExisting VMs using EFI but that do not have a TPM now have a menu action to add a TPM. This is especially useful for upgrading older VMs which have OS requirements that require a TPM, such as Windows 11.\n\nCreating new VMs using EFI will automatically have a TPM created and configured.\n\n![tpm_kebab]({{ site.baseurl }}/images/328-machines-action-to-add-a-tpm.png)\n{:.screenshot.left}\n\n## Files: Change permissions for enclosed files\n\nWhen setting the permissions for a directory, there is now an action to also recursively change all files and directories it contains.\n\n![screenshot of change permissions for enclosed files]({{ site.baseurl }}/images/328-files-change-permissions-for-enclosed-files.png)\n{:.screenshot.left}\n\n## Files: View SELinux context of a file or directory\n\nThe \"Edit permissions\" dialog now shows a read-only view of the SELinux context.\n\n![screenshot of view selinux context of a file]({{ site.baseurl }}/images/328-files-view-selinux-context-of-a-file.png)\n{:.screenshot.left}\n\n## Try it out\n\ncockpit-machines 323 and cockpit-files 11 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/323)\n* [cockpit-machines Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2024-36bb952bda)\n* [cockpit-machines Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-739b51d9f3)\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/11)\n* [cockpit-files Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-347c1cef29)\n* [cockpit-files Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2024-4f95125108)\n\n*[OS]: Operating System\n*[SELinux]: Security-Enhanced Linux, policies for enforcing access controls in Linux\n*[VM]: Virtual Machine\n*[VMs]: Virtual Machines\n"
  },
  {
    "path": "_posts/2024-11-20-cockpit-329.md",
    "content": "---\ntitle: Cockpit 329\nauthor: mvo\ndate: '2024-11-20'\ntags: cockpit, files\nslug: cockpit-329\ncategory: release\nsummary: 'Improved warnings when connecting to remote hosts and Cockpit Files learns how to create new files'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from cockpit 329 and cockpit-files 12:\n\n\n## Shell: Improve warning when connecting to remote hosts\n\nWhile [Cockpit 322](https://cockpit-project.org/blog/cockpit-322.html) deprecated the \"host switcher\" on newer distribution versions, connecting to hosts within Cockpit is still possible on older distribution versions or when using a specific override in `cockpit.conf`. Cockpit now displays a clear warning when connecting to a remote host, as all connected hosts can control each other.\n\n![screenshot of extra warnings when connecting to remote hosts]({{ site.baseurl }}/images/329-shell-extra-warnings-when-connecting-to-remote-hosts.png)\n\n\nThis warning can be disabled by including the following in `/etc/cockpit/cockpit.conf`:\n\n```\n[Session]\nWarnBeforeConnecting=false\n```\n\n## Files: File creation support\n\nCreate new files directly in Cockpit Files. Enter the file name and content. Ownership is automatically determined from the current directory, but can be changed if needed.\n\n![screenshot of file creation support]({{ site.baseurl }}/images/329-cockpit-files-file-creation-support.png)\n\n## Try it out\n\nCockpit 329 and cockpit-files 12 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/329)\n* [Cockpit Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2024-dfb16f4947)\n* [Cockpit Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-8c16d73fbb)\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/12)\n* [cockpit-files Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2024-26a924256e)\n* [cockpit-files Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-e189b427d7)\n"
  },
  {
    "path": "_posts/2024-12-04-cockpit-330.md",
    "content": "---\ntitle: Cockpit 330\nauthor: pitti\ndate: '2024-12-04'\ntags: cockpit\nslug: cockpit-330\ncategory: release\nsummary: 'bootc support, sysext development mode'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 330:\n\n\n## Web server: Increased sandboxing, `setuid` removal, `bootc` support\n\nCockpit's web server already had low privilege levels, but previously used a [setuid](https://en.wikipedia.org/wiki/Setuid) helper program `cockpit-session` for user logins. That helper had restricted permissions and was only executable by Cockpit (through group ownership). Its sole purpose was to run at the system level and immediately drop permissions to log in to a specific user account. However, the binary was still `setuid`, and `setuid` should be avoided for security reasons.\n\nThis release removes the `setuid` flag from the helper. `cockpit-session` now starts via systemd socket activation, with the Cockpit web server connecting to it using a protected UNIX socket in the `/run` directory. This approach enables tighter sandbox security by preventing the login session from being a direct descendant of the web server process. It also [fixes Cockpit on bootc images](https://github.com/cockpit-project/cockpit/issues/21201).\n\nAll Cockpit components now run as dynamic users created at startup using the `DynamicUser=` systemd feature.  Existing systems may still have a `cockpit-ws` user (and very old systems might even have associated TLS certificates). However, this `cockpit-ws` user is no longer required and can be safely deleted.\n\n## Development: New install mode using `systemd-sysext`\n\nTo simplify development, a new build tool can install Cockpit as a [systemd-sysext](https://www.freedesktop.org/software/systemd/man/latest/systemd-sysext.html) (system extension). This enables testing all parts of Cockpit (web server, login page, systemd units, and bridge) directly on the host system, safely and quickly, without modifying the disk or having to use a virtual machine. Installation is temporary in `/run/extensions/` and cleared on reboot.\n\nRead [the documentation for detailed instructions](https://github.com/cockpit-project/cockpit/blob/main/HACKING.md#working-on-your-local-machine-systemd-sysext).\n\n\n## Try it out\n\nCockpit 330 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/330)\n* [Cockpit Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2024-60684a3b16)\n* [Cockpit Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-ba2375d278)\n\n*[TLS]: Transport Layer Security\n"
  },
  {
    "path": "_posts/2024-12-18-cockpit-331.md",
    "content": "---\ntitle: Cockpit 331\nauthor: jelle\ndate: '2024-12-18'\ntags: cockpit, machines, files\nslug: cockpit-331\ncategory: release\nsummary: 'Prevent search engine indexing, support sharing host ssh-agent, downloading of unsupported operating systems and file upload improvements'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 331, cockpit-machines 326, and cockpit-files 14:\n\n## Files: Allow uploading files as administrator\n\nWhen logged in with administrator privileges, you can now upload files to directories other than your home. The default ownership of these files are the user/group of the current directory. This can be changed after the upload completes.\n\n![screenshot of ## allow uploading files as administrator]({{ site.baseurl }}/images/331-allow-uploading-files-as-administrator.png)\n\n## Files: Drag and drop file upload\n\nIt is now possible to upload files by simply dragging them from your desktop or a file explorer and dropping them directly into Cockpit Files.\n\n![dragndrop-smaller]({{ site.baseurl }}/images/331-drag-and-drop-file-upload.png)\n\n## Files: Allow editing of multiple file permissions\n\nThe permissions of multiple selected files can now be changed if they have the same owner and group.\n\n![screenshot of ## allow editing of multiple file permissions]({{ site.baseurl }}/images/331-allow-editing-of-multiple-file-permissions.png)\n\n## Machines: Download and install unsupported and older operating systems\n\nCockpit now offers to download and install unsupported and older operating systems, while still promoting supported and newer ones.\n\n![screenshot of download and install unsupported and older operating systems]({{ site.baseurl }}/images/331-machines-download-and-install-unsupported-and-older-operating-systems.png)\n\n## ws container: Support sharing host ssh-agent\n\nFor SSH key authentication, the [cockpit/ws container](https://quay.io/repository/cockpit/ws) has supported bind-mounting private SSH keys into the container for a long time. That mode is appropriate for server system containers or deploying in e.g. Kubernetes.\n\nFor desktop use cases similar to [Cockpit Client](https://github.com/flathub/org.cockpit_project.CockpitClient) it is preferable to instead run the ws container as your own user, and share your user session's [SSH agent](https://linux.die.net/man/1/ssh-agent). This provides a more comfortable login experience as you don't have to unlock private keys with your passphrases on the Cockpit login page again, and this also avoids exposing the private key to the web server.\n\nPlease see the \"SSH authentication: Share SSH agent with container\" section in the [container documentation](https://quay.io/repository/cockpit/ws) for details.\n\n## ws: Prevent search engine indexing with robots.txt\n\nPublic Cockpit instances are no longer indexed by default.\n\n## Try it out\n\nCockpit 331, cockpit-machines 326, and cockpit-files 14 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/331)\n* [Cockpit Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-f628a4fdfa)\n* [Cockpit Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2024-e711c105f7)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/326)\n* [cockpit-machines Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2024-262f9653db)\n* [cockpit-machines Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-7777033248)\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/14)\n* [cockpit-files Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2024-e89afaedc1)\n* [cockpit-files Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2024-1082464f5d)\n\n*[repo]: repository\n*[SSH]: Secure Shell, a common protocol to securely connect to a remote computer\n"
  },
  {
    "path": "_posts/2025-01-29-cockpit-332.md",
    "content": "---\ntitle: Cockpit 332\nauthor: jelle\ndate: '2025-01-29'\ntags: cockpit, machines, podman, files\nslug: cockpit-332\ncategory: release\nsummary: 'package-less session support for more operation systems, show system boot times in metrics, automatically start podman.socket and improve quadlet support in cockpit-podman, show user group in files footer'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 332, cockpit-machines 327, cockpit-podman 100, and cockpit-files 15:\n\n## cockpit/ws container: Include cockpit-files\n\nThe [cockpit/ws container](https://quay.io/repository/cockpit/ws) now includes [cockpit-files](https://github.com/cockpit-project/cockpit-files/). When you log into a remote machine that does not have any Cockpit packages installed (package-less mode), the \"Files\" page is now available.\n\n## Package-less session for all supported operating systems\n\n[Cockpit 327](https://cockpit-project.org/blog/cockpit-327.html) introduced support for connecting to remote machines without any installed Cockpit packages. That only worked if the local and remote machine had the same operating system version. This version extends this \"package-less session\" feature to all operating systems which Cockpit [continuously tests](https://cockpit-project.org/running.html#installation--setup). At the time of writing this includes:\n\n  * Arch Linux\n  * CentOS Stream 9, 10\n  * Debian 12, testing/unstable\n  * Fedora Linux 40, 41, 42 (rawhide)\n  * Red Hat Enterprise Linux 8, 9, 10\n  * Ubuntu 22.04 LTS, 24.04 LTS, 24.10\n\nThis list will change over time, due to new distribution releases and the end of support for each version.\n\n## Overview: Show system boot in metrics\n\n![screenshot of ## show system boot in metrics]({{ site.baseurl }}/images/332-show-system-boot-in-metrics.png)\n\n## Machines: \"Launch viewer\" now uses correct address\n\nThe \"Launch viewer\" button in a virtual machine's \"Console\" card now uses the same address that Cockpit uses to connect to the virtual machine host. Previously, the button incorrectly attempted to connect to either the local machine where the browser is running (when the listening address was set to \"localhost\") or to an invalid \"0.0.0.0\" address (when configured to listen to all interfaces).\n\n## Podman: Automatically start podman.socket\n\nIf `podman.socket` is not already running on the system or user session, cockpit-podman will now automatically start the unit.  It is no longer necessary to manually start or enable the podman service.\n\n## Podman: Improve quadlet compatibility\n\nContainer-based services (aka: \"quadlets\") are now labeled with a \"service\" badge in the containers overview. Additionally, the option to rename quadlets has been removed, as renaming must take place in the systemd service `.container` file, which are often found in `/etc/containers/systemd/`.\n\n![screenshot of improved quadlet compatibility]({{ site.baseurl }}/images/332-podman-improve-quadlet-compatibility.png)\n\n## Files: Show user:group in the footer\n\nThe footer now shows the user and group of the current directory.\n\n![screenshot of group in the footer]({{ site.baseurl }}/images/332-files-show-user-group-in-the-footer.png)\n\n## Try it out\n\nCockpit 332, cockpit-machines 327, cockpit-podman 100, and cockpit-files 15 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/332)\n* [cockpit Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2025-a4f4852087)\n* [cockpit Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-6dcfdb7080)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/327)\n* [cockpit-machines Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-c1926a5602)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/100)\n* [cockpit-podman Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-2daeba9db7)\n* [cockpit-podman Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2025-40ecc431d1)\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/15)\n* [cockpit-files Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-5f545df041)\n* [cockpit-files Fedora 40](https://bodhi.fedoraproject.org/updates/FEDORA-2025-6b89f3e6c8)\n\n*[OS]: Operating System\n*[repo]: repository\n*[SSH]: Secure Shell, a common protocol to securely connect to a remote computer\n"
  },
  {
    "path": "_posts/2025-02-13-cockpit-333.md",
    "content": "---\ntitle: Cockpit 333\nauthor: lis\ndate: '2025-02-13'\ntags: podman, files\nslug: cockpit-333\ncategory: release\nsummary: 'various fixes, copy-paste ownership selection dialog'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 333 🥃, cockpit-podman 101, and cockpit-files 16:\n\n## Files: Copy/paste ownership prompt\n\nWhen logged in as administrator and copying files with a given owner to a\ndirectory with a different owner, cockpit-files will now prompt for the desired\nownership of the copied files.\n\n![screenshot of copy-paste file owner dialog]({{ site.baseurl }}/images/333-files-paste-as-user.png)\n\n## Try it out\n\nCockpit 333, cockpit-podman 101, and cockpit-files 16 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/333)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-5c1dd409e3)\n* [Cockpit Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-38d722541c)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/101)\n* [cockpit-podman Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-0fd5693fb4)\n* [cockpit-podman Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-21a1c28a7b)\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/16)\n* [cockpit-files Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-b516b763b4)\n* [cockpit-files Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-385c6ea642)\n"
  },
  {
    "path": "_posts/2025-02-27-cockpit-334.md",
    "content": "---\ntitle: Cockpit 334\nauthor: mvo\ndate: '2025-02-27'\ntags: files\nslug: cockpit-334\ncategory: release\nsummary: 'Cockpit Files improves keyboard shortcuts on Apple operating systems'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from cockpit-files 17:\n\n\n## Files: Apple-compatible keyboard shortcuts\n\nCockpit Files now properly supports command-based keyboard shortcuts, also known by the `⌘` symbol, fitting in better with macOS and portable Apple devices using a paired keyboard.\n\n![screenshot of apple-compatible keyboard shortcuts]({{ site.baseurl }}/images/334-files-apple-compatible-keyboard-shortcuts.png)\n## Try it out\n\ncockpit-files 17 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/17)\n* [cockpit-files Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-912cb7ac9b)\n* [cockpit-files Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-ee3ce50104)\n\n*[OS]: Operating System\n"
  },
  {
    "path": "_posts/2025-03-12-cockpit-335.md",
    "content": "---\ntitle: Cockpit 335\nauthor: pitti\ndate: '2025-03-12'\ntags: cockpit, machines\nslug: cockpit-335\ncategory: release\nsummary: 'SMART status, fixed remote VNC/SPICE launcher viewing'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 335 and cockpit-machines 329:\n\n\n## Storage: SMART device health\n\nThe Storage page now shows disk device health and can run disk self-check tests on demand.\n\n![smart1]({{ site.baseurl }}/images/335-storage-smart-device-health.png)\n\n![smart2]({{ site.baseurl }}/images/335-storage-smart-device-health-2.png)\n\n## Machines: Fix remote viewer launching\n\nThe \"Launch viewer\" button in Cockpit Machines now reliably launches \"virt-viewer\". The fix adds a generated filename to the `application/x-virt-viewer` helper file, resolving browser-specific launch issues. The filename also clarifies the file's purpose in the downloads folder.\n\n\n## Try it out\n\nCockpit 335 and cockpit-machines 329 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/335)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-5960de636e)\n* [Cockpit Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-a2a3389a48)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/329)\n* [cockpit-machines Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-a67966a7c9)\n* [cockpit-machines Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-fc11d9443e)\n"
  },
  {
    "path": "_posts/2025-04-17-cockpit-337.md",
    "content": "---\ntitle: Cockpit 337\nauthor: jelle\ndate: '2025-04-17'\ntags: cockpit, podman, files, machines, ostree\nslug: cockpit-337\ncategory: release\nsummary: 'Upgraded to PatternFly 6, software updates support needs-restarting, service links for podlet containers, multi-user support for rootless containers, symbolic link creation'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 337, cockpit-podman 104,\ncockpit-files 19, cockpit-machines 330, and cockpit-ostree 208:\n\n## A fresh new style, upgraded to PatternFly 6\n\nCockpit features a refreshed style, thanks to the latest major version of [PatternFly](https://www.patternfly.org/). This update replaces the previous \"industrial\" look with a more modern \"airy\" design, featuring even more rounded corners, fewer borders, and improved visual consistency. This release also includes numerous UI-related bug fixes.\n\nThe visual changes apply to the core Cockpit interface and all official plugins (including cockpit-files, cockpit-machines, cockpit-podman, and cockpit-ostree). We have tested the new look in both light and dark styles, verified accessibility, and confirmed compatibility with right-to-left (RTL) languages. We are happy with the state of the migration and are ready to share it with everyone.\n\nIf you do encounter any issue, [please file a bug report to let us know](https://github.com/cockpit-project/cockpit/issues/new?template=bug_report.yml)!\n\nFor plugin developers: We wrote [a guide for upgrading to PatternFly 6](https://github.com/cockpit-project/cockpit/discussions/21753).\n\n![screenshot of Cockpit overview with new Patternfly design]({{ site.baseurl }}/images/337-cockpit-with-patternfly-v6-light-mode.png)\n\n## Software updates: Support `dnf needs-restarting`\n\nOn CentOS Stream and Red Hat Enterprise Linux 10, the Software Updates page uses `dnf needs-restarting` to check if updates only need service restarts or require a full reboot. This replaces the `tracer` tool previously used in version 9.\n\n\n## Podman: Link service containers to service pages\n\nContainers managed by systemd link to the Services page, where these containers can be stopped or restarted.\n\n![screenshot of link to services page for service containers]({{ site.baseurl }}/images/337-podman-link-to-services-page-for-service-containers.png)\n\n## Podman: Connect to other accounts with containers\n\nAdministrators sometimes run services as unprivileged containers on other system user accounts, for isolation purposes. These system users typically don't have a password and thus one cannot log into Cockpit as a system user.\n\nWhen starting, Cockpit Podman scans the system for other accounts with running containers and provides a means to connect to Podman services on other accounts.\n\nNote that you can only connect to one account at a time, to avoid breaking isolation.\n\n![podman-multi-user-fs8]({{ site.baseurl }}/images/337-podman-connect-to-other-users-which-run-containers.png)\n\n\n## Files: Symbolic link creation\n\nCreate symbolic links (symlinks) for files and directories by right-clicking and selecting the `Create link` menu entry. Both relative and absolute path symlinks are supported.\n\n![screenshot of symlink creation support]({{ site.baseurl }}/images/337-files-symlink-creation-support.png)\n\n## Try it out\n\nCockpit 337, cockpit-podman 104, cockpit-files 19, cockpit-machines\n330, and cockpit-ostree 208 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/337)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-d7f3975f00)\n* [Cockpit Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-5b85462a70)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/104)\n* [cockpit-podman Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-bb1a30911b)\n* [cockpit-podman Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-1ae47ad43e)\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/19)\n* [cockpit-files Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-213f32d826)\n* [cockpit-files Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-647b86483e)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/330)\n* [cockpit-machines Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-dee77b3745)\n* [cockpit-machines Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-25ebbe5d20)\n* [cockpit-ostree Source Tarball](https://github.com/cockpit-project/cockpit-ostree/releases/tag/208)\n* [cockpit-ostree Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-ee441b0482)\n* [cockpit-ostree Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-88604f3995)\n\n*[OS]: Operating System\n*[RHEL]: Red Hat Enterprise Linux\n"
  },
  {
    "path": "_posts/2025-05-21-cockpit-339.md",
    "content": "---\ntitle: Cockpit 339\nauthor: tmatus\ndate: '2025-05-21'\ntags: cockpit, podman, files, machines, ostree\nslug: cockpit-339\ncategory: release\nsummary: 'Cockpit-ws arm64 container, warn on SMART failures, Cockpit no longer modifies the \"shareable\" attribute of disks'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 339, cockpit-podman 106,\ncockpit-files 21, cockpit-machines 332, and cockpit-ostree 210:\n\n## Add cockpit/ws arm64 container\n\nThe [cockpit webserver container image](https://quay.io/repository/cockpit/ws?tab=info) is now available for the arm64 architecture as well.\n\n_Thanks to Marvin Ruder for this contribution!_\n\n## Storage: Disk Self-Test error warnings\n\nThe health card on the overview page now provides proactive warnings when a disk reports errors from its SMART self-test.\n\n![smart]({{ site.baseurl }}/images/339-overview-smart-warning.png)\n\n## Machines: The \"shareable\" attribute of disks is no longer modified by Cockpit\n\nBy default, libvirt can attach a disk to multiple virtual machines, but if the disk allows writing, only a single one of these machines\ncan be running at a given time. Writing to a disk concurrently from multiple VMs at the same time can easily lead to data corruption,\nand libvirt prevents this unless the \"shareable\" attribute of a disk is set. Previously, Cockpit would set this attribute by default\nand would thus invite data corruption. To avoid this, Cockpit no longer marks disks as \"shareable\" when attaching them to multiple VMs.\n\nMoreover, the \"Edit attributes\" dialog no longer allows setting the \"shareable\" attribute either.\nWe now believe this attribute is too dangerous to be exposed in such an easy way. If you really need it,\nyou can use \"virt-xml\" on the command line.\nCockpit will show disks with the \"shareable\" attribute as \"Concurrently writable\" in the UI.\n\n## Try it out\n\nCockpit 339, cockpit-podman 106, cockpit-files 21, cockpit-machines\n332, and cockpit-ostree 210 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/339)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-b414ded6de)\n* [Cockpit Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-dc44e3ebf2)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/106)\n* [cockpit-podman Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-33e26f7c12)\n* [cockpit-podman Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-e867161328)\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/21)\n* [cockpit-files Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-3136f15eb8)\n* [cockpit-files Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-332f1df14a)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/332)\n* [cockpit-machines Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-ef270f0390)\n* [cockpit-machines Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-065f8865d6)\n* [cockpit-ostree Source Tarball](https://github.com/cockpit-project/cockpit-ostree/releases/tag/210)\n* [cockpit-ostree Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-cca579c4b9)\n* [cockpit-ostree Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-e28678da70)\n"
  },
  {
    "path": "_posts/2025-06-04-cockpit-340.md",
    "content": "---\ntitle: Cockpit 340\nauthor: Venefilyn\ndate: \"2025-06-04\"\ntags: cockpit, podman, files, machines, ostree\nslug: cockpit-340\ncategory: release\nsummary: \"Handle unsupported storage partitions, link quadlet logs to their service, source mode for virtual networks, various UX improvements.\"\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 340, cockpit-podman 107, cockpit-machines 333, and cockpit-ostree 211:\n\n## Storage: Prevent modifying unsupported partitions\n\nCockpit now detects unsupported partitions and displays a notice that Cockpit does not support it, such as modifying LVM2 Logical Volume partitions.\n\n![Screenshot showing a notice inside a GPT partitions card saying \"Unexpected partitions\" in bold, followed by a description saying \"Partitions are not supported on this block device. If it is used as a disk for a virtual machine, the partitions must be managed by the operating system inside the virtual machine.\"]({{ site.baseurl }}/images/340-storage-unsupported-partitions.png)\n\n## Storage: Rename safety warning\n\nWe now display a warning when renaming volume groups that contain the root filesystem as it might break the next boot.\n\n\n## Podman: Quadlet log links\n\nQuadlet logs now link to their systemd service log page counterpart.\n\n![An image of a podman logs page for a container called \"systemd-test\" below the black logs box is a link saying \"View test.service logs\".]({{ site.baseurl }}/images/340-quadlet-service-logs-link.png)\n\n## Machines: Virtual network interfaces can now select source mode\n\nWhen adding a new virtual network interface you can now select between VEPA, Bridge, Private, or Passthrough for more flexibility with how machines are exposed to the network.\n\n![Screenshot showing off new form selection, it includes an information button for \"Source\" as well as a radio button to select either VEPA, Bridge, Private, or Passthrough.]({{ site.baseurl }}/images/340-machines-network-source-mode.png)\n\n## Try it out\n\nCockpit 340, cockpit-podman 107, cockpit-files 22, cockpit-machines\n334, and cockpit-ostree 211 are available now:\n\n- [For your Linux system](https://cockpit-project.org/running.html)\n- [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n- [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/340)\n- [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-a98d1623db)\n- [Cockpit Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-df18134211)\n- [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/107)\n- [cockpit-podman Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-4f9690891e)\n- [cockpit-podman Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-0ef740783b)\n- [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/22)\n- [cockpit-files Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-52fec1350b)\n- [cockpit-files Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-f17103754e)\n- [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/333)\n- [cockpit-machines Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-4b565877e8)\n- [cockpit-machines Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-0a3e74f882)\n- [cockpit-ostree Source Tarball](https://github.com/cockpit-project/cockpit-ostree/releases/tag/211)\n- [cockpit-ostree Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-932df9a178)\n- [cockpit-ostree Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-4029d213a0)\n"
  },
  {
    "path": "_posts/2025-06-25-cockpit-341.md",
    "content": "---\ntitle: Cockpit 341\nauthor: jelle\ndate: '2025-06-25'\ntags: cockpit\nslug: cockpit-341\ncategory: release\nsummary: 'link to podman quadlet containers'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 341 and Cockpit-podman 108:\n\n\n## services: show link to podman page for quadlets\n\nThe Services page now recognizes [podman quadlets](https://www.redhat.com/en/blog/quadlet-podman) and shows a link to the Podman containers page.\n\nThe link is only shown when cockpit-podman ≥ 108 is installed.\n\n![screenshot of show link to podman page for quadlets]({{ site.baseurl }}/images/341-services-show-link-to-podman-page-for-quadlets.png)\n\n\n## Try it out\n\nCockpit 341 and Cockpit-podman 108 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/108)\n* [Cockpit-podman Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-30d0320ad2)\n* [Cockpit-podman Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-86e2865795)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/341)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-3bcc30f5f0)\n* [Cockpit Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-4bc30a6154)\n"
  },
  {
    "path": "_posts/2025-07-23-cockpit-343.md",
    "content": "---\ntitle: Cockpit 343\nauthor: tmatus\ndate: \"2025-07-23\"\ntags: cockpit, machines\nslug: cockpit-343\ncategory: release\nsummary: \"Improved VNC and serial consoles\"\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 343 and cockpit-machines 336:\n\n## Machines: Graphical VNC and serial consoles have been improved\n\nIt is now easier to switch between these two console types, and also easier to launch a remote viewer. Cockpit can now add VNC and serial consoles to machines that are missing them, and can change the port and password of the VNC servers of individual machines.\n\n![Screenshot showing improved VNC view and includes new \"Launch viewer\" button.]({{ site.baseurl }}/images/343-machines-graphical-vnc-and-serial-console-improvements.png)\n\n## Machines: Control VNC console resizing and scaling\n\nYou can now explicitly control the graphical console's resizing and scaling behaviour in expanded mode:\n * \"No scaling or resizing\" gets you an 1-to-1 pixel perfect view of a remote desktop, but possibly with scrollbars, depending on the browser window size.\n * \"Local scaling\" scales the console in the browser and thus is compatible with small browser windows and large remote resolutions, but is harder to read.\n * \"Remote resizing\" asks the remote machine to set a native resolution that matches Cockpit's console view. This keeps crisp graphics, but may not be compatible with all operating systems.\n\n![Screenshot showing new resize behavior selection.]({{ site.baseurl }}/images/343-machines-control-vnc-console-resizing-and-scaling.png)\n\n## Try it out\n\nCockpit 343 and cockpit-machines 336 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/343)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-2835cbf11f)\n* [Cockpit Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-8eb80e9a6f)\n- [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/110)\n- [cockpit-podman Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-88cbcd7fc5)\n- [cockpit-podman Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-225466f39e)\n- [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/25)\n- [cockpit-files Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-f5529c387a)\n- [cockpit-files Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-0f80a559d5)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/336)\n* [cockpit-machines Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-585cb79d47)\n* [cockpit-machines Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-200ccd6d0b)\n- [cockpit-ostree Source Tarball](https://github.com/cockpit-project/cockpit-ostree/releases/tag/212)\n- [cockpit-ostree Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-d9248ea49d)\n- [cockpit-ostree Fedora 41](https://bodhi.fedoraproject.org/updates/FEDORA-2025-0f38827a47)\n\n"
  },
  {
    "path": "_posts/2025-08-19-cockpit-345.md",
    "content": "---\ntitle: Cockpit 345\nauthor: mvo\ndate: '2025-08-19'\ntags: cockpit, machines\nslug: cockpit-345\ncategory: release\nsummary: 'IPv6 for Wireguard, detachable VNC console'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 345 and cockpit-machines 338:\n\n\n## Networking: Support IPv6 addresses for WireGuard\n\nThe Networking page can now configure IPv6 addresses for WireGuard VPN\ndirectly within the WireGuard modal.\n\n![image](/images/345-wireguard-ipv6.png)\n\n## Machines: Allow pop-out of VNC console viewer\n\nYou can now detach the VNC console viewer of a virtual machine into\nits own window.\n\n![image](/images/345-vnc-detach.png)\n\n## Try it out\n\nCockpit 345 and cockpit-machines 338 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/345)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/?releases=F42&packages=cockpit)\n* [Cockpit Fedora 41](https://bodhi.fedoraproject.org/updates/?releases=F41&packages=cockpit)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/338)\n* [cockpit-machines Fedora 42](https://bodhi.fedoraproject.org/updates/?releases=F42&packages=cockpit-machines)\n* [cockpit-machines Fedora 41](https://bodhi.fedoraproject.org/updates/?releases=F41&packages=cockpit-machines)\n"
  },
  {
    "path": "_posts/2025-09-03-cockpit-346.md",
    "content": "---\ntitle: Cockpit 346\nauthor: pitti\ndate: '2025-09-03'\ntags: cockpit, machines, podman\nslug: cockpit-346\ncategory: release\nsummary: 'Stratis V2 pools, branding support, serial console improvements, sortable Podman images table'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 346, cockpit-machines 339, and cockpit-podman 113:\n\n\n## Storage: Support for Stratis \"V2\" pools\n\nStratis 3.8 and newer will create pools with a new metadata format that allows multiple passphrases and keyservers. Cockpit now supports this new format.\n\n![screenshot of support for stratis \"v2\" pools]({{ site.baseurl }}/images/346-storage-support-for-stratis-v2-pools.png)\n\n## Support branding Cockpit pages\n\nCockpit's [branding CSS](https://github.com/cockpit-project/cockpit/blob/main/doc/branding.md) so far only applied to the Login page and the Shell. With this version it gets applied to all Cockpit pages. This allows distributors more customization possibilities, such as changing [PatternFly brand colors](https://www.patternfly.org/design-foundations/colors/#brand-colors).\n\n## Machines: Serial consoles now keep their content and stay alive\n\nCockpit Machines used to lose the content of a serial console when navigating away from a virtual machine, and it would be empty when returning to it later. Now the content will be preserved and the console will also pick up output that happened while the console was not visible.\n\n## Machines: No longer copies qemu.conf values into VM definitions\n\nPreviously, Cockpit would copy the listening address and passwords for VNC and SPICE from the global qemu.conf configuration file into the definitions of new virtual machines.\n\nThis had the undesired effect that changes to qemu.conf made after these machines were created would not take effect for them.\n\nCockpit no longer does this. New machines will be created with no extra configuration for their VNC and SPICE devices, and thus the values in qemu.conf will be applied on each start of these machines.\n\n## Podman: Sortable Images table\n\nYou can now sort the images table by any column.\n\n![screenshot of image sorting]({{ site.baseurl }}/images/346-podman-images-sort.png)\n\n_Thanks to `@rare-magma` for this contribution!_\n\n\n## Try it out\n\nCockpit 346, cockpit-machines 339, and cockpit-podman 113 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/346)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-c0e84e0264)\n* [Cockpit Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-ca5be198f5)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/339)\n* [cockpit-machines Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-282bc8c2fc)\n* [cockpit-machines Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-d71fdc4160)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/113)\n* [cockpit-podman Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-608064958e)\n* [cockpit-podman Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-8af7fb9fdf)\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "_posts/2025-09-17-cockpit-347.md",
    "content": "---\ntitle: Cockpit 347\nauthor: lis\ndate: '2025-09-17'\ntags: cockpit, machines\nslug: cockpit-347\ncategory: release\nsummary: 'site-specific branding support, exclusive VNC connections'\n\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 347 and cockpit-machines 340:\n\n\n## Site-specific branding support\n\nAdministrators can provide a custom local [branding](https://github.com/cockpit-project/cockpit/blob/main/doc/branding.md) in `/etc/cockpit/branding/` (more generally, `$XDG_CONFIG_DIRS/cockpit/branding/`). If that directory exists, it is considered before the system package branding directories in /usr.\n\n## Machines: Exclusive VNC connections with \"Remote resizing\"\n\nA VNC viewer can tell the VNC server whether or not it wants exclusive access to it, or whether it is okay that multiple viewers display and interact with the same console. Until now, Cockpit has always allowed shared access when it connects.\n\nNow, Cockpit will request exclusive access when it is in the \"Remote resizing\" mode, to avoid having multiple viewers make conflicting resize requests.\n\nThis feature requires the web server from Cockpit 346.\n\n\n## Try it out\n\nCockpit 347 and cockpit-machines 340 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/347)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-c9141544b1)\n* [Cockpit Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-c872b517de)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/340)\n* [cockpit-machines Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-aec8bbe6a2)\n* [cockpit-machines Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-6fb0e8d24f)\n"
  },
  {
    "path": "_posts/2025-10-02-cockpit-348.md",
    "content": "---\ntitle: Cockpit 348\nauthor: Venefilyn\ndate: '2025-10-02'\ntags: cockpit, machines, ostree, files, podman\nslug: cockpit-348\ncategory: release\nsummary: 'improved table UX for machines'\n\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from cockpit-machines 341:\n\n## Machines: Improved UX for Disks and Network interface tables\n\nLooking at a Virtual Machine's available disks or the designated network interfaces there was too much detail being displayed, causing unintended wrapping and making some parts impossible to read with certain screen resolutions.\n\nTo alleviate this we have changed the UI around to showcase only the most important information a user would want and hid the rest within an expandable section.\n\n![screenshot of disks table expanded]({{ site.baseurl }}/images/348-machines-nics-disks-ux.png)\n\nAll the information we had prior to this change is still here, but in a much easier to read design.\n \n![screenshot of disks table expanded]({{ site.baseurl }}/images/348-machines-disks-ux-expand.png)\n\n![screenshot of network interfaces table expanded]({{ site.baseurl }}/images/348-machines-nics-ux-expand.png)\n\n## Try it out\n\nCockpit 348, cockpit-podman 114, cockpit-files 29, cockpit-machines\n341, and cockpit-ostree 215 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/348)\n* [Cockpit Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-3d16d96da4)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-101cb80f79)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/114)\n* [cockpit-podman Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-e8cbff319b)\n* [cockpit-podman Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-a767f40e58)\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/29)\n* [cockpit-files Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-4221c954d3)\n* [cockpit-files Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-a4241fced1)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/341)\n* [cockpit-machines Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-24e36e8212)\n* [cockpit-machines Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-377be8f9c1)\n* [cockpit-ostree Source Tarball](https://github.com/cockpit-project/cockpit-ostree/releases/tag/215)\n* [cockpit-ostree Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-70eabb049a)\n* [cockpit-ostree Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-94d94f6bd6)\n"
  },
  {
    "path": "_posts/2025-10-15-cockpit-349.md",
    "content": "---\ntitle: Cockpit 349\nauthor: tmatus\ndate: '2025-10-15'\ntags: cockpit, machines, ostree, files, podman\nslug: cockpit-349\ncategory: release\nsummary: 'manifest \"any\" condition and list inactive podman quadlests'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 349, and cockpit-podman 115:\n\n## Package manifests: Add `any` test\n\n[Package manifests](https://cockpit-project.org/guide/latest/packages.html#package-manifest) can have a list of conditions.\nCockpit will only consider the package if *all* conditions are met. This release introduces an operator for alternative checks in a condition, for example\n\n```json\n\"conditions\": [\n    {\"any\": [{\"path-exists\": \"…/packagekit.service\"}, {\"path-exists\": \"…/dnfdaemon.service\"}]}\n]\n```\n\nThat condition will be true if at least one of its subconditions matches.\n\n## List stopped quadlets\n\nQuadlets are a declarative way to define podman pods/containers using systemd-like configuration files.\nThese podman containers/pods are ephemeral and previously disappeared from cockpit-podman when stopped.\n\nWith this release, cockpit-podman can now detect stopped quadlets on the system for the logged in user and superuser.\nThe quadlets are shown as normal \"inactive\" pods/containers. In the future, lifecycle actions such as start/stop/restart will be added.\n\n![screenshot of inactive podman quadlet]({{ site.baseurl }}/images/349-inactive-podman-quadlet.png)\n\n## Try it out\n\nCockpit 349, cockpit-podman 115, cockpit-files 30, cockpit-machines 342,\nand cockpit-ostree 216 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/349)\n* [Cockpit Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-5afa4ee846)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-5fd1666bcf)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/115)\n* [cockpit-podman Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-1404566a88)\n* [cockpit-podman Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-23dc695301)\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/30)\n* [cockpit-files Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-31b88a9163)\n* [cockpit-files Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-0b96fa8cfe)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/342)\n* [cockpit-machines Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-a4660c2f88)\n* [cockpit-machines Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-eacacb4046)\n* [cockpit-ostree Source Tarball](https://github.com/cockpit-project/cockpit-ostree/releases/tag/216)\n* [cockpit-ostree Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-e431550108)\n* [cockpit-ostree Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-37d8669702)\n"
  },
  {
    "path": "_posts/2025-10-29-cockpit-350.md",
    "content": "---\ntitle: Cockpit 350\nauthor: jelly\ndate: '2025-10-29'\ntags: machines, podman\nslug: cockpit-350\ncategory: release\nsummary: 'more accurate virtual machine memory usage and podman quadlet lifecycle action support'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from cockpit-machines 343 and cockpit-podman 116:\n\n\n## Machines: Memory usage now shows numbers reported by the guest\n\nThe memory usage bars now show the same numbers as tools like \"top\" and \"free\" when run inside the guest. Specifically, the memory usage shown by Cockpit is based on the \"MemAvailable\" number of the guest kernel.\n\nTo implement this, Cockpit will run `virsh dommemstat <vm name> --period 10 --life`. If that is not acceptable, please let us know.\n\n## Support stopping/starting/restarting quadlets\n\nQuadlets now have lifecycle operations such as \"Start\". These use systemd operations instead of podman's API.\n\n![screenshot of an inactive podman quadlet with stop/restart actions]({{ site.baseurl }}/images/350-support-stopping-starting-restart-quadlets.png)\n\n## Try it out\n\ncockpit-machines 343 and cockpit-podman 116 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/343)\n* [cockpit-machines Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-9c96b216aa)\n* [cockpit-machines Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-e3ae7fd76d)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/116)\n* [cockpit-podman Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-9ac6e67a12)\n* [cockpit-podman Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-8d9c58de31)\n\n*[API]: Application Programming Interface\n*[repo]: repository\n"
  },
  {
    "path": "_posts/2025-11-11-cockpit-351.md",
    "content": "---\ntitle: Cockpit 351\nauthor: mvo\ndate: '2025-11-11'\ntags: cockpit, machines\nslug: cockpit-351\ncategory: release\nsummary: 'deleting firewall ports, restarting VMs, forwarding ports'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 351, and cockpit-machines 344:\n\n\n## Firewall: Additional ports can now be deleted\n\n\"Additional ports\" in a firewall zone are now listed each in their\nindividual row, and can be individually deleted.\n\nThanks a lot libkurisu for this contribution!\n\n![screenshot of additional firewall ports]({{ site.baseurl }}/images/351-firewall-ports.png)\n\n## Machines: VMs can be shutdown and restarted with a single action\n\nSome changes to a virtual machine, such as adding VNC graphics, require it to be completely shut down and restarted before these changes take effect. Cockpit can now do this with a single action.\n\n![screenshot of the \"Shutdown and Restart\" dialog]({{ site.baseurl }}/images/351-shutdown-restart.png)\n\n## Machines: Support for network port forwarding\n\nCockpit can now configure port forwarding for virtual machines on the user session.\n\n![screenshot of the port forwarding dialog]({{ site.baseurl }}/images/351-passt.png)\n\n## Try it out\n\nCockpit 351, cockpit-machines 344, and cockpit-podman 117 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/351)\n* [Cockpit Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-5e7212a181)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-20d5cb0e41)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/344)\n* [cockpit-machines Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-a175bcd6cd)\n* [cockpit-machines Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-90b61e1f6b)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/117)\n* [cockpit-podman Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-feea0649ba)\n* [cockpit-podman Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-fcec857391)\n"
  },
  {
    "path": "_posts/2025-11-26-cockpit-352.md",
    "content": "---\ntitle: Cockpit 352\nauthor: Venefilyn\ndate: '2025-11-26'\ntags: cockpit, machines\nslug: cockpit-352\ncategory: release\nsummary: 'warning for unclean shutdown, disable SPICE by default'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 352 and cockpit-machines 345:\n\n## Show a warning if the last shutdown/reboot was unclean\n\nCockpit's healtchard will now show warning when the system was shutdown uncleanly. \n\n![screenshot of shown a warning if the last shutdown/reboot was unclean]({{ site.baseurl }}/images/352-shown-a-warning-if-the-last-shutdown-reboot-was-unclean.png)\n\n## Machines: New virtual machines don't get SPICE graphics anymore\n\nCockpit used to add both VNC and SPICE graphics when creating new virtual machines. Now only VNC graphics are added. We have made this change since Cockpit itself does not benefit from SPICE graphics, and we think that opening the SPICE port for a running machine should be intentional on part of the user and not happen silently and surprisingly.\n\n## Try it out\n\nCockpit 352 and cockpit-machines 345 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/352)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/345)\n* [cockpit-machines Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-df0de54f21)\n* [cockpit-machines Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-07ca1e97a5)\n"
  },
  {
    "path": "_posts/2025-12-10-cockpit-353.md",
    "content": "---\ntitle: Cockpit 353\nauthor: tmatus\ndate: '2025-12-10'\ntags: cockpit\nslug: cockpit-353\ncategory: release\nsummary: 'smarter IP configuration'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 353:\n\n\n## Networking: Suggest prefix length and gateway address\n\nIPv4 and IPv6 configuration dialogs now automatically pre-fill network prefix length and default gateway.\nPrefix length defaults to classful addressing in IPv4 and /64 prefix is suggested for IPv6.\nClassless addressing is fully supported and manual overrides are available, the default gateway is calculated as the first usable address of the subnet.\n\n\n## Try it out\n\nCockpit 353 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/353)\n* [Cockpit Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2025-b1f425c47c)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2025-9139c48acb)\n"
  },
  {
    "path": "_posts/2026-01-29-cockpit-355.md",
    "content": "---\ntitle: Cockpit 355\nauthor: jelle\ndate: '2026-01-29'\ntags: cockpit\nslug: cockpit-355\ncategory: release\nsummary: 'systemd/polkit based fallback for administrative privileges and pam_cockpit_cert removal'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 355:\n\n\n## Add systemd/polkit-based fallback for administrative privileges if sudo is not available\n\nThere are systems like [Ubuntu 25.10](https://github.com/cockpit-project/cockpit/issues/22811) which don't have `sudo`, or only the [incompatible `sudo-rs`](https://github.com/trifectatechfoundation/sudo-rs/issues/1249). Cockpit previously failed to gain administrator rights then. Cockpit 355 now both detects and ignores an incompatible `sudo`, as well as introduces a fallback authentication method: It starts the root bridge through systemd's `StartTransientUnit()` API. This is inspired by systemd's [run0](https://man7.org/linux/man-pages/man1/run0.1.html), and uses the exact same underlying mechanism. This is guarded by [polkit](https://polkit.pages.freedesktop.org/polkit/polkit.8.html), so you need to authorize with your user password similar to `sudo`.\n\n## ws: Remove obsolete pam_cockpit_cert module\n\nCockpit version 209 (Dec 2019) introduced a `pam_cockpit_cert` PAM module in /etc/pam.d/cockpit. Cockpit 248 (Jul 2021) made this module unnecessary, and replaced the module with a stub that did not do anything, plus a warning during package upgrade.\n\nThis version finally removes it. So if you have locally modified `/etc/pam.d/cockpit` and still have that module in your configuration, you need to manually remove it.\n\n\n## Try it out\n\nCockpit 355 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/355)\n* [Cockpit Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2026-f6bf111f25)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2026-a003231b69)\n\n*[API]: Application Programming Interface\n"
  },
  {
    "path": "_posts/2026-02-11-cockpit-356.md",
    "content": "---\ntitle: Cockpit 356\nauthor: mvo\ndate: '2026-02-11'\ntags: cockpit\nslug: cockpit-356\ncategory: release\nsummary: 'Cockpit updates systemd timers to run commands via /bin/sh and allows editing timers created in Cockpit.'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 356:\n\n\n## Services: Timers created by Cockpit run shell commands and can be edited\n\nThe systemd timer units created by Cockpit now run their command via\nthe shell. Previously, the text you entered into the \"Command\" field\nwas used directly for the ExecStart value in the systemd service unit\nfor the timer, and was thus subject to systemd specifier expansion and\nother idiosyncrasies. Now the text you enter is executed directly by `/bin/sh`.\n\nSystemd timer units that have been created by this version of Cockpit\n(or later) can now also be edited in Cockpit.\n\nThanks to [Miguel Ribeiro](https://github.com/miguelbribeiro) for contributing this feature!\n\n\n## Try it out\n\nCockpit 356 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/356)\n* [Cockpit Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2026-e56f80347a)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/FEDORA-2026-fc46ffaa92)\n"
  },
  {
    "path": "_posts/2026-02-25-cockpit-357.md",
    "content": "---\ntitle: Cockpit 357\nauthor: lis\ndate: '2026-02-25'\ntags: machines, podman\nslug: cockpit-357\ncategory: release\nsummary: 'extra args for VMs, context menu hijacking avoidance'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 357, cockpit-files 37, cockpit-machines 350 and cockpit-podman 123:\n\n## Show browser context menu when holding `Shift`\n\nTo help with accessibility and user-specific items in your browser context menu we now follow the behavior seen\nin Firefox: holding the `Shift` key while right-clicking will skip our own context menu and instead follow the\ndefault behavior of your browser. Note that while Cockpit Files uses the Cockpit context menu it did not\nreceive this update before the release, but will get it for the for next one.\n\n## Machines: Support for kernel boot arguments when creating VMs\n\nCockpit now supports the `--extra-args` option of `virt-install`. This allows you to pass arguments to the\nkernel when the installer is booted during the creation of a new virtual machine. Installers like Anaconda and\nAgama can be controlled in various ways via these arguments.\n\nThanks to [Nykseli](https://github.com/Nykseli) for this contribution!\n\n## Podman: Show description, version and documentation image labels\n\nThe image details tab now shows a select set of labels from the [OpenContainers Annotations\nspecification](https://specs.opencontainers.org/image-spec/annotations/).\n\n![screenshot of show description, version, and documentation image labels]({{ site.baseurl }}/images/357-podman-show-details.png)\n\n## Try it out\n\nCockpit 357, cockpit-files 37, cockpit-machines 350 and cockpit-podman 123 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/357)\n* [Cockpit Fedora 43](https://bodhi.fedoraproject.org/updates/?releases=F43&packages=cockpit)\n* [Cockpit Fedora 42](https://bodhi.fedoraproject.org/updates/?releases=F42&packages=cockpit)\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/37)\n* [cockpit-files Fedora 43](https://bodhi.fedoraproject.org/updates/?releases=F43&packages=cockpit-files)\n* [cockpit-files Fedora 42](https://bodhi.fedoraproject.org/updates/?releases=F42&packages=cockpit-files)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/350)\n* [cockpit-machines Fedora 43](https://bodhi.fedoraproject.org/updates/?releases=F43&packages=cockpit-machines)\n* [cockpit-machines Fedora 42](https://bodhi.fedoraproject.org/updates/?releases=F42&packages=cockpit-machines)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/123)\n* [cockpit-podman Fedora 43](https://bodhi.fedoraproject.org/updates/?releases=F43&packages=cockpit-podman)\n* [cockpit-podman Fedora 42](https://bodhi.fedoraproject.org/updates/?releases=F42&packages=cockpit-podman)\n\n*[VMs]: Virtual Machines\n"
  },
  {
    "path": "_posts/2026-03-18-cockpit-358.md",
    "content": "---\ntitle: Cockpit 358\nauthor: tmatus\ndate: '2026-03-18'\ntags: cockpit, files\nslug: cockpit-358\ncategory: release\nsummary: 'Cockpit Client updated to GTK 4; Wi-Fi support in Networking; confirmation prompt when discarding file edits'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 358 and cockpit-files 38:\n\n\n## Cockpit Client updated to GTK 4\n\nThe Cockpit Client has been updated to GTK 4 and WebKit 6, making it easier to enable support for downloads from Cockpit Files.\n\n![screenshot of cockpit client updated to gtk 4]({{ site.baseurl }}/images/358-cockpit-client-updated-to-gtk-4.png)\n\n## Networking: Add Wi-Fi support\n\nIf there are any Wi-Fi devices, the Networking page overview shows the number of available networks and the currently connected network.\n\n![screenshot of add wi-fi support]({{ site.baseurl }}/images/358-networking-add-wi-fi-support.png)\n\nThe details page shows a table of available networks with mode/security, signal strength, and rate. The currently active connection (if any) is always at the top. It is followed by known networks, and then unknown networks sorted by descending signal strength. You can connect, disconnect, and forget networks.\n\n![screenshot of add wi-fi support]({{ site.baseurl }}/images/358-networking-add-wi-fi-support-2.png)\n\n## Files: Add confirmation prompt for discarding changes \n\nWhen editing files, Cockpit will now show a confirmation dialog when clicking away, hitting cancel, or pressing escape. This prevents accidentally discarding changes and losing data.\n\n![screenshot of add confirmation prompt for discarding changes]({{ site.baseurl }}/images/358-files-add-confirmation-prompt-for-discarding-changes-.png)\n\nThanks to [Leone25](https://github.com/Leone25) for this contribution!\n\n\n## Try it out\n\nCockpit 358, cockpit-files 38, cockpit-machines 350 and cockpit-podman 123 are available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/358)\n* [Cockpit Fedora 44](https://bodhi.fedoraproject.org/updates/FEDORA-2026-7c755914c5)\n* [Cockpit Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2026-14b2e886fa)\n* [cockpit-files Source Tarball](https://github.com/cockpit-project/cockpit-files/releases/tag/38)\n* [cockpit-files Fedora 44](https://bodhi.fedoraproject.org/updates/FEDORA-2026-a45efa88da)\n* [cockpit-files Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2026-04a26eaf54)\n* [cockpit-machines Source Tarball](https://github.com/cockpit-project/cockpit-machines/releases/tag/350)\n* [cockpit-machines Fedora 44](https://bodhi.fedoraproject.org/updates/FEDORA-2026-9bb66b2a31)\n* [cockpit-machines Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2026-55cfacb748)\n* [cockpit-podman Source Tarball](https://github.com/cockpit-project/cockpit-podman/releases/tag/123)\n* [cockpit-podman Fedora 44](https://bodhi.fedoraproject.org/updates/FEDORA-2026-d4f1131072)\n* [cockpit-podman Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2026-fb1e8eb986)\n\n"
  },
  {
    "path": "_posts/2026-04-08-cockpit-360.md",
    "content": "---\ntitle: Cockpit 360\nauthor: tmatus\ndate: '2026-04-08'\ntags: 'cockpit'\nslug: cockpit-360\ncategory: release\nsummary: 'CVE-2026-4631 ws SSH vulnerability'\n---\n\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from Cockpit 360:\n\n## ws: Prevent remote code execution with SSH argument injection [CVE-2026-4631]\n\n### Impact\n\nCockpit's remote login feature passes user-supplied hostnames and usernames from\nthe web interface to the SSH client without validation or sanitization.\nAn attacker with network access to the Cockpit web service can craft a single\nHTTP request to the login endpoint that injects malicious SSH options or shell\ncommands, achieving code execution on the Cockpit host without valid credentials.\nThe injection occurs during the authentication flow before any credential\nverification takes place, meaning no login is required to exploit the vulnerability.\n\n### Affected systems\n\nThe affected Cockpit versions are Cockpit 326 up to and including Cockpit 359. (cockpit >= 326, cockpit <= 359)\n\nThis is tracked as [CVE-2026-4631](https://www.cve.org/CVERecord?id=CVE-2026-4631).\n\n### Fix\n\n- Upgrade to **Cockpit version 360** to fix this issue.\n- The [official Debian patch](https://salsa.debian.org/utopia-team/cockpit/-/blob/trixie/debian/patches/ws-be-more-explicit-when-handling-hostnames-on-cli.patch)\nincludes all required changes and is applicable to recent Cockpit versions.\n- You can alternatively backport the following patches:\n    - [https://github.com/cockpit-project/cockpit/commit/9d0695647cb6f6209e68231fd165917123aa502d](https://github.com/cockpit-project/cockpit/commit/9d0695647cb6f6209e68231fd165917123aa502d)\n    - [https://github.com/allisonkarlitskaya/ferny/commit/44ec511c99](https://github.com/allisonkarlitskaya/ferny/commit/44ec511c99)\n\n### Workarounds\n\nA workaround is disabling [LoginTo](https://cockpit-project.org/guide/latest/cockpit.conf.5) option in cockpit.conf,\nthis disables the direct login feature but it is still strongly recommended to upgrade to Cockpit 360.\n\n### Acknowledgments\n\nMany thanks to Florian Kohnhäuser for reporting this issue!\n\n## Try it out\n\nCockpit 360 is available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\n* [Cockpit Source Tarball](https://github.com/cockpit-project/cockpit/releases/tag/360)\n* [Cockpit Fedora 44](https://bodhi.fedoraproject.org/updates/FEDORA-2026-bbc8f7695a)\n* [Cockpit Fedora 43](https://bodhi.fedoraproject.org/updates/FEDORA-2026-42f1aaa820)\n"
  },
  {
    "path": "_scripts/container-create",
    "content": "#!/bin/bash -e\n\nin_toolbox=/run/.containerenv\n\nif [ -f $in_toolbox ]; then\n  podman=\"flatpak-spawn --host env podman\"\nelse\n  podman=\"env podman\"\nfi\n\necho \"## Creating website container...\"\n# Use GitHub's official pages container as a base\n# but use local .gem directory (which will be mounted in /src/site)\ncat <<'EOF' | $podman build -t cockpit-website --pull -\nFROM ghcr.io/github/pages-gem\nRUN bundle config path /src/site/.gem\nEOF\n\n\"$(dirname \"$0\")\"/container-update-gems\n"
  },
  {
    "path": "_scripts/container-delete",
    "content": "#!/bin/bash -e\n\nin_toolbox=/run/.containerenv\n\nif [ -f $in_toolbox ]; then\n  podman=\"flatpak-spawn --host env podman\"\nelse\n  podman=\"env podman\"\nfi\n\ncontainer_exists=$( $podman container exists cockpit-website )\n\nif [[ -n $container_exists ]]; then\n  echo \"## Removing local .gem directory...\"\n  \"$(dirname \"$0\")\"/container-run rm -rf .gem\n  echo \"## Deleting Cockpit website container...\"\n  $podman rmi -f cockpit-website\n  echo \"## Done! \"\nelse\n  echo \"## Container does not exist\"\nfi\n"
  },
  {
    "path": "_scripts/container-jekyll",
    "content": "#!/bin/bash -e\n\n\"$(dirname \"$0\")\"/container-run bundle exec jekyll server -H 0.0.0.0 \"$*\"\n"
  },
  {
    "path": "_scripts/container-ruby",
    "content": "#!/bin/sh -e\n\n\"$(dirname \"$0\")\"/container-run sh -c \"bundle exec ruby $*\"\n"
  },
  {
    "path": "_scripts/container-run",
    "content": "#!/bin/bash -e\n\nin_toolbox=/run/.containerenv\n\nif [ -f $in_toolbox ]; then\n  podman=\"flatpak-spawn --host env podman\"\nelse\n  podman=\"env podman\"\nfi\n\ncontainer_exists=$( $podman images -q cockpit-website )\n\nif [[ -n $container_exists ]]; then\n  # Use the container with podman; first assign to $run\n  # Port 35729 is for the port when Jekyll auto-reloads\n  # Port 4000 is the Jekyll server port\n  run=\"$podman run -it -p 4000:4000 -p 35729:35729 -v $PWD:/src/site:Z --replace --name cockpit-website cockpit-website\"\n\n  if [ -n \"$1\" ]; then\n    $run \"$@\"\n  else\n    $run bundle exec jekyll server -H 0.0.0.0 -l \"$*\"\n  fi\nelse\n  echo \"## Container does not exist\"\nfi\n"
  },
  {
    "path": "_scripts/container-update-gems",
    "content": "#!/bin/bash -e\n\n\"$(dirname \"$0\")\"/container-run bundle install\n\necho \"## Done!\"\necho \"## Run _scripts/container-jekyll\"\n"
  },
  {
    "path": "_scripts/generate-release-notes",
    "content": "#!/usr/bin/python3\n\n\"\"\"\nGenerates release notes by fetching pull requests with a 'release-note' label\nfrom a list of GitHub repositories.\n\"\"\"\n\nimport argparse\nimport contextlib\nimport datetime\nimport json\nimport os\nimport re\nimport sys\nfrom html.parser import HTMLParser\nfrom pathlib import Path\nfrom typing import Any\nfrom urllib.parse import urlparse\nfrom urllib.request import Request, urlopen\n\nimport yaml\n\n# GitHub repos to consider\nREPOS = [\n    \"cockpit\",\n    \"cockpit-machines\",\n    \"cockpit-podman\",\n    \"cockpit-ostree\",\n    \"cockpit-files\",\n]\n\n# Common terms and definitions\nTERMS = {\n    \"API\": \"Application Programming Interface\",\n    \"ARIA\": \"Accessible Rich Internet Applications\",\n    \"AWS\": \"Amazon Web Services\",\n    \"CDN\": \"Content Delivery Network\",\n    \"CI\": \"continuous integration (testing)\",\n    \"Copr\": \"A build service for unofficial / semi-official Fedora community \"\n    'projects. It\\'s a portmanteau, short for \"Community Projects\". '\n    'Pronounced like the metal \"copper\".',\n    \"CPU\": 'Central Processing Unit, the \"brain\" of a computer',\n    \"DIMM\": \"Dual Inline Memory Module\",\n    \"EC2\": \"Amazon Elastic Compute Cloud\",\n    \"FIPS\": \"Federal Information Processing Standard\",\n    \"FMF\": \"Flexible Metadata Format\",\n    \"GSoC\": \"Google Summer of Code\",\n    \"HTTP\": \"Hypertext Transport Protocol\",\n    \"IPA\": 'identity management system (\"Identity, Policy, Audit\")',\n    \"LAN\": \"Local Area Network\",\n    \"LVM\": \"Logical Volume Manager\",\n    \"motd\": \"message of the day\",\n    \"NBDE\": \"network-bound disk encryption\",\n    \"NFS\": \"Network File System\",\n    \"NIC\": \"Network Interface Card\",\n    \"NMI\": \"Non-Maskable Interrupt\",\n    \"NPM\": \"Node Package Manager\",\n    \"OS\": \"Operating System\",\n    \"PCP\": \"Performance Co-Pilot\",\n    \"RAID\": \"Redundant Array of Inexpensive Disks\",\n    \"RAM\": \"Random Access Memory\",\n    \"repo\": \"repository\",\n    \"RHEL\": \"Red Hat Enterprise Linux\",\n    \"SATA\": 'Serial \"Advanced Technology\" Attachment, a bus interface to attach storage devices to a computer',\n    \"SCSI\": \"Small Computer System Interface, commands and protocols for communication with (mainly storage) devices\",\n    \"SELinux\": \"Security-Enhanced Linux, policies for enforcing access controls in Linux\",\n    \"single pane of glass\": 'console that provides high-level management of multiple machines, also known as a \"single-pane view\"',\n    \"SRPM\": \"source RPM\",\n    \"SSH\": \"Secure Shell, a common protocol to securely connect to a remote computer\",\n    \"STI\": \"Fedora's Standard Test Interface\",\n    \"TLS\": \"Transport Layer Security\",\n    \"tmt\": \"test management tool\",\n    \"USB\": \"Universal Serial Bus, a protocol for hot-pluggable (and usually external) devices\",\n    \"VDO\": \"Virtual Data Optimizer\",\n    \"Virtio\": \"Virtual Input/Output, a standard for network and disk drivers where the guest cooperates with the host for performant virtualization\",\n    \"VM\": \"Virtual Machine\",\n    \"VMs\": \"Virtual Machines\",\n}\n\nUSER_AGENT = (\n    \"Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:90.0) Gecko/20100101 Firefox/90.0\"\n)\n\nHEADER = \"\"\"\nCockpit is the [modern Linux admin interface](https://cockpit-project.org/).\nWe release regularly.\n\nHere are the release notes from VERSIONS:\n\"\"\"\n\nFOOTER = \"\"\"\n## Try it out\n\nVERSIONS ARE available now:\n\n* [For your Linux system](https://cockpit-project.org/running.html)\n* [Cockpit Client](https://flathub.org/apps/details/org.cockpit_project.CockpitClient)\n\"\"\"\n\n# TODO: fetch from https://bodhi.fedoraproject.org/releases?state=current\n# TODO: fetch from https://bodhi.fedoraproject.org/updates/?packages=${pkgname}\nFOOTER_DYNAMIC = \"\"\"\n* [NAME Source Tarball](https://github.com/cockpit-project/REPO/releases/tag/VERSIONS)\n* [NAME Fedora 43](https://bodhi.fedoraproject.org/updates/?releases=F43&packages=REPO)\n* [NAME Fedora 42](https://bodhi.fedoraproject.org/updates/?releases=F42&packages=REPO)\n\"\"\"\n\ncockpit_version: int | None = None\nreleases: list[str] = []\nfooter_locations: list[str] = []\ntags: list[str] = []\nfiles_images: list[str] = []\n\n\nclass NoteImageParser(HTMLParser):\n    def __init__(self, **kwargs):\n        super().__init__(**kwargs)\n        self.images: list[tuple[str, tuple[int, int]]] = []\n\n    def handle_starttag(self, tag, attrs):\n        if tag != \"img\":\n            return\n\n        for attr, val in attrs:\n            if attr == \"src\" and val is not None:\n                self.images.append((val, self.getpos()))\n\n\ndef xdg_home(\n    subdir: str, envvar: str, *components: str, override: str | None = None\n) -> str:\n    path = override and os.getenv(override)\n\n    if not path:\n        directory = os.getenv(envvar)\n        if not directory:\n            directory = os.path.join(os.path.expanduser(\"~\"), subdir)\n        path = os.path.join(directory, *components)\n\n    return path\n\n\ndef xdg_config_home(*components: str, envvar: str | None = None) -> str:\n    return xdg_home(\".config\", \"XDG_CONFIG_HOME\", *components, override=envvar)\n\n\ndef slugify(title: str) -> str:\n    return re.sub(r\"[^0-9a-z]\", \"-\", title.lower())\n\n\ndef markdown_filename() -> str:\n    date_str = datetime.datetime.now().strftime(\"%Y-%m-%d\")\n    return f\"{date_str}-cockpit-{cockpit_version}.md\"\n\n\ndef oxfordize(parts: list[str]) -> str:\n    if len(parts) <= 1:\n        return \"\".join(parts)\n    if len(parts) == 2:\n        return \" and \".join(parts)\n    return f\"{', '.join(parts[:-1])}, and {parts[-1]}\"\n\n\ndef get_json(url: str) -> Any:\n    headers = {\"user-Agent\": USER_AGENT}\n    with contextlib.suppress(FileNotFoundError):\n        token = Path(xdg_config_home(\"cockpit-dev/github-token\")).read_text()\n        if token is not None:\n            headers[\"Authorization\"] = f\"token {token.strip()}\"\n\n    # Specify agent as some websites otherwise block requests\n    req = Request(url=url, headers=headers)\n    resp = urlopen(req)\n    return json.loads(resp.read())\n\n\ndef drop_prefix(repo: str) -> str:\n    return repo.split(\"-\", 1)[1].capitalize() if \"-\" in repo else \"\"\n\n\ndef build_frontmatter(user: str) -> str:\n    cockpit_title = f\"Cockpit {cockpit_version}\"\n    frontmatter_dict = {\n        \"title\": cockpit_title,\n        \"author\": user,\n        \"date\": datetime.datetime.now().strftime(\"%Y-%m-%d\"),\n        \"tags\": \", \".join(tags),\n        \"slug\": slugify(cockpit_title),\n        \"category\": \"release\",\n        \"summary\": \"\",\n    }\n    return yaml.dump(frontmatter_dict, sort_keys=False)\n\n\ndef download_image(url: str, basename: str) -> str | None:\n    \"\"\"Download an image from GitHub and save it locally.\"\"\"\n    req = Request(url=url, headers={\"User-Agent\": USER_AGENT})\n    resp = urlopen(req)\n\n    # Allow one re-direct\n    if resp.geturl() != url:\n        req = Request(url=url, headers={\"User-Agent\": USER_AGENT})\n        resp = urlopen(req)\n\n    parts = urlparse(resp.geturl())\n    extension = Path(parts.path).suffix\n    local_file = f\"{basename}{extension}\"\n    image_path = Path(\"images\") / local_file\n\n    with open(image_path, \"wb\") as f:\n        f.write(resp.read())\n\n    files_images.append(str(image_path))\n    return local_file\n\n\ndef process_images(notes: str) -> str:\n    title = notes.split(\"\\n\", 1)[0]\n    base_slug = re.sub(r\"--+\", \"-\", slugify(title))\n    base_slug = re.sub(r\"^-\", \"\", base_slug)\n    basename = f\"{cockpit_version}-{base_slug}\"\n\n    parser = NoteImageParser()\n    parser.feed(notes)\n\n    for index, (url, (lineno, _offset)) in enumerate(parser.images):\n        if index > 1:\n            basename += f\"-{index}\"\n\n        alt = f\"screenshot of {title.split('##', 1)[-1].split(':', 1)[-1].strip().lower()}\"\n        filename = download_image(url, basename)\n\n        if filename:\n            split_notes = notes.split(\"\\n\")\n            split_notes[lineno - 1] = f\"![{alt}]({{{{ site.baseurl }}}}/images/{filename})\"\n            notes = \"\\n\".join(split_notes)\n\n    return notes\n\n\ndef format_issue(issue: dict[str, Any], repo: str, preview: bool, debug: bool) -> str:\n    splitter = re.compile(r\"^[# ]*release note.*\", re.IGNORECASE | re.MULTILINE)\n    underlines = re.compile(r\"^[=\\-#]+$\")\n    heading_prefix = f\"{drop_prefix(repo)}: \" if \"-\" in repo else \"\"\n\n    issue_body = (issue.get(\"body\") or \"\").replace(\"\\r\\n\", \"\\n\").strip()\n\n    # Attempt to split release notes from the body\n    parts = splitter.split(issue_body, 1)\n    release_note = parts[-1].strip()\n\n    # If no splitter was found, try to extract content after the first heading\n    if len(parts) == 1:\n        heading_parts = re.split(r\"^#\", issue_body, maxsplit=1, flags=re.MULTILINE)\n        if len(heading_parts) > 1:\n            release_note = f\"##{heading_parts[1]}\"\n        else:  # No heading found, use the whole body\n            release_note = issue_body\n\n    # Remove extraneous underline characters, like ==== ---- ####\n    lines = release_note.split(\"\\n\")\n    if lines and underlines.match(lines[0]):\n        release_note = \"\\n\".join(lines[1:]).strip()\n        lines = release_note.split(\"\\n\")\n\n    # Handle underline-style headings and convert them to ATX-style\n    if len(lines) > 1 and underlines.match(lines[1]):\n        release_note = f\"## {lines[0]}\\n\" + \"\\n\".join(lines[2:])\n\n    # Prepend an issue title if no heading was found\n    issue_title = \"\"\n    if not release_note.strip().startswith(\"#\"):\n        issue_title = f\"## {heading_prefix}{issue['title']}\\n\\n\"\n\n    if debug:\n        print(yaml.dump(issue))\n\n    state_info = \"\"\n    if preview:\n        state = issue[\"state\"]\n        url = issue[\"html_url\"]\n        if state == \"open\":\n            alert, included, merged = \"warn\", \"(will not be included) \", \"OPEN\"\n        else:\n            alert, included, merged = \"note\", \"\", \"merged\"\n        state_info = f\"State: **{merged}** {included}@ <{url}>\\n{{:.{alert}}}\\n\\n\"\n\n    # Assemble the note, normalize headings to H2, and inject state info\n    full_note = f\"{issue_title}{release_note.strip()}\"\n    full_note = re.sub(r\"^#+\", \"##\", full_note, count=1, flags=re.MULTILINE)\n    full_note = re.sub(r\"\\n\\n\", f\"\\n\\n{state_info}\", full_note, count=1)\n    if not state_info and full_note.endswith(\n        \"\\n\\n\"\n    ):  # If no state info, ensure no double newline\n        full_note = full_note.rstrip() + f\"\\n\\n{state_info}\"\n\n    return process_images(full_note)\n\n\ndef find_terms(doc: list[str]) -> list[str]:\n    full_text = \"\".join(doc)\n    found_terms = []\n    for term, definition in TERMS.items():\n        if re.search(r\"\\b\" + re.escape(term) + r\"\\b\", full_text):\n            clean_def = \" \".join(definition.replace(\"\\n\", \" \").split())\n            found_terms.append(f\"*[{term}]: {clean_def}\")\n    return sorted(found_terms)\n\n\ndef repo_human(repo: str) -> str:\n    return repo.capitalize() if \"-\" not in repo else repo\n\n\ndef headfoot(template: str) -> str:\n    return template.replace(\"VERSIONS\", oxfordize(releases)).replace(\n        \"ARE\", \"are\" if len(releases) != 1 else \"is\"\n    )\n\n\ndef build_footer_locations(repo: str, version: int) -> str:\n    return (\n        FOOTER_DYNAMIC.replace(\"NAME\", repo_human(repo))\n        .replace(\"VERSIONS\", str(version))\n        .replace(\"REPO\", repo)\n        .strip()\n    )\n\n\ndef process_meta(repo: str, versions: list[int], increment: int):\n    if not versions:\n        print(f\"Warning: No versions found for repo {repo}\", file=sys.stderr)\n        return\n\n    latest_version = versions[-1] + increment\n    releases.append(f\"{repo_human(repo)} {latest_version}\")\n    footer_locations.append(build_footer_locations(repo, latest_version))\n    tags.append(repo.replace(\"cockpit-\", \"\"))\n\n\ndef process_repos(preview: bool, increment: int, debug: bool) -> list[str]:\n    base_url = \"https://api.github.com/search/issues?q=is:pr+repo:cockpit-project/{repo}+label:release-note\"\n    tags_template = \"https://api.github.com/repos/cockpit-project/{repo}/tags\"\n    all_notes = []\n\n    for repo in REPOS:\n        # Get tags to determine the latest version\n        tags_url = tags_template.format(repo=repo)\n        tags_data = get_json(tags_url)\n\n        if tags_data is None:\n            continue\n\n        versions = sorted(\n            [int(tag[\"name\"]) for tag in tags_data if tag[\"name\"].isdigit()]\n        )\n\n        # Set the main cockpit_version from the first repo ('cockpit')\n        global cockpit_version\n        if cockpit_version is None and versions:\n            cockpit_version = versions[-1] + increment\n\n        # Get pull requests with release notes\n        if not preview:\n            base_url += \"+is%3Aclosed\"\n        pr_url = base_url.format(\"\", repo=repo)\n        pr_data = get_json(pr_url)\n        if pr_data is None or not pr_data.get(\"items\"):\n            continue\n\n        notes = [\n            format_issue(issue, repo, preview, debug) for issue in pr_data[\"items\"]\n        ]\n\n        if notes:\n            process_meta(repo, versions, increment)\n            all_notes.extend(notes)\n\n    return all_notes\n\n\ndef construct_all_the_notes(\n    user: str, preview: bool, increment: int, debug: bool\n) -> str:\n    release_notes = process_repos(preview, increment, debug)\n    frontmatter = build_frontmatter(user)\n\n    sections = [\n        \"---\",\n        \"\\n\",\n        frontmatter,\n        \"---\",\n        \"\\n\",\n        headfoot(HEADER),\n        \"\\n\\n\",\n        \"\\n\\n\".join(release_notes),\n        \"\\n\\n\",\n        headfoot(FOOTER),\n        \"\\n\",\n        \"\\n\".join(footer_locations),\n        \"\\n\\n\",\n        \"\\n\".join(find_terms(release_notes)),\n    ]\n\n    # Clean up excessive newlines\n    full_text = \"\".join(sections)\n    return re.sub(r\"\\n{4,}\", \"\\n\\n\\n\", full_text)\n\n\ndef main():\n    parser = argparse.ArgumentParser(description=\"\" \\\n    \"Generate Cockpit release notes from Cockpit repositories that include\" \\\n    \"the label `release-note`. It takes the last ## header in the PR body and\"\n    \"formats it to function within a Jekyll blog post.\"\n    )\n    parser.add_argument(\n        \"-p\",\n        \"--preview\",\n        action=\"store_true\",\n        help=\"Preview release notes with open PRs and more info\",\n    )\n    parser.add_argument(\n        \"-r\",\n        \"--released\",\n        action=\"store_true\",\n        help=\"Cockpit has been released (do not increment version)\",\n    )\n    # TODO: validate author\n    parser.add_argument(\n        \"-u\",\n        \"--user\",\n        help=\"Author of the blog post (see data/_authors.yml)\",\n        required=True,\n    )\n    parser.add_argument(\n        \"-v\",\n        \"--verbose\",\n        action=\"store_true\",\n        help=\"Show additional information on the command line\",\n    )\n    args = parser.parse_args()\n    user = args.user\n\n    increment = 0 if args.released else 1\n    final_notes = construct_all_the_notes(user, args.preview, increment, args.verbose)\n    output_filename = Path(\"_posts\") / markdown_filename()\n    with open(output_filename, \"w\", encoding=\"utf-8\") as f:\n        f.write(final_notes)\n\n    print(f\"Generated release notes for Cockpit {cockpit_version}: {output_filename}\")\n    if files_images:\n        print(f\"Downloaded images: {' '.join(files_images)}\")\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "_scripts/update-browser-data.rb",
    "content": "#!/usr/bin/ruby\n# frozen_string_literal: true\n\n# To use with a toolbox, make sure your toolbox exists and run:\n# _scripts/container-ruby _scripts/update-browser-data.rb\n\nrequire 'bundler'\nrequire 'net/http'\nrequire 'json'\nrequire 'yaml'\nrequire 'fileutils'\n\n# Browser support feature rules\n# Uses caniuse.com's short name for the key\n# Values are 1:1 what Cockpit checks for req() in src/ws/login.js\n# css() is prefixed with css, then includes the rules\nsupports = YAML.safe_load(\"\n    websockets:\n        req: [WebSocket, window]\n\n    xhr2:\n        req: [XMLHttpRequest, window]\n\n    namevalue-storage:\n        req: [sessionStorage, window]\n\n    json:\n        req: [JSON, window]\n\n    es5:\n        req: [defineProperty, Object]\n\n    console-basic:\n        req: [console, window]\n\n    history:\n        req: [pushState, window.history]\n\n    textcontent:\n        req: [textContent, document]\n\n    css-variables:\n        req: [CSS, window]\n\n    css-supports-api:\n        req: [supports, window.CSS]\n\n    promise-finally:\n        req: [finally, Promise.prototype]\n\n    mdn-javascript_builtins_string_replaceall:\n        req: [replaceAll, String.prototype]\n\n    flexbox:\n        css: [display, flex]\n\n    css-grid:\n        css: [display, grid]\n\n    css-supports-api:\n        css: 'selector(test)'\n\n    mdn-css_selectors_where:\n        css: 'selector(:is(*):where(*))'\n\")\n\ncaniuse_db = 'https://raw.githubusercontent.com/Fyrd/caniuse/main/data.json'\nsupport_file = File.expand_path \"#{__dir__}/../_data/browser_support.yml\"\n\nputs 'Downloading caniuse database...'\ndoc = Net::HTTP.get(URI(caniuse_db))\n\nputs 'Processing DB...'\n\nobj = JSON.parse(doc)\ndata = obj['data']\n\nbrowsers = {}\nterminator = 999_999\n\nsupports.each do |support, _vals|\n  # First check to see if the support data is in the caniuse DB.\n  # It really should be, but sometimes it's missing something.\n  # Regardless, it needs to be passed through still, for the live JS browser check.\n  data[support] && data[support]['stats'].each do |browser, version|\n    # Edge _almost_ supports @supports API; close enough for us\n    low_version = if support == 'css-supports-api'\n                    version.reject { |_k, v| v == 'n' }.keys.first\n                  else\n                    version.select { |_k, v| v == 'y' }.keys.first\n                  end\n\n    if low_version.nil?\n      browsers[browser] = terminator\n    elsif !browsers[browser] || browsers[browser].to_f < low_version.to_f\n      browsers[browser] = low_version.split('-').first\n    end\n\n    ## Include versions in each rule\n    # if (low_version)\n    #   supports[support][\"browsers\"] ||= {}\n    #   supports[support][\"browsers\"][browser] = low_version.split('-').first\n    # end\n  end\nend\n\n# Smoosh browser support down\nbrowsers = browsers.reject { |_k, v| v == terminator }.compact\n\ncomment = 'Generated by _scripts/update-browser-data.rb'\n\nputs \"Writing #{support_file}...\"\nFile.write(support_file, ['comment' => comment, 'browsers' => browsers, 'rules' => supports].first.to_yaml)\nputs 'Done!'\n"
  },
  {
    "path": "_scripts/update-external-docs.rb",
    "content": "#!/usr/bin/ruby\n# frozen_string_literal: true\n\n# Run using toolbox-ruby:\n# _scripts/container-ruby _scripts/update-external-docs.rb\n\n### Editable variables ###\n\n# Pages to fetch from the Cockpit wiki\nwiki_pages = %w[\n  Cockpit-Coding-Guidelines\n  Contributing\n  Workflow\n  Proxying-Cockpit-over-NGINX\n  Proxying-Cockpit-over-Apache-with-LetsEncrypt\n  Demos-and-Talks\n]\n\n# Pages to fetch from the Cockpit git repo\nsource_pages = %w[\n  HACKING.md\n  test/README.md\n]\n\n# Pages to fetch from the Cockpit bots repo\nbots_pages = %w[\n  README.md\n]\n\n# URLs to rewrite\n@url_rewrites = {\n  'https://github.com/cockpit-project/cockpit/blob/main/HACKING.md' =>\n  '{{ site.baseurl }}/external/source/HACKING.html',\n\n  'https://github.com/cockpit-project/cockpit/blob/main/test/README' =>\n  '{{ site.baseurl }}/external/source/test/README.html',\n\n  'https://github.com/cockpit-project/bots/blob/main/README.md' =>\n  '{{ site.baseurl }}/external/bots/README.html',\n\n  'https://github.com/cockpit-project/cockpit/blob/master/HACKING.md' =>\n  '{{ site.baseurl }}/external/source/HACKING.html',\n\n  './pkg/' => 'https://github.com/cockpit-project/cockpit/tree/main/pkg',\n\n  './pkg/systemd/' => 'https://github.com/cockpit-project/cockpit/tree/main/pkg/systemd/',\n\n  'https://github.com/cockpit-project/cockpit/blob/master/test/README' =>\n  '{{ site.baseurl }}/external/source/test/README.html',\n\n  'https://github.com/cockpit-project/bots/blob/master/README.md' =>\n  '{{ site.baseurl }}/external/bots/README.html',\n\n  'http://cockpit-project.org/ideals.html' =>\n  '{{ site.baseurl }}/ideals.html',\n\n  'About#project-ideals' =>\n  '{{ site.baseurl }}/ideals.html',\n\n  'About#contact-developers--stay-up-to-date' =>\n  'https://github.com/cockpit-project/cockpit/wiki/About',\n\n  'http://files.cockpit-project.org/guide/latest/' =>\n  '{{ site.baseurl }}/guide/latest/',\n\n  'Ideas' =>\n  'https://github.com/cockpit-project/cockpit/wiki/Ideas',\n\n  'https://github.com/cockpit-project/cockpit/wiki/Workflow#review-criteria' =>\n  '/external/wiki/Workflow#review-criteria',\n\n  'How-@mvollmer-merges-pull-requests' =>\n  'https://github.com/cockpit-project/cockpit/wiki/How-@mvollmer-merges-pull-requests',\n\n  'Design' =>\n  'https://github.com/cockpit-project/cockpit/wiki/Design'\n}\n\n### Code below ###\n\nrequire 'bundler'\nrequire 'net/http'\nrequire 'yaml'\nrequire 'fileutils'\n\n@prefix = {\n  source: 'https://github.com/cockpit-project/cockpit/blob/master/',\n  source_raw: 'https://raw.githubusercontent.com/cockpit-project/cockpit/master/',\n  bots: 'https://github.com/cockpit-project/bots/blob/master/',\n  bots_raw: 'https://raw.githubusercontent.com/cockpit-project/bots/master/',\n  wiki: 'https://github.com/cockpit-project/cockpit/wiki/',\n  wiki_raw: 'https://raw.githubusercontent.com/wiki/cockpit-project/cockpit/',\n  issues: 'https://github.com/cockpit-project/cockpit/issues'\n}\n\n@external_dir = File.expand_path \"#{__dir__}/../external/\"\n\ndef fetch_and_add(pages, type = :source)\n  pages.each do |page|\n    suffix = type == :wiki ? '.md' : ''\n    url = @prefix[type] + page\n    url_raw = @prefix[\"#{type}_raw\".to_sym] + page + suffix\n    file = \"#{type}/#{page}\"\n    file += '.md' unless page.match(/\\.md$/)\n\n    doc = Net::HTTP.get(URI(url_raw))\n\n    if %i[source bots].include?(type)\n      # Extract the title for git source, as filenames are often \"README\"\n      title = doc.match(/^#[^\\n]*\\n/m)[0].gsub(/#/, '').strip\n\n      # Strip the title, as it's added in our Jekyll codebase\n      doc = doc.sub(/^#* #{title}/m, '').strip\n    else\n      # Show the path as title for wiki pages,\n      # as wiki pages need to have relevant names\n      title = page.gsub('/', ' / ').gsub('-', ' ').sub(/\\.md$/i, '')\n\n      # Indent pages 1 level if there's a matching H1 already\n      # (similar to what GitHub does on wiki pages)\n      doc = doc.gsub(/^#/m, '##') if doc.match(/^# /m)\n    end\n\n    # Rewrite URLs\n    @url_rewrites.each do |before, after|\n      doc = doc.gsub(\"](#{before})\", \"](#{after})\")\n      doc = doc.gsub(%r{]\\(http(s)?://cockpit-project\\.org/}, ']({{ site.baseurl }}/')\n    end\n\n    # Fix issue link URLs\n    doc = doc.gsub(%r{\\]\\(../issues}m, \"](#{@prefix[:issues]}\")\n\n    frontmatter = {\n      'title' => title,\n      'source' => url\n    }.to_yaml\n\n    FileUtils.mkdir_p \"#{@external_dir}/#{File.dirname file}\"\n    File.write \"#{@external_dir}/#{file}\", \"#{frontmatter}---\\n\\n#{doc}\"\n  end\nend\n\nputs 'Updating source pages'\nfetch_and_add(source_pages, :source)\nputs 'Updating wiki pages'\nfetch_and_add(wiki_pages, :wiki)\nputs 'Updating bots pages'\nfetch_and_add(bots_pages, :bots)\nputs 'All pages updated'\n"
  },
  {
    "path": "applications.md",
    "content": "---\ntitle: Applications\n---\n\n{% comment %}\n###\n### NOTE: Application data is located in _data/applications.yml\n###\n{% endcomment %}\n\nThe Cockpit Web Console is extendable. The Cockpit team and others have built applications that are easy to install.\n\nOften, these applications are available to install with a click of a button on the \"Applications\" page, but command-line installation is also possible using the package name.\n\nHelp us [expand this list](https://github.com/cockpit-project/cockpit-project.github.io/edit/main/_data/applications.yml)! Also consider [developing]({{ site.baseurl }}/external/wiki/Contributing.html) [your own application with the Starter Kit]({{ site.baseurl }}/blog/cockpit-starter-kit.html).\n\n{% assign apps = site.data.applications %}\n\n{% for maintainer in site.data.maintainers %}\n### {{ maintainer[1].title }} developed applications\n{% assign maintainer_apps = apps | where: 'maintainer', maintainer[0] %}\n{% include apps.html apps=maintainer_apps %}\n{% endfor %}\n\n### Third party\n{% assign thirdparty = apps | where_exp: 'item', 'item.maintainer == nil' %}\n{% include apps.html apps=thirdparty %}\n"
  },
  {
    "path": "assets/default.scss",
    "content": "// Please copy default.scss to site.scss to customize your site.\n//\n// If site.scss (or site) exists, then default.scss will not\n// be used. (You can then use it for reference later.)\n//\n// Be sure to `@import \"minima\"` after the variables needed for it\n// and before your own custom CSS, so you can easily override\n// (if you really need to).\n\n// Variables for SASS\n$spacing-unit:     1rem;\n\n:root {\n    // CSS variables\n    --font-base-family: Helvetica Neue, Helvetica, Arial, Liberation Sans, sans-serif;\n    --font-base-size:   16px;\n    --font-base-weight: 400;\n    --font-small-size:  var(--font-base-size) * 0.875;\n    --base-line-height: 1.5;\n\n    --color-text:       #333;\n    --color-background: #fdfdfd;\n    --color-brand:      #2a7ae2;\n\n    --color-grey:       #828282;\n    --color-grey-light: color-mix(in lch, var(--color-grey), var(--color-background), 40%);\n    --color-grey-dark: color-mix(in lch, var(--color-grey), var(--color-text), 25%);\n\n    // Width of the content area\n    --content-width:    60em;\n}\n\n// Import partials from the `minima` theme.\n@import \"minima\";\n\n// Import grid (see http://gridlex.devlint.fr/ for docs)\n@import \"vendor/gridlex\";\n\n// Comment out or remove the follow if you don't use the feature\n////////////////////////////////////////////////////////////////////////\n@import \"lib/nav\";          // Navbar (see opts in lib/navbar.scss)\n@import \"lib/search\";       // Styles for the search page\n@import \"lib/blog\";         // Default blog style\n@import \"lib/pagination\";   // Blog pagination\n@import \"lib/stickyfooter\"; // Stretch page with footer on bottom\n@import \"lib/scrollbar-on\"; // Stop page shift by keeping scrollbar on\n//@import \"lib/stickyheader\"; // Keep header at the top\n\n// Minima also includes a mixin for defining media queries.\n// Use media queries like this:\n// @include media-query($on-palm) {\n//     .wrapper {\n//         padding-inline: calc(var(--spacing-unit) / 2);\n//     }\n// }\n"
  },
  {
    "path": "assets/lib/blog.scss",
    "content": ":root {\n  --color-author-card: inherit;\n  --author-card-padding: 0;\n  --author-card-margin: 2em 0;\n}\n\nbody.archive {\n  &.category-blog,\n  &.category-1 {\n    .page-header {\n      display: none;\n    }\n\n    #content {\n      padding-block-start: 2em;\n    }\n\n    .entry-title {\n      a {\n        color: inherit;\n\n        &:hover {\n          text-decoration: underline;\n        }\n      }\n    }\n  }\n}\n\n/* Make comments come from avatars */\n\n.commentlist {\n  .avatar {\n    inset: 0 auto auto -98px;\n  }\n\n  > li.comment {\n    margin-inline-start: 98px;\n\n    .comment-meta, .comment-content {\n      margin-inline-end: auto;\n    }\n  }\n}\n\n/** Article */\n\n.singular .hentry, .hentry {\n  padding: 0;\n}\n\n.singular .entry-header .entry-meta, .entry-header .entry-meta {\n  position: static;\n}\n\n.wrapper > article > .entry-content {\n  margin: 2rem 0;\n}\n\narticle.post {\n  overflow: hidden;\n\n  h2:first-child {\n    a {\n      display: block;\n    }\n  }\n\n  /* Style-up blog post YouTube videos & Slideshare decks (center & frame) */\n  iframe {\n    &[src*=youtube],\n    &[src*=slideshare] {\n      border: 1px solid var(--color-text);\n      border-radius: 5px;\n      overflow: hidden;\n      display: block;\n      margin: 1em auto;\n      background: #999;\n\n      /* Fit width to page */\n      max-width: calc(100vw - 2rem);\n\n      /* Attempt to preserve aspect ratio */\n      max-height: calc(100vw * 1080 / 1920);\n    }\n  }\n\n  + article.post {\n    margin-block-start: 3em;\n  }\n}\n\n.articles {\n  h2.post-title {\n    margin: 2rem 0 1rem;\n  }\n}\n\n.post-meta {\n  margin: 1ex 0 0;\n  color: var(--color-grey-dark);\n\n  .tags {\n    ul {\n      display: inline;\n      padding: 0;\n      margin: 0;\n    }\n\n    li {\n      display: inline;\n      margin: 0;\n      padding: 0;\n\n      + li {\n        margin-inline-start: -1ex;\n\n        &:before {\n          content: \", \";\n        }\n      }\n\n      a {\n        padding: 0.5ex;\n      }\n    }\n  }\n}\n\n.author-card {\n  background: var(--color-author-card);\n  padding: var(--author-card-padding);\n  margin: var(--author-card-margin);\n}\n\n.author-photo {\n  vertical-align: middle;\n  text-align: right;\n\n  img {\n    border-radius: 48px;\n  }\n}\n\n.author-blurb {\n  overflow: hidden;\n\n  .follow-on,\n  .more-link {\n    line-height: 3;\n  }\n}\n\n.post-content {\n  p {\n    > :where(img:first-child),\n    > a[href*=flickr] img {\n      max-width: calc(100% - 2px);\n      height: auto;\n      display: block;\n      text-align: center;\n      margin: 1em auto;\n    }\n  }\n\n  > p:first-child {\n    > a > :where(img:first-child),\n    > :where(img:first-child) {\n      float: left;\n      margin: 0 3ex 1ex 0;\n      max-width: 33%;\n\n      @media screen and (max-width: 651px) {\n        max-width: 33%;\n        height: auto;\n      }\n    }\n  }\n\n  li > p {\n    margin: 0;\n  }\n\n  table:not([class]) {\n    margin: 2em 0;\n  }\n}\n\n#blog-comments {\n  border-top: 1px solid #ccc;\n  margin: 4em 0 0;\n  padding: 3em 0 3em;\n}\n\n.tag-cloud {\n  line-height: 2.5ex;\n  text-align: justify;\n\n  a {\n    padding: 0.25ex;\n    vertical-align: middle;\n    white-space: nowrap;\n  }\n}\n\n.tag-cloud + .tag-list {\n  margin-block-start: 4em;\n}\n\n.tag-list {\n  ul {\n    margin: 0 0 3em 0;\n  }\n\n  ul, li {\n    list-style: none;\n  }\n\n  li {\n    display: flex;\n    overflow: hidden;\n  }\n\n  .published {\n    @extend .post-meta;\n\n    font-size: inherit;\n    min-width: 12ex;\n    padding-inline-end: 1ex;\n    text-align: right;\n  }\n\n  a {\n    flex: 1;\n  }\n}\n\n/* Disclaimer */\n\n.blog-disclaimer {\n  border-top: 1px solid #ccc;\n  clear: both;\n  opacity: 0.75;\n  margin: 3em 0 0;\n  padding: 3em 0 0;\n}\n\n.article-tag-list {\n  padding: 0 0.5em 3em;\n  margin: 0;\n\n  li {\n    list-style: none;\n    margin: 0;\n    padding: 0;\n\n    a {\n      font-size: 130%;\n      padding-block-start: 1.5em;\n      display: block;\n    }\n  }\n}\n\n/* Blog post summary */\n\n.blog-posts-list {\n  .post-content-subtitle {\n    font-size: inherit;\n    margin: 1rem 0 0.5rem;\n  }\n}\n\n/* Pagination */\n\n.blog-posts-list + nav > .pagination {\n  margin: 4rem 0 0;\n}\n"
  },
  {
    "path": "assets/lib/browser-support.js",
    "content": "(function (){\n    function req(name, obj) {\n        var valid;\n\n        try {\n            valid = obj[name];\n        } catch (err) {\n            valid = undefined;\n        }\n\n        if (valid === undefined && console) console.log('Missing JS feature: ' + name);\n        return (valid !== undefined);\n    }\n\n    function css(prop, val) {\n        var valid;\n\n        try {\n            if (val) {\n                valid = CSS && CSS.supports && CSS.supports(prop, val);\n            } else {\n                // Support query string (instead of prop:val)\n                valid = CSS && CSS.supports && CSS.supports(prop);\n            }\n        } catch (err) {\n            valid = false;\n        }\n\n        if (!valid && console) console.log('Missing CSS feature: ' + [prop, val].join(', '));\n        return valid;\n    }\n\n    function browserCheck() {\n        var browserTest = true,\n            valid;\n\n        return ({% for rule in site.data.browser_support.rules %}{%\n            if rule[1].req \n\n                %}\n            /* Check {{ rule[0] }}: {{ rule[1].req[0] }} in {{ rule[1].req[1] }} */\n            req('{{ rule[1].req[0] }}', {{ rule[1].req[1] }}) && {%\n\n            elsif rule[1].css\n            %}{%\n                if rule[1].css[1] \n\n                    %}\n            /* Check {{ rule[0] }}: @supports({{ rule[1].css[0] }}:{{ rule[1].css[1] }}) */\n            css('{{ rule[1].css[0] }}', '{{ rule[1].css[1] }}') && {%\n\n                else\n\n                    %}\n            /* Check {{ rule[0] }}: @supports({{ rule[1].css }}) */\n            css('{{ rule[1].css }}') && {%\n\n                endif\n                %}{%\n            endif\n            %}{%\n        endfor %}\n        true);\n    }\n\n    // Success handler\n    function success() {\n        document\n            .getElementById('browser-support')\n            .setAttribute('data-browser-supported', true);\n    }\n\n    // Bind an event listener for when the page has loaded\n    document.addEventListener('DOMContentLoaded', function(event) {\n        document.getElementById('browser-support') &&\n            browserCheck() &&\n            success();\n    });\n}());"
  },
  {
    "path": "assets/lib/minima-unset.scss",
    "content": "table {\n  border: unset;\n\n  th, td {\n    border: unset;\n  }\n}\n\ntable[class] {\n  border-collapse: unset;\n  margin: unset;\n  padding: unset;\n  text-align: unset;\n\n  tr {\n    &:nth-child(2n) {\n      background: unset;\n    }\n  }\n\n  th, td {\n    background: unset;\n    color: unset;\n  }\n}\n"
  },
  {
    "path": "assets/lib/nav.scss",
    "content": "// Select the mobile menu style\n// styles include: sidebar, menu, none\n$nav-mobile-style: menu;\n\n// Responsive breakpoint\n$nav-min-width: $on-laptop;\n\n:root {\n  //// Defaults\n\n  // Padding defaults\n  --nav-padding: .75ex;\n  --nav-padding-ratio: 2.5;\n  --nav-padding-y: var(--nav-padding);\n  --nav-padding-x: calc(var(--nav-padding-y) * var(--nav-padding-ratio));\n\n  // Color defaults\n  --color-nav: transparent;\n  --color-nav-text: var(--color-text);\n  --color-nav-menu: var(--color-grey-light);\n  --color-nav-menu-top: var(--color-nav-menu);\n  --color-nav-menu-top-text: var(--color-nav-text);\n  --color-nav-highlight: var(--color-brand);\n  --color-nav-highlight-text: #fff;\n  --nav-active: transparent;\n\n  // Icons\n  --nav-icon-opacity: 0.5;\n  --nav-icon-menu: \"≡\";\n  --nav-icon-right: \"⯈\";\n  --nav-icon-down: \"▾\";\n\n  // Styling defaults (shadow and rounded radius)\n  --nav-menu-shadow: 2px 2px 2px rgba(var(--color-text), 0.125);\n  --nav-menu-radius: 3px;\n\n  // Animation timing defaults\n  --nav-animation: 150ms;\n  --nav-menu-animation: var(--nav-animation) * 2;\n  --nav-mobile-menu-animation: all 300ms ease-in-out;\n\n  // These should be set in theme.scss/theme.scss or minima already...\n  // but just in case, we're defining fallbacks here\n  --on-palm: 600px;\n  --on-laptop: 800px;\n\n  // Mobile menu colors\n  --nav-mobile-text: white;\n  --nav-mobile-text-shadow: 1px 1px 0 darken(var(--color-brand, ) 30%);\n  --nav-mobile-menu: darken(var(--color-brand, ) 20%);\n  --nav-mobile-menu-highlight: mix(var(--nav-mobile-menu, ) var(--nav-mobile-text, ) 80%);\n  --nav-mobile-button-size: 32px;\n  --nav-mobile-font-size: 16px;\n  --nav-mobile-item-height: 48px;\n  --nav-mobile-item-padding: 0 16px;\n  --nav-mobile-menu-padding: 8px 0;\n  --nav-mobile-menu-min-width: 56px * 3;\n\n  // Native iOS or Android fonts when installed, else use website fonts\n  --nav-mobile-font-family: -apple-system-font, \"Roboto\", \"Droid Sans\", var(--font-base-family);\n}\n\n////////////////////////////////////////////////////////////////////////\n\n@mixin no-select {\n  -webkit-touch-callout: none;\n  -webkit-user-select: none;\n  -khtml-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\n.nav-check {\n  display: none;\n}\n\n@media screen and (min-width: #{$nav-min-width + 1}) {\n  nav.menu, %nav-menu {\n    position: relative;\n    z-index: 100;\n    cursor: default;\n\n    // Cleafix hack to make nav act more like block\n    // without having to set an overflow property\n    // (which would hide menus)\n    &::after {\n      content: \"\";\n      display: table;\n      clear: both;\n    }\n\n    // Remove list styles\n    ul, li {\n      transition: all var(--nav-animation);\n      list-style: none;\n      margin: 0;\n      padding: 0;\n    }\n\n    a, .not-a-link {\n      transition: all var(--nav-menu-animation);\n      display: block;\n      color: var(--color-nav-text) !important;\n      padding: var(--nav-padding-y) var(--nav-padding-x);\n      text-decoration: none !important;\n    }\n\n    ul {\n      background: var(--color-nav);\n\n      ul {\n        position: absolute;\n        inset-inline-start: 0;\n        inset-block-start: 100%;\n        visibility: hidden;\n        opacity: 0;\n        box-shadow: var(--nav-menu-shadow);\n\n        li {\n          &:last-child {\n            border-radius: 0 0 var(--nav-menu-radius) var(--nav-menu-radius);\n          }\n\n          &.nav-group:hover {\n            border-radius: 0 0 0 var(--nav-menu-radius);\n          }\n\n          ul li:first-child {\n            border-radius: 0 var(--nav-menu-radius) 0 0;\n          }\n        }\n\n        ul {\n          inset-inline-start: 100%;\n          inset-block-start: 0;\n        }\n      }\n    }\n\n    li {\n      float: left;\n      position: relative;\n\n      > ul {\n        transform: scaleY(0);\n        transform-origin: top left;\n\n        ul {\n          transform: scale(0);\n        }\n      }\n\n      &:hover {\n        background: var(--color-nav-menu);\n\n        li {\n          background: var(--color-nav-menu);\n        }\n\n        > ul {\n          // Activate the immediate submenu\n          visibility: visible;\n          opacity: 1;\n\n          // Make sure menus are on top (z-index is relative to parent z-index)\n          z-index: 1;\n          transform: scale(1);\n\n          a, .not-a-link {\n            margin: 0 calc(var(--nav-padding-x) * -1);\n            padding: var(--nav-padding-y) calc(var(--nav-padding-x) * 2);\n          }\n\n          li:last-child a, .not-a-link {\n            margin-block-end: calc(var(--nav-padding-y) * -4);\n            padding-bottom: calc(var(--nav-padding-y) * 5);\n          }\n        }\n      }\n\n      li {\n        width: 100%;\n        white-space: nowrap;\n        min-width: 10rem;\n\n        &:hover,\n        li:hover {\n          background: var(--color-nav-highlight);\n\n          > a {\n            color: var(--color-nav-highlight-text) !important;\n          }\n        }\n      }\n    }\n\n    > ul > li {\n      &:hover {\n        background: var(--color-nav-menu-top);\n\n        > a {\n          color: var(--color-nav-menu-top-text) !important;\n        }\n      }\n\n      &.active {\n        background: var(--nav-active);\n      }\n\n      &.nav-group > {\n        a, .not-a-link {\n          &::after {\n            opacity: var(--nav-icon-opacity);\n            content: var(--nav-icon-down);\n            margin-inline-start: 1ex;\n          }\n        }\n      }\n    }\n\n    li .nav-group > {\n      a, .not-a-link {\n        &::after {\n          content: \"\";\n          display: inline-block;\n          width: 3ex;\n        }\n\n        &::before {\n          opacity: var(--nav-icon-opacity);\n          content: var(--nav-icon-right);\n          float: right;\n        }\n      }\n    }\n  }\n}\n\n@media screen and (max-width: $nav-min-width) {\n  %sidebar {\n    nav {\n      font-family: var(--nav-mobile-font-family);\n      font-size: var(--nav-mobile-font-size);\n      z-index: 1000;\n      cursor: default;\n\n      ul, li {\n        padding: 0;\n        margin: 0;\n        list-style: none;\n      }\n\n      li.active {\n        background-color: var(--nav-mobile-menu-highlight);\n      }\n\n      > .nav-menu {\n        transition: var(--nav-mobile-menu-animation);\n        visibility: hidden;\n        position: fixed;\n        inset-block-start: 0;\n        inset-inline-start: -100%;\n        overflow: auto;\n        height: 100vh;\n        background-color: var(--nav-mobile-menu);\n        z-index: 2;\n        box-shadow: 0 0 6px rgba(var(--color-text), 0.25);\n        min-width: 25vw;\n        max-width: 75vw;\n        padding: var(--nav-mobile-button-size) 0 0 1ex;\n\n        > li {\n          margin-block-start: 2ex;\n        }\n\n        ul {\n          padding: 0 2ex 0 2ex;\n        }\n\n        a, .not-a-link {\n          display: block;\n          padding: 0 1ex;\n          color: var(--nav-mobile-text) !important;\n          text-shadow: var(--nav-mobile-text-shadow);\n        }\n\n        .not-a-link {\n          opacity: 0.4;\n        }\n      }\n\n      > .nav-screen {\n        @include no-select;\n\n        transition: var(--nav-mobile-menu-animation);\n        opacity: 0;\n      }\n\n      .nav-toggle:before {\n        transition: var(--nav-mobile-menu-animation);\n        display: block;\n        width: var(--nav-mobile-button-size);\n        height: var(--nav-mobile-button-size);\n        cursor: pointer;\n        content: var(--nav-icon-menu);\n        font-size: var(--nav-mobile-button-size);\n        color: var(--color-nav-text);\n        background: var(--color-nav-menu);\n        z-index: 3;\n        position: fixed;\n        inset-block-start: 0;\n        inset-inline-start: 0;\n        padding: 0.5ex;\n        line-height: var(--nav-mobile-button-size);\n        border-radius: var(--nav-menu-radius);\n      }\n    }\n\n    .nav-check:checked + nav > {\n      .nav-menu {\n        visibility: visible;\n        inset-inline-start: 0;\n        display: block;\n      }\n\n      .nav-screen {\n        position: fixed;\n        inset: 0;\n        z-index: 1;\n        background: var(--color-text);\n        opacity: 0.5;\n      }\n\n      .nav-toggle:before {\n        background: transparent;\n      }\n    }\n\n    .hgroup {\n      padding-inline-start: calc(calc(var(--nav-mobile-button-size)) + 1.5ex);\n    }\n  }\n\n  %menu {\n    & {\n      display: flex;\n      align-items: baseline;\n      justify-content: space-between;\n    }\n\n    nav {\n      font-family: var(--nav-mobile-font-family);\n      font-size: var(--nav-mobile-font-size);\n      z-index: 1000;\n      cursor: default;\n      position: relative;\n      margin: 1rem;\n\n      ul, li {\n        padding: 0;\n        margin: 0;\n        list-style: none;\n      }\n\n      > .nav-menu {\n        transition: all 100ms;\n        visibility: hidden;\n        transform: scale(0);\n        transform-origin: calc(100% - 2.5ex) 2.5ex;\n        position: absolute;\n        inset-block-start: 0;\n        inset-inline-end: 0;\n        overflow: auto;\n        background-color: var(--nav-mobile-menu);\n        z-index: 2;\n        box-shadow: 0 0 6px rgba(var(--color-text), 0.25);\n        max-height: 75vh;\n        padding: var(--nav-mobile-menu-padding);\n        min-width: var(--nav-mobile-menu-min-width);\n\n        ul {\n          padding: 0 2ex 0 2ex;\n        }\n\n        a, .not-a-link {\n          display: block;\n          line-height: var(--nav-mobile-item-height);\n          padding: var(--nav-mobile-item-padding);\n          color: var(--nav-mobile-text) !important;\n          text-shadow: var(--nav-mobile-text-shadow);\n          text-decoration: none !important;\n        }\n\n        a:hover {\n          background-color: rgba(var(--nav-mobile-menu-highlight,) 0.5);\n        }\n\n        .not-a-link {\n          opacity: 0.4;\n        }\n      }\n\n      li.active {\n        background-color: var(--nav-mobile-menu-highlight);\n      }\n\n      .nav-toggle:before {\n        transition: var(--nav-mobile-menu-animation);\n        display: inline-block;\n        width: var(--nav-mobile-button-size);\n        height: var(--nav-mobile-button-size);\n        cursor: pointer;\n        content: var(--nav-icon-menu);\n        font-size: var(--nav-mobile-button-size);\n        color: var(--color-nav-text);\n        z-index: 3;\n        padding: 0.5ex;\n        line-height: var(--nav-mobile-button-size);\n        border-radius: var(--nav-menu-radius);\n      }\n    }\n\n    .nav-check:checked + nav > {\n      .nav-menu {\n        visibility: visible;\n        transform: scale(1);\n      }\n\n      // Invisible screen to capture clicks\n      // (and not trigger page links)\n      .nav-screen {\n        @include no-select;\n\n        position: fixed;\n        inset: 0;\n        z-index: 1;\n      }\n\n      .nav-toggle:before {\n        background: transparent;\n      }\n    }\n  }\n\n  %none {\n    background: none;\n  }\n}\n\n//// Make the masthead a menu\n// It's also possible to extend nav.menu for other nav elements\n// ...or make nav elements with a class of menu in document bodies too\n.masthead {\n  @extend %#{$nav-mobile-style};\n\n  nav {\n    @extend %nav-menu;\n  }\n}\n"
  },
  {
    "path": "assets/lib/pagination.scss",
    "content": ".pagination {\n  margin: 0;\n  padding: 0;\n  overflow: hidden;\n\n  li {\n    text-align: center;\n    display: block;\n    float: left;\n    list-style: none;\n\n    + li {\n      margin-inline-start: -1px;\n    }\n\n    &:first-child {\n      a, span {\n        border-radius: var(--border-radius) 0 0 var(--border-radius);\n      }\n    }\n\n    &:last-child {\n      a, span {\n        border-radius: 0 var(--border-radius) var(--border-radius) 0;\n      }\n    }\n  }\n\n  a, span {\n    border: 1px solid transparent;\n    display: block;\n    padding: 0.5ex 1ex;\n    min-width: 2ex;\n  }\n\n  span {\n    background: color-mix(in srgb, var(--color-badge) 40%, var(--color-background));\n    border-color: var(--color-badge-base);\n    color: color-mix(in srgb, var(--color-badge-base) 40%, var(--color-text));\n    border-radius: 6px;\n  }\n}\n"
  },
  {
    "path": "assets/lib/quicklinks.scss",
    "content": "/* Quicklinks */\n\n.quicklinks {\n  margin: 4em 0 2em;\n  padding: 0 0 2em;\n  overflow: hidden;\n\n  ul, li {\n    list-style: none;\n    padding: 0;\n    margin: 0;\n  }\n\n  ul {\n    //@extend .grid\n    -moz-columns: 25ex;\n    -webkit-columns: 25ex;\n    columns: 25ex;\n    -moz-column-gap: 2ex;\n    -webkit-column-gap: 2ex;\n    column-gap: 2ex;\n  }\n\n  li {\n    overflow: hidden;\n\n    //@extend .col\n    //flex: 0 0 20ex\n \n  }\n\n  a {\n    display: block;\n    -moz-box-sizing: border-box;\n    box-sizing: border-box;\n    padding: 0.5ex 0;\n  }\n\n  br {\n    display: none;\n  }\n\n  p {\n    display: inline;\n    margin: 0;\n  }\n}\n\n.top a, a.top {\n  clear: both;\n  display: block;\n  padding: 2em 1em 2em 0;\n  font-size: 86%;\n}\n\n.top a {\n  padding-block-start: 1em;\n\n  &:before {\n    content: \"▴\";\n    padding-inline-end: 0.5ex;\n    text-decoration: none !important;\n  }\n}\n\na.top:before {\n  content: \"▴\";\n  padding-inline-end: 0.5ex;\n  text-decoration: none !important;\n}\n\n.quicklinks {\n  li {\n    min-width: 50%;\n  }\n}\n"
  },
  {
    "path": "assets/lib/screenshot-gallery.js",
    "content": "$(function(){\n  var $next, $prev, touchX, touchY;\n\n  // Prevent scrolling the page (used with CSS no-scroll class)\n  function lockScrolling(bool) {\n    $('html').toggleClass('no-scroll', bool);\n  }\n\n  // Generate the HTML for the zoomed in preview\n  function makePreview(element) {\n    if (!element) return false;\n\n    // Previous and next elements get tracked in the JS enclosure\n    $prev = $('img', $(element).prev('.zoom'));\n    $next = $('img', $(element).next('.zoom'));\n    \n    // Grab the description\n    var desc = $('img', element).attr('alt');\n    // Format next/previous links when they're relevant\n    var prev = $prev.length ? '<a href=\"#\" data-direction=\"prev\" class=\"screenshot-prev prev\"><img alt=\"previous\" src=\"images/site/arrow-left.svg\"></a>' : '';\n    var next = $next.length ? '<a href=\"#\" data-direction=\"next\" class=\"screenshot-next next\"><img alt=\"next\" src=\"images/site/arrow-right.svg\"></a>' : '';\n\n    // Generate jQuery document fragment based on the generated HTML\n    var $html = $('<div id=\"imagePreview\" class=\"image-container zoom-out\">' + prev + '<img src=\"' + element.href + '\" alt=\"' + desc + '\">' + next + '<p>' + desc + \"</p></div>\");\n    \n    return $html;\n  }\n\n  // Show the preview\n  function showPreview(element) {\n    var preview = makePreview(element);\n    $('body').append(preview);\n    lockScrolling(true);\n  }\n\n  // Hotswap the preview for the next or previous\n  function switchPreview(direction) {\n    var $element = (direction == \"next\") ? $next : $prev;\n    if (!$element) return false;\n\n    var code = makePreview($element.parent()[0]);\n    if (!code) return false;\n    \n    // We're transplanting the contents inside the container, to prevent an animation\n    $('#imagePreview').addClass('no-anim').html($(code).children());\n    // Add a pulse class, to make the arrow react to a switch\n    $('.' + direction, '#imagePreview').addClass('pulse');\n  }\n\n  // Close the preview (with a fade and removal)\n  function closePreview(element) {\n    var $element = $('#imagePreview');\n\n    $element.fadeOut(200, function(){\n      $element.remove();\n      lockScrolling(false);\n    });\n  }\n\n  function previewIsVisible() {\n    return $('#imagePreview').is(':visible');\n  }\n\n  // Bind actions to the document; bubbling up events, handled in specific cases\n  $(document).on('click', 'a.screenshot.zoom, .screenshot.zoom a', function(ev){\n    // Generate a screenshot preview when clicking on a screenshot thumbnail\n    showPreview(this);\n    ev.preventDefault();\n  }).on('click', '#imagePreview', function(ev){\n    // Close, unless clicking on a link\n    if (ev.target.nodeName !== 'A') {\n      closePreview();\n    }\n  }).on('click', '.screenshot-next, .screenshot-prev', function(ev){\n    // Switch to the next or previous, when clicking on an link arrow\n    switchPreview(this.getAttribute('data-direction'));\n    ev.preventDefault();\n  }).on('keydown', function(ev) {\n    // Handle keyboard shortcuts\n    var action;\n\n    if (previewIsVisible()) {\n      switch (ev.key) {\n        // arrows\n        case 'ArrowLeft': action = \"prev\"; break;\n        case 'ArrowRight': action = \"next\"; break;\n        case 'ArrowUp': action = \"prev\"; break;\n        case 'ArrowDown': action = \"next\"; break;\n        // Page up / down\n        case 'PageUp': action = \"prev\"; break;\n        case 'PageDown': action = \"next\"; break;\n        // Space, shift+space, and backspace\n        case ' ':\n          if (ev.shiftKey) {\n            action = \"prev\";\n          } else {\n            action = \"next\";\n          }\n          break;\n        case 'Backspace': action = \"prev\"; break;\n        // vi keys\n        case 'h': action = \"prev\"; break;\n        case 'j': action = \"next\"; break;\n        case 'k': action = \"prev\"; break;\n        case 'l': action = \"next\"; break;\n        // wasd\n        case 'w': action = \"prev\"; break;\n        case 's': action = \"next\"; break;\n        case 'a': action = \"prev\"; break;\n        case 'd': action = \"next\"; break;\n        // Escape\n        case 'Escape': action = \"close\"; break;\n      }\n\n      if (!action) return true;\n\n      if (action == \"close\") {\n        closePreview();\n      } else {\n        switchPreview(action);\n      }\n\n      ev.preventDefault();\n    }\n  }).on('wheel', function(ev){\n    // Handle mouse scroll events\n    var action = (ev.originalEvent.deltaY > 0) ? 'next' : 'prev';\n    switchPreview(action);\n  });\n});\n"
  },
  {
    "path": "assets/lib/scrollbar-on.scss",
    "content": "/* Always show the vertical scrollbar, reducing jumps between pages */\nhtml {\n  overflow-y: scroll;\n}\n"
  },
  {
    "path": "assets/lib/search.coffee",
    "content": "---\n---\n\n\"use strict\"\n\n$ ->\n  $form = $('#search-form')\n  $input = $('#search-input')\n  $similar = $('#similar')\n  $similarList = $('#similar-list')\n  $matchesString = $('#matches')\n  $results = $('#results')\n  $progress = $('#progress')\n  template = $('#template').html()\n\n  searchIndex = null\n\n  ajax = new $.Deferred()\n\n  wordsplit = /[\\s,;!?=\\+\"'\\\\\\/]+/\n  typeTimer = null\n\n  generateWordList = ->\n    window.wordlistAll = {}\n\n    searchIndex.pages.forEach (obj, pageId) ->\n      # Uppercase is a work-around to avoid reserved words\n      # (Thanks, JavaScript!)\n      obj.wordlist.toUpperCase().split(/\\s+/).forEach (word) ->\n        return if word == ''\n\n        wordlistAll[word] ||= []\n\n        try\n          wordlistAll[word].push pageId\n        catch e\n          console.log \"Problem:\", word, pageId\n        return\n\n    searchIndex.words = wordlistAll\n\n  loadsearchIndex = ->\n    return if ajax.state() == \"resolved\" && ajax.state() == \"pending\"\n\n    $.get '{{ site.baseurl }}/search.json', (data)->\n      searchIndex = data\n      do generateWordList unless data.words\n      ajax.resolve data\n\n\n  displayResults = (words, matches, similar) ->\n    $pending = $('<div class=\"pending\"/>')\n    pages = searchIndex.pages\n    text = $input.val().toLowerCase().replace(/ ?-\\w+/g, '').replace(/\\+/g, '')\n\n    $('#results-none').hide()\n\n    if matches.length > 0\n      fakedate = (new Date).toISOString()\n\n      matches.sort (a, b) ->\n        # Sort by date\n        dateA = pages[a].date || fakedate\n        dateB = pages[b].date || fakedate\n\n        # Title match score (weighted heavily)\n        titleA = pages[a].title.toLowerCase().score(text)\n        titleB = pages[b].title.toLowerCase().score(text)\n\n        # Summary snippet score (weighted a good bit)\n        summA = pages[a].summary.toLowerCase().score(text)\n        summB = pages[b].summary.toLowerCase().score(text)\n\n        # Date score (very small weight)\n        dateScoreA = Date.parse(dateA.split(' ')[0]) / Date.now() * 0.05\n        dateScoreB = Date.parse(dateB.split(' ')[0]) / Date.now() * 0.05\n\n        # Generate page scores\n        # (and add a 'score' value to the page info)\n        scoreA = pages[a].score = (titleA * 3 + summA + dateScoreA) / 5 / 0.71\n        scoreB = pages[b].score = (titleB * 3 + summB + dateScoreB) / 5 / 0.71\n\n        # Sort based on score\n        return scoreB - scoreA\n\n      for match in matches\n        page = pages[match]\n\n        # Clone search result snippet\n        $snippet = $(template)\n\n        # Add data to the cloned template\n        $snippet.removeClass('hidden')\n          .find('.title').html(page.title).attr('href', page.url).end()\n          .find('.url').html(page.url).attr('href', page.url).end()\n          .find('.summary').html(page.summary).end()\n\n        if page.date\n          $snippet.find('.date').text(page.datestring).end()\n        else\n          $snippet.find('.date').remove().end()\n\n        # Add snippet to pending (off-page) search results\n        $pending.append $snippet\n\n    else\n      if $input.val() != ''\n        $('#results-none').removeClass('hidden').show()\n\n    # Add search results to the page\n    $results.html($pending.children())\n\n    if similar.length > 0\n      $similar.removeClass('hidden').hide()\n      $similarList.html ->\n        result = ''\n\n        $.each similar, (k, v)->\n          rating = \"Score: \" + Math.round(v.score * 50) / 10\n          result += '<a href=\"#%\" title=\"$\">%</a> '.replace(/%/g, v.word).replace(/\\$/, rating)\n\n        return result\n\n      $similar.show()\n    else\n      $similar.hide()\n      $matchesString.hide()\n      $similarList.html('')\n\n    $matchesString\n      .find('.number').html(matches.length).end()\n      .find('.plural').toggle(matches.length != 1).end()\n      .removeClass('hidden').toggle(matches.length != 0)\n\n    $progress.hide()\n    $input.focus()\n\n\n  parseForm = ->\n    $progress.removeClass('hidden').show()\n\n    $.when(ajax).done (data)->\n      text = $input.val()\n      words = text.toLowerCase().trim().split(wordsplit)\n      similar = []\n      matchers = {matches: [], antimatches: []}\n\n      # Search for each word in the text entry\n      for word in words\n        # Check for \"-\" before a word to exclude that word\n        polarity = if word.match(/^-/) then 'antimatches' else 'matches'\n        # Strip dashes at the beginning and periods at the end of a word\n        word = word.replace(/^-/, '').replace(/\\.$/, '')\n        # Search for the existence of words\n        wordMatch = data.words[word.toUpperCase()]\n\n        if wordMatch\n          if matchers[polarity].length < 1\n            # First word; propagate the matches\n            matchers[polarity] = wordMatch\n          else\n            if polarity == 'matches'\n              # Do an AND of matching pages\n              matchers[polarity] = matchers[polarity].map (a) ->\n                return a unless wordMatch.indexOf(a) < 0\n            else\n              # Add unique antimatchers\n              matchers[polarity] = matchers[polarity]\n                .concat wordMatch.filter (item) ->\n                    matchers[polarity].indexOf(item) < 0\n\n        # Add similar words to a 'similar' keyword array\n        if polarity == 'matches'\n          $.map searchIndex.words, (data, key) ->\n            keyLow = key.toLowerCase()\n            matchscore = keyLow.score(word, 0.5)\n\n            if (matchscore > 0.7) &&\n              !similar.filter((s) -> s.word == keyLow)[0] &&\n              word != keyLow\n                similar.push {word: keyLow, score: matchscore}\n\n      # Sort similar words by similarity score\n      similar.sort (a, b) -> a.score < b.score ? a : b\n\n      # Power results with a matches-antimatches reaction\n      results = matchers['matches'].filter (match) ->\n        match if matchers['antimatches'].indexOf(match) < 0\n\n      # Hand off word matches and similar keywords to the renderer\n      displayResults words, results, similar.slice(0,21)\n\n\n  selectForm = ->\n    setTimeout ->\n      $input.focus().select()\n    , 0\n\n\n  updateHash = ->\n    window.location.hash = \"#\" + $input.val().trim()\n\n\n  window.trigger404 = (val) ->\n    if $input.val() == ''\n      keywords= decodeURIComponent(document.location.pathname)\n        .replace val, ''\n        .replace '{{ site.permalink | split: '/' | first }}', ''\n        .replace /.html$/, ''\n        .replace /.md$/, ''\n        .replace /[\\/\\-\\_\\+]/g, ' '\n        .replace /^\\s+|\\s+$/g, ''\n\n      $input.val(keywords)\n      do parseForm\n\n\n  do loadsearchIndex\n\n  $form\n    .on 'keydown', (e)->\n      switch e.key\n        when \"Tab\", \"Down\", \"ArrowDown\"\n          $('#similar a:first,#results a').first().focus()\n          do e.preventDefault\n        when \"Left\", \"ArrowLeft\", \"Right\", \"ArrowRight\", \"Home\", \"End\", \"Esc\", \"Escape\", \"Enter\"\n          # NOOP\n        else\n          unless e.ctrlKey || e.altKey\n            clearTimeout typeTimer\n            typeTimer = setTimeout updateHash, 500\n    .on 'submit', (e)->\n      do updateHash\n      do e.preventDefault\n\n  $similar.on 'keydown', 'a', (e)->\n    switch e.key\n      when \"Right\", \"ArrowRight\"\n        $(@).next().focus()\n      when \"Left\", \"ArrowLeft\"\n        $(@).prev().focus()\n      when \"Up\", \"ArrowUp\"\n        selectForm()\n      when \"Down\", \"ArrowDown\"\n        $('#results a:first').focus()\n      when \" \"\n        $(@).click()\n      when \"Enter\"\n        selectForm()\n\n  $results\n    .on 'keydown', 'a', (e) ->\n      $article = $(@).parentsUntil('#results')\n      switch e.key\n        when \"Down\", \"ArrowDown\"\n          $article.next().find('a:first').focus()\n        when \"Up\", \"ArrowUp\"\n          firstChild = $article.filter(':first-child').length != 1\n          if firstChild\n            selectForm()\n          else\n            $article.prev().find('a:first').focus()\n    .on 'focus', 'a', (e) ->\n      $(@).parentsUntil('#results').addClass('highlight')\n    .on 'blur', 'a', (e) ->\n      $(@).parentsUntil('#results').removeClass('highlight')\n\n  $(document)\n    .on 'keydown', (e) ->\n      switch e.key\n        when \"Esc\", \"Escape\"\n          $input.val('')\n          do updateHash\n\n  $.when(ajax).done (data)->\n    do parseForm\n\n  $(window).on 'hashchange', (e)->\n    val = @location.hash.substr(1)\n    $input.val(decodeURIComponent(val))\n    do parseForm\n\n  # Run a search if the URL is like \"/search/#foo\"\n  $(window).trigger 'hashchange' if window.location.hash\n\n  selectForm()\n"
  },
  {
    "path": "assets/lib/search.scss",
    "content": ".search-page {\n  --pf-v5-global--Color--100: red;\n\n  .search-icon path {\n    fill: green;\n  }\n\n  .search-form {\n    margin-block-end: 1rem;\n    display: flex;\n    gap: 0.5rem;\n    flex-flow: row wrap;\n  }\n\n  .search-input,\n  .search-button {\n    line-height: 2rem;\n    color: var(--color-text);\n    font: inherit;\n    padding: .75ex 2ex;\n  }\n\n  .search-input {\n    border-radius: 6px;\n    border: 1px solid var(--color-grey-dark);\n    background: var(--color-background);\n    position: relative;\n    flex: auto;\n    padding-inline-start: 1.5ex;\n\n    // Make room for the icon\n    @supports (mask: url()) {\n      padding-inline-start: 4.5ex;\n    }\n  }\n\n  .search-input-wrapper {\n    flex: auto;\n    display: flex;\n    position: relative;\n\n    @supports (mask: url()) {\n      &::after {\n        position: absolute;\n        inset: 10px;\n        content: '';\n        background: color-mix(in srgb, var(--color-text) 75%, var(--color-background));\n        mask: url(\"../images/site/search.svg#search-icon\") 0 100% no-repeat;\n        pointer-events: none;\n      }\n    }\n  }\n\n  .search-button {\n    background: var(--color-grey-light);\n    border: 1px solid var(--color-grey-dark);\n    border-radius: 400px;\n\n    &:hover {\n      background: color-mix(in srgb, var(--color-grey-light) 80%, white);\n    }\n  }\n\n  .similar {\n    padding: 1ex 0 2ex;\n    color: var(--color-grey-dark);\n  }\n\n  .progress-container {\n    position: absolute;\n    inset-inline: 0;\n    text-align: center;\n  }\n\n  .spinner {\n    font-size: 6em;\n    margin: 1em auto;\n    color: var(--color-grey);\n  }\n\n  .articles {\n    margin: 1rem 0 0;\n  }\n\n  article.post {\n    padding: 1em 1em 1em;\n    margin: 0 -1em;\n\n    &.highlight {\n      background: rgba(yellow, 0.125);\n      outline: 1px solid rgba(orange, 0.25);\n      border-radius: 6px;\n\n      h2 {\n        background: inherit;\n      }\n    }\n\n    h2 {\n      padding: 0;\n      margin: 0;\n    }\n  }\n\n  .date {\n    padding: 0 0 0.5ex;\n  }\n\n  .post-content {\n    margin: 0;\n  }\n\n  .hidden {\n    display: none;\n  }\n\n  #results-none {\n    text-align: center;\n    padding: 2em 0;\n  }\n}\n"
  },
  {
    "path": "assets/lib/stickyfooter.scss",
    "content": "body {\n  display: flex;\n  min-height: 100vh;\n  flex-direction: column;\n}\n\n#page-wrap {\n  flex: 1;\n}\n"
  },
  {
    "path": "assets/lib/stickyheader.scss",
    "content": "html, body {\n  height: 100%;\n  min-height: 100%;\n}\n\nbody {\n  display: flex;\n  min-height: 100vh;\n  flex-direction: column;\n}\n\n.masthead {\n  flex: 1 0 0;\n}\n\n.page-content {\n  flex: auto;\n  overflow-y: auto;\n}\n"
  },
  {
    "path": "assets/main.js",
    "content": "---\nlayout:\n---\n{% include_relative vendor/jquery.js %}\n{% include_relative lib/browser-support.js %}\n"
  },
  {
    "path": "assets/main.scss",
    "content": "---\n# // Only the main Sass file needs front matter (the dashes are enough)\n# //\n# // Note: Only include Liquid templating in this file.\n# //       It won't work in @imported SASS or SCSS.\n---\n@charset \"utf-8\";\n\n// Set responsive breakpoints for minima\n// (same as what's used for Gridlex — so the two align)\n$on-palm:          35.5em;\n$on-laptop:        48em;\n\n// Set both $spacing-unit (for minima) and $gl-gutter (for gridlex)\n$spacing-unit: 2rem;\n$gl-gutter: $spacing-unit / 2;\n\n// Import styles from site.scss or site.sass or fall back to default.scss\n{% assign _site_style = site.static_files | where_exp: \"item\", \"item.path contains '/assets/site.'\" %}\n{% if _site_style[0] %}\n  @import \"site\";\n{% else %}\n  @import \"default\";\n{% endif %}\n"
  },
  {
    "path": "assets/site/animation.scss",
    "content": "@keyframes fadeIn {\n  0% {\n    opacity: 0;\n  }\n\n  100% {\n    opacity: 1;\n  }\n}\n\n@keyframes zoomWidth {\n  0% {\n    max-width: 0;\n  }\n\n  100% {\n    max-width: 100%;\n  }\n}\n\n@keyframes growIn {\n  0% {\n    font-size: 0;\n    height: 0;\n    max-height: 0;\n    opacity: 0;\n  }\n\n  25% {\n    font-size: auto;\n    height: auto;\n    max-height: 100%;\n    opacity: 0;\n  }\n\n  50% {\n    opacity: 0;\n  }\n\n  100% {\n    opacity: 1;\n  }\n}\n\n@keyframes pulse {\n  25% {\n    opacity: 1;\n  }\n\n  50% {\n    opacity: 0.5;\n  }\n\n  75% {\n    opacity: 1;\n  }\n}\n"
  },
  {
    "path": "assets/site/applications.scss",
    "content": ".apps {\n  .app {\n    padding: 2rem 0.5rem;\n    display: grid;\n    grid-gap: 1rem;\n    align-items: baseline;\n\n    // Mobile first\n    grid-template: \"title tag\" \"description description\" \"meta meta\";\n    grid-template-columns: auto 1fr;\n\n    @media (min-width: $on-laptop) {\n      grid-template: \"title description tag\" \"title meta .\";\n      grid-template-columns: 25% 1fr auto;\n    }\n\n    &:not(:first-child) {\n      border-top: 1px dotted var(--color-grey-dark);\n    }\n\n    &-title {\n      grid-area: title;\n      font-size: 1.3rem;\n      margin: 0;\n      line-height: inherit;\n    }\n\n    &-description {\n      grid-area: description;\n\n      p:last-child {\n        margin-block-end: 0;\n      }\n    }\n\n    &-tag {\n      grid-area: tag;\n      --hue: 150;\n      --saturation: 0%;\n      --color: var(--hue), var(--saturation);\n      border: 1px solid color-mix(in srgb, hsl(var(--color), 40%) 80%, var(--color-background));\n      background: color-mix(in srgb, hsl(var(--color), 40%) 10%, var(--color-background));\n      color: color-mix(in srgb, hsl(var(--color), 30%) 40%, var(--color-text));\n      padding: 0.125em 0.5em;\n      border-radius: 3em;\n      font-size: 0.9rem;\n      white-space: nowrap;\n\n      &.app-official {\n        --hue: 150;\n        --saturation: 50%;\n      }\n\n      &.app-prerelease {\n        --hue: 40;\n        --saturation: 100%;\n      }\n    }\n\n    &-details {\n      grid-area: meta;\n      font-size: 0.9rem;\n      margin: 0;\n\n      dd, dt {\n        margin: 0;\n        padding: 0;\n      }\n\n      dt:not(:first-child) {\n        margin-block-start: 1em;\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "assets/site/fonts.scss",
    "content": "@font-face {\n  font-family: 'RedHatDisplay';\n  src: url('fonts/RedHatDisplay-Regular.woff2') format('woff2');\n  font-style: normal;\n  font-weight: 300;\n  text-rendering: optimizeLegibility;\n}\n\n@font-face {\n  font-family: 'RedHatDisplay';\n  src: url('fonts/RedHatDisplay-Medium.woff2') format('woff2');\n  font-style: normal;\n  font-weight: 400;\n  text-rendering: optimizeLegibility;\n}\n\n@font-face {\n  font-family: 'RedHatDisplay';\n  src: url('fonts/RedHatDisplay-Bold.woff2') format('woff2');\n  font-style: normal;\n  font-weight: 700;\n  text-rendering: optimizeLegibility;\n}\n\n@font-face {\n  font-family: 'RedHatText';\n  src: url('fonts/RedHatText-Regular.woff2') format('woff2');\n  font-style: normal;\n  font-weight: 400;\n  text-rendering: optimizeLegibility;\n}\n\n@font-face {\n  font-family: 'RedHatText';\n  src: url('fonts/RedHatText-Medium.woff2') format('woff2');\n  font-style: normal;\n  font-weight: 700;\n  text-rendering: optimizeLegibility;\n}\n"
  },
  {
    "path": "assets/site/frontpage.scss",
    "content": "$frontpage-content-breakpoint: 42rem;\n\nhtml.front-page {\n  > body {\n    @supports (display: grid) {\n      display: grid;\n      grid-template-rows: auto auto 1fr;\n    }\n  }\n\n  .masthead {\n    margin-block-end: 0;\n\n    a {\n      color: white;\n    }\n  }\n\n  .page-content {\n    padding-block-start: 4rem;\n\n    > .wrapper {\n      display: grid;\n      grid-template-columns: 1fr minmax(auto, 65rem) 1fr;\n      margin: 0;\n      padding: 0 1.5rem;\n      max-width: 100%;\n      --grid-column: 2;\n\n      > * {\n        grid-column: var(--grid-column);\n      }\n    }\n  }\n\n  .frontpage-background {\n    background: var(--color-masthead-background) url(../images/site/clouds-bw.webp);\n    background-blend-mode: screen;\n    background-size: cover;\n    background-repeat: no-repeat;\n    background-position: bottom;\n    backdrop-filter: blur(3px);\n\n    > header.masthead {\n      background: var(--gradient-masthead-shine);\n    }\n  }\n\n  .intro-lede {\n    max-width: 24em;\n    padding: 2rem 8rem 0 1rem;\n    grid-area: lede;\n    font-size: 1.5rem;\n\n    @media (min-width: $on-laptop) {\n      padding: 4rem 0 3rem 4rem;\n      font-size: 1.75rem;\n    }\n  }\n\n  .intro {\n    --remainder: calc((100vw - 65rem) / 2);\n    --offset: 1rem;\n    font-family: var(--font-headline);\n    line-height: 1.4;\n    color: #eeeeec;\n    display: grid;\n    grid-template: \". lede planes .\" \"badge badge badge badge\";\n    grid-template-columns: var(--remainder) auto 1fr var(--remainder);\n    padding: 0;\n\n    .planes {\n      --planes-height: 5rem;\n      --planes-offset: 2.5rem;\n      grid-area: planes;\n      background: url(../images/site/planes.svg) no-repeat right calc(100% - var(--planes-offset));\n      background-size: auto var(--planes-height);\n      grid-row: 1 / -1;\n      grid-column: 1 / -2;\n      margin-inline-end: 1rem;\n\n      @media screen and (min-width: $content-width) {\n        margin-inline-end: 0;\n      }\n    }\n\n    @supports (clip-path: polygon(0 0, 0 0, 0 0, 0 0)) or (-webkit-clip-path: polygon(0 0, 0 0, 0 0, 0 0)) {}\n\n    .side-left {\n      padding: 3rem 1rem 1rem;\n      text-align: center;\n\n      @media screen and (min-width: $content-width) {\n        padding: 1rem;\n\n        p {\n          max-width: 35ex;\n        }\n      }\n    }\n\n    .intro-image {\n      position: relative;\n      margin-block-start: 2rem;\n\n      .screenshot {\n        margin: 0.5rem 0 0;\n        max-height: 12rem;\n        overflow: hidden;\n        display: block;\n      }\n\n      &:before {\n        z-index: 100;\n        content: \"\";\n        position: absolute;\n        width: 100%;\n        height: 100%;\n        box-shadow: inset 0px -20px 15px -15px rgba(0, 0, 0, 0.2);\n        pointer-events: none;\n      }\n    }\n\n    p:first-child:last-child {\n      margin: 0 0.5rem;\n    }\n\n    .grid > div {\n      padding-bottom: 0;\n    }\n\n    ul, li {\n      margin: 0;\n      padding: 0;\n      list-style: none;\n      display: inline;\n    }\n\n    %btn {\n      display: inline-block;\n      background: #eeeeec;\n      border-radius: 6px;\n      box-shadow: 0 3px 0 rgba(46, 61, 86, 1);\n      color: #3e5375;\n      font-size: 18px;\n      line-height: 1.33;\n      margin: 10px 10px 20px 0px;\n      padding: 10px 16px;\n\n      &:hover {\n        text-decoration: none;\n        background: var(--color-background);\n        color: var(--color-text);\n      }\n    }\n\n    li a {\n      @extend %btn;\n    }\n\n    li.with-img img {\n      vertical-align: top;\n      margin: (-1px) 2px 0 0;\n    }\n  }\n\n  .intro-text {\n    padding: 0 0 2rem;\n\n    h2 {\n      font-size: 2rem;\n\n      &:not(:first-child) {\n        padding-block-start: 2rem;\n      }\n    }\n\n    h3 {\n      font-size: 1.5rem;\n\n      &:not(:first-child) {\n        padding-block-start: 1.5rem;\n      }\n    }\n\n    @media (min-width: $on-laptop) {\n      h2 {\n        font-size: 2.953125rem;\n\n        &:not(:first-child) {\n          padding-block-start: 2.5rem;\n        }\n      }\n\n      h3 {\n        font-size: 1.828125rem;\n\n        &:not(:first-child) {\n          padding-block-start: 2rem;\n        }\n      }\n    }\n\n    .audience-list {\n      display: grid;\n      grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr));\n      grid-gap: 1rem 2rem;\n      padding: 0.5rem 1rem;\n\n      strong {\n        display: block;\n      }\n\n      @media (max-width: 32rem) {\n        grid-template-columns: auto;\n      }\n    }\n\n    .using-cockpit {\n      columns: 20rem 2;\n      column-gap: 2rem;\n    }\n  }\n\n  footer.footer-cockpit {\n    margin-block-start: 0;\n  }\n\n  .badge {\n    grid-area: badge;\n    text-align: right;\n    position: relative;\n    inset-block-start: var(--offset);\n\n    &-new,\n    &-version,\n    &-date {\n      transition: all 300ms;\n      font-size: 0.9rem;\n\n      @media (prefers-reduced-motion: reduce) {\n        transition: none;\n      }\n    }\n\n    &-new {\n      font-weight: inherit;\n    }\n\n    &-version {\n      font-size: 1.4rem;\n      font-weight: bold;\n      color: var(--color-link);\n    }\n\n    a {\n      --offset1: var(--offset);\n      --offset2: var(--offset);\n      transition: background 500ms, clip-path 500ms;\n      // Badge color is defined with the other colors in site.scss\n      background: var(--color-badge);\n      display: block;\n      padding: 1.5rem 0 1.25rem;\n      padding: calc((var(--offset) + 0.5vw) * 1.125) 1rem calc((var(--offset) + 0.25vw) * 1);\n      text-decoration: none !important;\n      color: var(--color-text);\n      clip-path: polygon(0 calc(100% - var(--offset1)), 0 calc(100% - var(--offset2)), 100% 100%, 100% 0);\n      display: grid;\n      grid-template-columns: 1fr auto var(--remainder);\n      grid-template-rows: 33%;\n      align-items: baseline;\n      grid-gap: 0 0.5rem;\n\n      @media (prefers-reduced-motion: reduce) {\n        transition: none;\n      }\n\n      @media (max-width: $frontpage-content-breakpoint) {\n        --offset1: calc(100% - 1.5rem);\n        --offset2: 0.5rem;\n      }\n\n      &:hover {\n        background: var(--color-badge-hover);\n\n        > span {\n          opacity: 1;\n        }\n\n        > .badge-version {\n          text-decoration: underline;\n        }\n      }\n    }\n  }\n}\n\n.distro-logos {\n  display: grid;\n  align-items: center;\n  grid-gap: 2.5rem 5rem;\n  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));\n  margin: 3rem 2rem 4rem;\n\n  > li {\n    margin: 0;\n    padding: 0;\n    flex: 1 1 12rem;\n    list-style: none;\n\n    > a {\n      filter: grayscale(1) contrast(50%) brightness(125%);\n      transition: 300ms all;\n\n      @media (prefers-reduced-motion: reduce) {\n        transition: none;\n      }\n\n      &:hover {\n        opacity: 1;\n        filter: grayscale(0);\n      }\n    }\n  }\n\n  img {\n    max-height: 3rem;\n    max-width: 100%;\n  }\n}\n\n.footerlinks {\n  background: var(--color-grey-light);\n  padding: 2rem 0;\n  margin: 4rem 0 2rem;\n  clip-path: polygon(0 32px, 0 calc(100% - 32px), 100% 100%, 100% 0);\n  display: grid;\n  grid-template-columns: repeat(auto-fit, minmax(auto, calc(var(--content-width) / 3)));\n  justify-content: center;\n  align-items: center;\n\n  dl a,\n  dt {\n    padding: 5px 20px;\n  }\n\n  dt {\n    font-weight: bold;\n\n    a {\n      margin: (-5px) -20px;\n    }\n  }\n\n  dd {\n    a {\n      padding-inline-start: 30px;\n    }\n  }\n\n  @extend %link;\n}\n\n.screenshots {\n  display: grid;\n  grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));\n  align-items: center;\n\n  &:hover {\n    > .screenshot {\n      transition: opacity 100ms ease-in-out;\n\n      @media (prefers-reduced-motion: reduce) {\n        transition: none;\n      }\n    }\n\n    > :not(:hover) {\n      opacity: 0.75;\n      transition-duration: 200ms;\n\n      @media (prefers-reduced-motion: reduce) {\n        transition: none;\n      }\n    }\n  }\n\n  > .screenshot {\n    opacity: 1;\n    margin: 0.5rem;\n    box-shadow: none;\n\n    &, > img {\n      transition: all 100ms ease-in-out;\n\n      @media (prefers-reduced-motion: reduce) {\n        transition: none;\n      }\n    }\n\n    &:hover {\n      z-index: 2;\n      outline-offset: 0;\n      cursor: pointer;\n\n      > img {\n        outline: 2px solid hsl(var(--color-link-base), 40%);\n        transform: scale(125%);\n        transition-duration: 200ms;\n        box-shadow: 0 0.125rem 1rem hsla(0, 0, 0%, 50%);\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "assets/site/guide.scss",
    "content": "// Hide guide version notice\n.cockpit-guide .book > .titlepage:first-child {\n  display: none;\n}\n\nhtml.cockpit-guide {\n  body {\n    /* Guide CSS has padding-block-start set as important; let's override to fix Chrome */\n    padding-block-start: 0 !important;\n    position: relative;\n\n    // Override the font for guides\n    div.book,\n    div.refentry,\n    div.chapter,\n    div.article,\n    div.reference,\n    div.index,\n    div.footer,\n    div.section,\n    div.part,\n    div.variablelist table {\n      font-family: inherit;\n    }\n\n    // Same list as above, but also a <pre>\n    div.book,\n    div.refentry,\n    div.chapter,\n    div.article,\n    div.reference,\n    div.index,\n    div.footer,\n    div.section,\n    div.part,\n    div.variablelist table,\n    pre.programlisting {\n      color: inherit;\n      font-size: inherit;\n      line-height: inherit;\n    }\n\n    .programlisting {\n      @extend .highlighter-rouge;\n      @extend pre;\n    }\n  }\n\n  /* Evil hack to deconstruct tables\n   * as we don't have any way to rewrite the HTML here, it's pretty bad\n   * but the variable list doesn't use semantic tables anyway\n   * so a11y is questionable at best\n   * it really should be a dl (with dt, dd) */\n\n  div.variablelist {\n    th, td {\n      padding: 0;\n    }\n\n    @media screen and (max-width: $on-laptop) {\n      table tr {\n        display: flex;\n        flex-direction: column;\n\n        .term {\n          display: block;\n          margin-block-end: 0.5rem;\n        }\n\n        &:not(:last-child) {\n          margin-block-end: 3rem;\n        }\n\n        p:last-child {\n          margin-block-end: 0 !important;\n        }\n      }\n    }\n  }\n\n  header.masthead {\n    margin-block-end: 0;\n  }\n\n  table.navigation {\n    background: transparent !important;\n    height: auto;\n    margin: auto;\n    max-width: 64rem;\n    order: 1;\n    position: static !important;\n\n    th, td {\n      height: 3rem;\n      line-height: 3rem;\n    }\n\n    td:last-child {\n      width: 100%;\n      text-align: right;\n    }\n\n    th {\n      text-align: center !important;\n      font-family: var(--font-headline);\n      font-size: 1.75rem !important;\n\n      display: none;\n\n      > p {\n        font: inherit !important;\n        margin: 0;\n      }\n    }\n\n    @extend %link;\n\n    a {\n      align-items: center;\n      height: 100%;\n      padding: 0 0.5rem;\n      text-decoration: none;\n      display: inline-flex;\n\n      &:before,\n      &:after {\n        font-family: var(--font-base-family);\n        font-size: var(--font-base-size);\n        line-height: var(--base-line-height);\n        vertical-align: middle;\n        margin: 0.5em;\n      }\n\n      img {\n        opacity: 0.6;\n        min-width: 24px;\n\n        @media (prefers-color-scheme: dark) {\n          filter: invert(1);\n        }\n      }\n\n      &:hover img {\n        opacity: 1;\n      }\n    }\n\n    @media screen and (min-width: $on-laptop) {\n      a[accesskey=p]:after {\n        content: \"Previous\";\n      }\n\n      a[accesskey=u]:after {\n        content: \"Up\";\n      }\n\n      a[accesskey=h]:after {\n        content: \"Contents\";\n      }\n\n      a[accesskey=n]:before {\n        content: \"Next\";\n      }\n    }\n  }\n\n  .releaseinfo {\n    text-align: center;\n  }\n\n  div.toc {\n    margin: 0 0 3rem;\n\n    p:first-child > b {\n      display: block;\n      font-family: var(--font-headline);\n      font-size: 1.72rem;\n      font-weight: normal;\n      padding: 1rem 0;\n    }\n  }\n\n  dl.toc {\n    dd, dt {\n      padding-inline-start: 3ex;\n    }\n\n    > dd > dl {\n      margin-block-end: 3ex;\n\n      dl {\n        margin: 1ex 0 2ex;\n      }\n    }\n\n    a {\n      text-decoration: underline;\n    }\n  }\n\n  h2, h3, h4, h5, h6,\n  dl.toc .part {\n    position: static;\n    padding: 1rem 0 0.5rem;\n  }\n\n  h2,\n  dl.toc .part {\n    font-size: 1.72rem;\n  }\n\n  h3 {\n    font-size: 1.4rem;\n  }\n\n  .refnamediv h2,\n  [role=main] > .titlepage:first-child .title {\n    font-size: 2.75rem;\n    margin-block-end: 2rem;\n    line-height: 1.2;\n    padding-block-start: 0;\n  }\n\n  [role=main],\n  div.chapter,\n  div.reference,\n  div.refentry {\n    padding: 4rem 2rem 0;\n    max-width: calc(65rem - 4rem);\n    margin-inline: auto;\n    flex: auto;\n\n    @media screen and (max-width: $on-laptop) {\n      max-width: calc(100vw - 4rem);\n    }\n  }\n\n  .refentry {\n    table {\n      color: var(--color-text);\n    }\n  }\n\n  .refnamediv > table td {\n    padding: 0 !important;\n    color: var(--color-text);\n  }\n\n  hr {\n    max-width: calc(65rem - (1rem * 2));\n    margin: auto;\n  }\n\n  .book {\n    dl.toc > dt {\n      margin: 6ex 0 3ex;\n      font-size: 120%;\n      font-weight: bold;\n    }\n  }\n\n  a[name] {\n    position: relative;\n    inset-block-start: -3rem;\n  }\n\n  [role=main] {\n    @extend %link;\n  }\n\n  @media screen and (max-width: $on-laptop) {\n    table.navigation {\n      th {\n        font-size: 1.2rem !important;\n      }\n    }\n\n    pre {\n      max-width: calc(100vw - 6rem);\n      overflow: auto;\n    }\n  }\n}\n\n/* Adapt warnings to Cockpit's PF4 inspired style */\ndiv.warning {\n  margin-inline: 0 !important;\n  @extend %alert;\n  @extend .warning;\n\n  > .title,\n  > h3,\n  > p {\n    padding: 0;\n    margin: 0;\n    font-size: inherit;\n\n    + p:not(:first-of-type) {\n      margin-block-start: 1rem;\n    }\n  }\n}\n"
  },
  {
    "path": "assets/site.scss",
    "content": "// // Variables for SASS\n\n// Gridlex\n$spacing-unit: 1rem;\n\n// Redefine laptop breakpoint\n$on-laptop: 52rem;\n\n// Minima defaults\n$base-font-family: RedHatText, Open Sans, PT Sans, Helvetica Neue, Helvetica, Arial, Liberation Sans, sans-serif;\n$base-font-size: 1.125rem;\n$base-font-weight: 400;\n$small-font-size: $base-font-size * .875;\n$base-line-height: 1.5;\n$content-width: 65rem;\n\n// Import fonts\n@import 'site/fonts';\n\n// Import partials from the `minima` theme.\n@import 'minima';\n\n// Unset parts of minima (currently styled tables)\n@import 'lib/minima-unset';\n\n// Import grid (see http://gridlex.devlint.fr/ for docs)\n//@import vendor/gridlex\n\n// Styles for the search page\n@import 'lib/search';\n\n// Default blog style\n@import 'lib/blog';\n\n// Blog pagination\n@import 'lib/pagination';\n\n// Stretch page with footer on bottom\n@import 'lib/stickyfooter';\n\n// Stop page shift by keeping scrollbar on\n@import 'lib/scrollbar-on';\n\n// Import site pieces\n@import 'site/guide';\n@import 'site/animation';\n@import 'site/frontpage';\n@import 'site/applications';\n\n// // Our variables\n:root {\n  // Map SASS variables for minima into CSS variables\n  --font-base-family: #{$base-font-family};\n  --font-base-size: #{$base-font-size};\n  --font-base-weight: #{$base-font-weight};\n  --font-small-size: #{$small-font-size};\n  --base-line-height: #{$base-line-height};\n  --content-width: #{$content-width};\n\n  --color-text: #333;\n  --color-background: #fff;\n  --color-brand-base-lightness: 52.2%;\n  --color-brand-base-hue: 255.83;\n  --color-brand-base-chroma: 0.177;\n  --color-brand-base: var(--color-brand-base-chroma) var(--color-brand-base-hue);\n  --color-brand: oklch(var(--color-brand-base-lightness) var(--color-brand-base));\n\n  --color-black: #000;\n  --color-white: #fff;\n  --color-grey: #ccc;\n  --color-grey-light: color-mix(in srgb, var(--color-grey) 20%, var(--color-background));\n  --color-grey-dark: color-mix(in srgb, var(--color-grey) 45%, var(--color-text));\n\n  --color-border: var(--color-grey-dark);\n\n  // Mix PF gold-50 and gold-100\n  --color-badge-highlight: 70%;\n  --color-badge-base: oklch(83.54% 0.148 85.65);\n  --color-badge: color-mix(in srgb, var(--color-badge-base) 40%, var(--color-background));\n  --color-badge-hover: color-mix(in srgb, var(--color-badge) var(--color-badge-highlight), white);\n\n  --color-link-brightness: 52.2%\n\n  --color-link-base: 0.177 255.83;\n  --color-link-base-lightness: 52.2%;\n  --color-link: oklch(var(--color-link-base-lightness) var(--color-brand-base));\n\n  --opacity-link-underline: 25%;\n  --color-link-underline: color-mix(in srgb(--color-link) var(--opacity-link-underline), transparent);\n\n  --color-link-visited: color-mix(\n      in srgb,\n      color-mix(in oklch, var(--color-link), #c60 33%) 95%,\n      var(--color-background)\n    );\n  --color-link-hover: color-mix(in srgb, var(--color-link) 85%, white);\n  --color-link-visited-hover: color-mix(in srgb, var(--color-link-visited) 85%, white);\n\n  --color-accent: #fff;\n  --color-accent-background: transparent;\n  --color-accent-highlight: var(--color-background);\n  --color-accent-links: #fff;\n\n  --color-masthead-lightness: 42%;\n  --color-masthead-chroma: var(--color-brand-base-chroma);\n  --color-masthead-hue: var(--color-brand-base-hue);\n  --color-masthead-background: oklch(var(--color-masthead-lightness) var(--color-masthead-chroma) var(--color-masthead-hue));\n\n  --gradient-masthead-shine: linear-gradient(\n    to bottom,\n    oklch(var(--color-masthead-chroma) var(--color-masthead-hue)) 1rem,\n    color-mix(in srgb, var(--color-masthead-background), transparent 100%)\n  );\n\n  --font-headline: RedHatDisplay, RedHatText, Cantarell, Roboto Slab, Helvetica Neue, Helvetica, Arial, Liberation Sans, sans-serif;\n\n  --gutter-width: calc((100vw - 65rem) / 2);\n\n  // Out of gamut, but used for mixing\n  --color-code-pigment: oklch(65% 0.35 285);\n\n  // Dark mode\n  @media (prefers-color-scheme: dark) {\n    // Swap light and dark\n    --color-text: #eee;\n    --color-background: #111;\n    --color-black: #fff;\n    --color-white: #000;\n\n    // Adjust brightness\n    --color-link-base-lightness: 80%;\n    --color-badge-highlight: 90%;\n    --color-masthead-lightness: 25%;\n    --color-masthead-chroma: 0.08;\n\n    // Add filter for greyscaling and inverting logos in dark mode\n    --dark-image-invert: saturate(0%) brightness(0.7) contrast(10) invert(100%);\n  }\n}\n\nbody {\n  background: var(--color-background);\n  color: var(--color-text);\n}\n\n.hidden {\n  display: none;\n}\n\n[id] {\n\tscroll-margin-block-start: var(--scroll-margin, 2rem);\n}\n\n:where(h1, h2, h3, h4, h5, h6, blockquote, dl, ol, ul, figure, p, pre) {\n  margin-block-end: .5em;\n}\n\n:where(h1, h2, h3, h4, h5, h6) {\n  font-family: var(--font-headline);\n\n  > code,\n  > pre {\n    font-size: .9em;\n  }\n}\n\nh1 {\n  font-size: 1.5rem;\n}\n\nh2 {\n  font-size: 1.4rem;\n}\n\nh3 {\n  font-size: 1.3rem;\n}\n\nh4 {\n  font-size: 1.2rem;\n}\n\nh5 {\n  font-size: 1.1rem;\n}\n\nh6 {\n  font-size: 1rem;\n}\n\n.no-scroll {\n  overflow: hidden;\n}\n\n%link {\n  a[href] {\n    color: var(--color-link);\n    text-decoration: underline;\n    text-decoration-color: var(--color-link-underline);\n    text-decoration-thickness: 1px;\n    text-underline-offset: 3px;\n    transition: text-decoration-thickness 300ms, text-underline-offset 300ms;\n\n    &:hover,\n    &:active {\n      --color-link-base-lightness: 55%;\n      --opacity-link-underline: 40%;\n      text-decoration-thickness: 2px;\n      text-underline-offset: 2px;\n      color: var(--color-link-hover);\n    }\n\n    &:visited {\n      color: var(--color-link-visited);\n    }\n\n    &:visited:hover,\n    &:active:hover {\n      color: var(--color-link-visited-hover);\n    }\n  }\n}\n\n.page-content,\n.footer-cockpit,\n.cockpit-guide .book,\n.cockpit-guide .chapter {\n  @extend %link;\n}\n\n.page-content {\n  padding-block-start: 4rem;\n\n  > .wrapper {\n    padding-inline: 1.5rem;\n  }\n\n  dl {\n    margin: 1em;\n\n    dt {\n      font-weight: bold;\n      margin-block-start: 2em;\n\n      &:first-child {\n        margin-block-start: 1em;\n      }\n    }\n\n    dd {\n      margin: 1em 2em;\n    }\n  }\n\n  ul,\n  ol {\n    margin-inline-start: 1.5rem;\n  }\n}\n\nhtml[class*=-Contributing] .nav--contribute,\nhtml[class*=-path-blog] .nav--blog,\nhtml.-path-running .nav--try-it-out,\nhtml.-path-running .nav--install,\nhtml.-path-documentation .nav--documentation,\nhtml.cockpit-guide .nav--documentation,\nhtml[class*=-path-search] .nav--search {\n  a {\n    background: linear-gradient(\n      to top,\n      color-mix(in srgb,\n        var(--color-accent-links) 33%,\n        var(--color-accent-highlight)\n      ) 10px,\n      transparent 10px\n    );\n  }\n}\n\nheader.masthead {\n  --logo-height: 48px;\n  --logo-width: 208px;\n  --header-bg: color-mix(var(--color-black), transparent 60%);\n  --header-line: 10px;\n\n  margin: 0;\n  color: var(--color-background);\n  display: flex;\n  line-height: var(--logo-height);\n  position: relative;\n  background: var(--color-masthead-background);\n  align-items: center;\n\n  h1 {\n    .logo {\n      height: var(--logo-height);\n      width: var(--logo-width);\n\n      @media screen and (min-width: $on-laptop) {\n        display: block;\n      }\n    }\n  }\n\n  a {\n    padding: 1rem;\n    display: block;\n    color: var(--color-accent-links);\n  }\n\n  .hgroup,\n  .nav-wrap {\n    flex: auto;\n    font-family: var(--font-headline);\n  }\n\n  h1,\n  ul {\n    margin: 0;\n  }\n\n  .nav-menu {\n\n    &,\n    & li {\n      list-style: none;\n      margin: 0;\n      padding: 0;\n    }\n  }\n\n  li.nav--home {\n    display: none !important;\n  }\n\n  .nav-wrap ul {\n    display: flex;\n    justify-content: space-evenly;\n    text-align: center;\n    flex-flow: wrap;\n\n    li {\n      flex: auto;\n    }\n\n    @media screen and (max-width: $on-laptop) {\n      line-height: 1;\n\n      li {\n        min-width: 5em;\n      }\n    }\n  }\n\n  @media screen and (min-width: $on-laptop) {\n    padding: 0 var(--gutter-width);\n    align-items: space-between;\n\n    .hgroup {\n      flex: none;\n    }\n\n    .nav-wrap {\n      margin: 0 1rem;\n    }\n  }\n\n  @media screen and (max-width: $on-laptop) {\n    flex-direction: column;\n\n    .logo {\n      margin-block-end: 1rem;\n    }\n\n    .hgroup,\n    .nav-wrap {\n      text-align: center;\n      width: 100%;\n      margin: 0;\n    }\n\n    .hgroup a {\n      padding: 1rem 1rem 0;\n      display: block;\n    }\n\n    .nav-wrap {\n      line-height: var(--logo-height);\n\n      a {\n        padding: 1rem 2ex;\n      }\n    }\n  }\n}\n\npre {\n  white-space: pre-wrap;\n}\n\nhtml.running-cockpit {\n  .os-instructions {\n    display: none;\n    margin-block-start: 10px;\n  }\n\n  .support-table {\n    border-collapse: collapse;\n    margin-block-start: -1rem;\n    max-width: 100%;\n    overflow: hidden;\n\n    a {\n      display: block;\n      line-height: 3rem;\n      padding: .5ch 2ch;\n    }\n\n    img {\n      --optimal-size: 2.5rem;\n      --multiplier: 1;\n      margin: 1rem 0;\n      max-height: calc(var(--optimal-size) * var(--multiplier));\n      width: auto;\n\n      filter: var(--dark-image-invert);\n    }\n\n    tr:nth-child(odd) td {\n      background: color-mix(in srgb, var(--color-text) 6%, var(--color-background));\n    }\n\n    th {\n      font-weight: normal;\n      color: var(--color-grey-dark);\n    }\n\n    td {\n      padding: 0;\n      border: 1px solid color-mix(in srgb, var(--color-text) 18%, var(--color-background));\n      text-align: left;\n\n      // Checkmarks\n      &:not(:first-child):not(:last-child) {\n        text-align: center;\n        font-size: 2rem;\n        color: color-mix(in srgb, oklch(80% 0.133 151) 70%, var(--color-text));\n      }\n\n      &:last-child {\n        width: 0;\n        white-space: nowrap;\n      }\n    }\n\n    /* Size overrides, to visually balance the various logos */\n\n    a[href*=debian] img {\n      --multiplier: .8;\n    }\n\n    a[href*=ubuntu] img {\n      --multiplier: .75;\n    }\n\n    a[href*=tumbleweed] img {\n      --multiplier: .55;\n    }\n\n    @media screen and (max-width: 46rem) {\n      a {\n        padding: 1ch;\n      }\n\n      th:not(:first-child) {\n        font-size: .85rem;\n        transform: rotate(-30deg);\n        height: 3rem;\n        padding: 0;\n        width: 7ch;\n        max-width: 7ch;\n      }\n\n      td:not(:first-child):not(:last-child) {\n        font-size: 32px;\n      }\n\n      th:last-child,\n      td:last-child {\n        display: none;\n      }\n    }\n  }\n\n  h4 {\n    margin-block-start: 3em;\n    font-size: 22px;\n  }\n\n  .browser-support,\n  .os-list {\n    li {\n      list-style: none;\n    }\n  }\n\n  ol {\n    li {\n      > p {\n        margin: 0 0 1rem;\n\n        + p {\n          margin-block-start: 1rem;\n        }\n      }\n\n      &:not(:first-child) {\n        margin-block-start: 2rem;\n      }\n    }\n  }\n}\n\n.-path-running-safari .page-content ol {\n  @media (min-width: $on-laptop) {\n    margin: 2rem 2rem 3rem;\n  }\n\n  li + li {\n    margin-block-start: 2rem;\n  }\n\n  img {\n    max-width: 250px;\n    height: auto;\n    display: inline-block;\n\n    &.full-width {\n      max-width: 100%;\n    }\n\n    + img {\n      @media (min-width: $on-laptop) {\n        margin-inline-start: 1rem;\n      }\n    }\n  }\n\n  .safari-icon {\n    // Will use max-width for images\n    width: 100%;\n  }\n}\n\n.side-by-side {\n  display: flex;\n  align-items: start;\n  grid-gap: .5rem;\n\n  > img {\n    max-width: 100%;\n    height: auto;\n    margin: 0 !important;\n  }\n}\n\nimg.screenshot,\n:is(a, p).screenshot img {\n  border: 1px solid hsl(90, 0%, 80%);\n  background: hsl(90, 0%, 80%);\n}\n\n.screenshot.left img {\n  display: inline;\n  text-align: left;\n}\n\n.image-container {\n  position: fixed;\n  inset: 0;\n  z-index: 1000;\n  display: flex;\n  flex-direction: column;\n  align-content: center;\n  padding: 1rem;\n\n  &:before {\n    display: block;\n    content: '';\n    position: absolute;\n    inset: 0;\n    background: rgba(#000, .7);\n    animation: 200ms fadeIn;\n    z-index: -1;\n\n    @media (prefers-reduced-motion: reduce) {\n      animation: none;\n    }\n  }\n\n  > img {\n    margin: auto auto 0;\n    max-width: 100%;\n    border: none;\n    max-height: calc(100% - 5rem);\n    box-shadow: none;\n  }\n\n  &:not(.no-anim)> img {\n    animation: 300ms ease-in-out fadeIn, 300ms ease-in-out zoomWidth;\n\n    @media (prefers-reduced-motion: reduce) {\n      animation: none;\n    }\n  }\n\n  p {\n    background: color-mix(in srgb, var(--color-black) 50%, transparent);\n    border-radius: 3ex;\n    color: var(--color-white);\n    margin: 1ex auto auto;\n    padding: .5ex 2ex;\n    text-shadow: 1px 1px 3px var(--color-black);\n    animation: 300ms ease-in-out fadeIn;\n    text-align: center;\n\n    @media (prefers-reduced-motion: reduce) {\n      animation: none;\n    }\n  }\n\n  a {\n    position: absolute;\n    inset-block: 5vw;\n    width: 10vw;\n    width: max(20vw, 5rem);\n    opacity: .5;\n    display: flex;\n\n    > img {\n      max-width: 2rem;\n      margin: auto;\n      pointer-events: none;\n    }\n\n    &:hover,\n    &:focus {\n      opacity: 1;\n    }\n\n    &.pulse {\n      animation: 400ms ease-out pulse;\n    }\n\n    &.screenshot-prev {\n      inset-inline-start: 0;\n\n      > img {\n        margin-inline-start: 2rem;\n      }\n    }\n\n    &.screenshot-next {\n      inset-inline-end: 0;\n\n      > img {\n        margin-inline-end: 2rem;\n      }\n    }\n  }\n}\n\n.zoom {\n  cursor: zoom-in;\n}\n\n.zoom-out {\n  cursor: zoom-out;\n}\n\nabbr {\n  cursor: help;\n\n  // Webkit does not support combining these values with a shorthand text-decoration\n  text-decoration: underline;\n  text-decoration-color: var(--color-grey-light);\n  text-decoration-skip-ink: none;\n  text-decoration-style: wavy;\n  text-decoration-thickness: 1px;\n  text-underline-offset: .2em;\n}\n\na > abbr {\n  text-decoration-color: var(--color-background);\n  text-decoration-style: dotted;\n  text-decoration-thickness: 2px;\n}\n\nfooter.footer-cockpit {\n  font-size: .8rem;\n  text-align: center;\n  padding: .5em var(--gutter-width);\n  display: flex;\n  flex-wrap: wrap;\n  justify-content: space-around;\n  align-items: center;\n\n  @media screen and (min-width: $on-laptop) {\n    padding: .5em var(--gutter-width);\n  }\n\n  @media screen and (max-width: 64rem) {\n    >.copyright {\n      flex-basis: 24em;\n    }\n  }\n\n  > p {\n    flex-grow: 1;\n    margin: 0;\n    padding: .5em 1em;\n  }\n\n  a {\n    font-weight: bold;\n  }\n}\n\n.browser-support {\n  --browser-support-columns: 1;\n  display: grid;\n  grid-gap: 1rem;\n  grid-template-columns: repeat(var(--browser-support-columns), minmax(10rem, 1fr));\n  margin: 1rem 0 3rem;\n\n  @media (min-width: 34rem) {\n    --browser-support-columns: 2;\n  }\n\n  @media (min-width: 48rem) {\n    --browser-support-columns: 3;\n  }\n\n  > li {\n    display: flex;\n    display: grid;\n    grid-template-columns: auto 1fr;\n    grid-gap: 0 .75rem;\n    align-items: start;\n  }\n\n  img {\n    width: 2rem;\n    height: auto;\n    min-height: 2rem;\n  }\n\n  .browser-name {\n    // Adjust for the difference between the icon height and the text height\n    // (We align to the top instead of to the center in the cases where text wraps)\n    padding-block-start: .125rem;\n  }\n\n  .browser-firefox > img {\n    position: relative;\n\n    // Firefox's tail is slightly taller\n    inset-block-start: -1px;\n  }\n\n  .note-safari {\n    font-size: .8em;\n    grid-column: 2;\n    font-style: normal;\n  }\n}\n\n#browser-support {\n\n  &[data-browser-supported='true'] .is-not-supported,\n  &:not([data-browser-supported='true']) .is-supported {\n    display: none;\n  }\n\n  .is-supported,\n  .is-not-supported {\n    --support-pigment: oklch(70% 0.2 var(--support-hue));\n    align-items: center;\n    background: color-mix(in srgb, var(--support-pigment) 15%, var(--color-background));\n    border-radius: 3px;\n    color: color-mix(in srgb, var(--support-pigment) 40%, var(--color-text));\n    display: inline-flex;\n    padding: 1rem 2rem 1rem 1.5rem;\n    gap: .5em;\n  }\n\n  .is-supported {\n    --support-hue: 130;\n  }\n\n  .is-not-supported {\n    --support-hue: 37;\n  }\n\n  img {\n    height: 3ch;\n    width: auto;\n  }\n}\n\narticle {\n  a {\n    color: inherit;\n  }\n}\n\n.post-content :is(h2, h3, h4, h5, h6) {\n  margin-block-start: 2em;\n  margin-block-end: .5em;\n}\n\n.post-link {\n  font-size: inherit;\n}\n\n.search-page .articles {\n  article.post {\n    margin-block-start: 0;\n    margin-block-end: 0;\n\n    h2 {\n      margin: 0 0 .5rem;\n      font-size: 150%;\n    }\n  }\n}\n\n.search-input {\n  background-color: var(--color-background);\n  color: var(--color-text);\n  border: 1px solid var(--color-border);\n  border-radius: 2px;\n\n  &:focus {\n    border-color: var(--color-link);\n    box-shadow: 0 0 2px var(--color-link);\n  }\n}\n\n/* Display the article list in a grid */\n@supports (display: grid) {\n  .blog-posts-list>.articles {\n    display: grid;\n    grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));\n    grid-gap: 2rem;\n\n    > article {\n      margin: 0 !important;\n    }\n  }\n}\n\npre,\ncode {\n  border: 1px solid color-mix(in srgb, var(--color-code-pigment) 30%, var(--color-background));\n  background: color-mix(in srgb, var(--color-code-pigment) 15%, var(--color-background));\n  color: color-mix(in srgb, var(--color-code-pigment) 30%, var(--color-text));\n}\n\n.highlighter-rouge {\n  margin: 1rem 0;\n\n  .highlight {\n    background: color-mix(in srgb, var(--color-code-pigment) 15%, var(--color-background));\n  }\n}\n\n.post-title {\n  letter-spacing: 0;\n}\n\n%alert {\n  --hue-info: 243;\n  --hue-success: 129;\n  --hue-warning: 80;\n  --hue-danger: 29;\n\n  --alert-hue: var(--hue-info);\n  --alert-chroma: 0.3;\n\n  --brightness-alert: 75%;\n  --brightness-alert-text: 50%;\n  --color-alert-background: oklch(var(--brightness-alert) var(--alert-chroma) var(--alert-hue) / 15%);\n  --color-alert-border: oklch(var(--brightness-alert) var(--alert-chroma) var(--alert-hue));\n  --color-alert-icon: oklch(var(--brightness-alert) var(--alert-chroma) var(--alert-hue));\n  --color-alert-text: oklch(var(--brightness-alert-text) var(--alert-chroma) var(--alert-hue));\n\n  @media (prefers-color-scheme: dark) {\n    --brightness-alert: 65%;\n    --brightness-alert-text: 82%;\n  }\n\n  --icon: url(/images/site/alert-default.svg);\n  --icon-width: 1em;\n  --icon-height: 1em;\n  --line-height: var(--base-line-height);\n  --icon-offset: calc(((var(--line-height) * 1em) - var(--icon-height)) / 2);\n  --alert-padding-size: 1rem;\n  color: var(--color-alert-text);\n  background: var(--color-alert-background);\n  border: 1px solid var(--color-alert-border);\n  border-inline-start-width: 4px;\n  margin: 2rem 0;\n  padding: var(--alert-padding-size);\n  position: relative;\n\n  i,\n  em {\n    font-style: normal;\n  }\n\n  @supports (mask: url()) {\n    padding-inline-start: calc(var(--icon-width) + (var(--alert-padding-size) * 1.5));\n\n    &::before {\n      background: var(--color-alert-icon);\n      content: '';\n      height: var(--icon-height);\n      width: var(--icon-width);\n      margin-block-start: var(--icon-offset);\n      mask-size: cover;\n      mask-image: var(--icon);\n      position: absolute;\n      inset: var(--alert-padding-size) auto auto var(--alert-padding-size);\n    }\n  }\n}\n\n.info,\n.note {\n  --icon: url(../images/site/alert-info.svg);\n  --alert-hue: var(--hue-info);\n  @extend %alert;\n}\n\n.success {\n  --icon: url(../images/site/alert-success.svg);\n  --alert-hue: var(--hue-success);\n  @extend %alert;\n}\n\n.warning,\n.warn {\n  --icon: url(../images/site/alert-warning.svg);\n  --alert-hue: var(--hue-warning);\n  --icon-width: calc(var(--icon-height) / 16 * 18);\n  @extend %alert;\n}\n\n.danger,\n.error {\n  --icon: url(../images/site/alert-danger.svg);\n  --alert-hue: var(--hue-danger);\n  @extend %alert;\n}\n\n#markdown-toc {\n  margin: 2rem 0;\n\n  li > a {\n    display: inline-block;\n    padding: .25rem 0;\n  }\n\n  > li {\n    list-style: none;\n    margin: 0;\n\n    > a {\n      font-size: 1.3rem;\n      font-weight: bold;\n    }\n  }\n\n  > li > ul {\n    margin-block-start: .5rem;\n    margin-block-end: 1rem;\n  }\n\n  > li > ul > li {\n    margin-block-end: .25rem;\n  }\n}"
  },
  {
    "path": "assets/vendor/gridlex-vars.scss",
    "content": "//************************\n//    VARIABLES\n//************************\n$gl-gridName:   grid !default;\n$gl-colName:   col !default;\n$gl-gutter:    1rem !default; // Total\n$gl-col-bottom: $gl-gutter !default;\n\n$gl-xs:        \"screen and (max-width: 35.5em)\" !default; // up to 568px\n$gl-sm:        \"screen and (max-width: 48em)\" !default; // max 768px\n$gl-md:        \"screen and (max-width: 64em)\" !default; // max 1024px\n$gl-lg:        \"screen and (max-width: 80em)\" !default; // max 1280px\n\n$glp_col-1: (100%/12);\n$glp_col-2: ($glp_col-1*2);\n$glp_col-3: ($glp_col-1*3);\n$glp_col-4: ($glp_col-1*4);\n$glp_col-5: ($glp_col-1*5);\n$glp_col-6: ($glp_col-1*6);\n$glp_col-7: ($glp_col-1*7);\n$glp_col-8: ($glp_col-1*8);\n$glp_col-9: ($glp_col-1*9);\n$glp_col-10: ($glp_col-1*10);\n$glp_col-11: ($glp_col-1*11);\n$glp_col-12: 100%;\n\n$glp_col-5-12: (100%/5);\n$glp_col-7-12: (100%/7);\n$glp_col-8-12: (100%/8);\n$glp_col-9-12: (100%/9);\n$glp_col-10-12: (100%/10);\n$glp_col-11-12: (100%/11);\n\n// Function to generate the grid by number\n@mixin makeGridByNumber($grid)\n{\n  [class*=\"#{$grid}-1\"] > .#{$gl-colName}, [class*=\"#{$grid}-1\"] > [class*='#{$gl-colName}-']{ flex-basis: $glp_col-12; max-width: $glp_col-12; }\n  [class*=\"#{$grid}-2\"] > .#{$gl-colName}, [class*=\"#{$grid}-2\"] > [class*='#{$gl-colName}-']{ flex-basis: $glp_col-6; max-width: $glp_col-6; }\n  [class*=\"#{$grid}-3\"] > .#{$gl-colName}, [class*=\"#{$grid}-3\"] > [class*='#{$gl-colName}-']{ flex-basis: $glp_col-4; max-width: $glp_col-4; }\n  [class*=\"#{$grid}-4\"] > .#{$gl-colName}, [class*=\"#{$grid}-4\"] > [class*='#{$gl-colName}-']{ flex-basis: $glp_col-3; max-width: $glp_col-3; }\n  [class*=\"#{$grid}-5\"] > .#{$gl-colName}, [class*=\"#{$grid}-5\"] > [class*='#{$gl-colName}-']{ flex-basis: $glp_col-5-12; max-width: $glp_col-5-12; }\n  [class*=\"#{$grid}-6\"] > .#{$gl-colName}, [class*=\"#{$grid}-6\"] > [class*='#{$gl-colName}-']{ flex-basis: $glp_col-2; max-width: $glp_col-2; }\n  [class*=\"#{$grid}-7\"] > .#{$gl-colName}, [class*=\"#{$grid}-7\"] > [class*='#{$gl-colName}-']{ flex-basis: $glp_col-7-12; max-width: $glp_col-7-12; }\n  [class*=\"#{$grid}-8\"] > .#{$gl-colName}, [class*=\"#{$grid}-8\"] > [class*='#{$gl-colName}-']{ flex-basis: $glp_col-8-12; max-width: $glp_col-8-12; }\n  [class*=\"#{$grid}-9\"] > .#{$gl-colName}, [class*=\"#{$grid}-9\"] > [class*='#{$gl-colName}-']{ flex-basis: $glp_col-9-12; max-width: $glp_col-9-12; }\n  [class*=\"#{$grid}-10\"] > .#{$gl-colName}, [class*=\"#{$grid}-10\"] > [class*='#{$gl-colName}-']{ flex-basis: $glp_col-10-12; max-width: $glp_col-10-12; }\n  [class*=\"#{$grid}-11\"] > .#{$gl-colName}, [class*=\"#{$grid}-11\"] > [class*='#{$gl-colName}-']{ flex-basis: $glp_col-11-12; max-width: $glp_col-11-12; }\n  [class*=\"#{$grid}-12\"] > .#{$gl-colName}, [class*=\"#{$grid}-12\"] > [class*='#{$gl-colName}-']{ flex-basis: $glp_col-1; max-width: $glp_col-1; }\n}\n\n// Function to generate the grid by columns\n@mixin makeCol($col)\n{\n    [class*='#{$gl-gridName}'] {\n        > [class*=\"#{$col}-1\"]{ flex-basis: $glp_col-1;max-width: $glp_col-1; }\n        > [class*=\"#{$col}-2\"]{ flex-basis: $glp_col-2;max-width: $glp_col-2; }\n        > [class*=\"#{$col}-3\"]{ flex-basis: $glp_col-3;max-width: $glp_col-3; }\n        > [class*=\"#{$col}-4\"]{ flex-basis: $glp_col-4;max-width: $glp_col-4;}\n        > [class*=\"#{$col}-5\"]{ flex-basis: $glp_col-5;max-width: $glp_col-5;}\n        > [class*=\"#{$col}-6\"]{ flex-basis: $glp_col-6;max-width: $glp_col-6;}\n        > [class*=\"#{$col}-7\"]{ flex-basis: $glp_col-7;max-width: $glp_col-7;}\n        > [class*=\"#{$col}-8\"]{ flex-basis: $glp_col-8;max-width: $glp_col-8;}\n        > [class*=\"#{$col}-9\"]{ flex-basis: $glp_col-9;max-width: $glp_col-9;}\n        > [class*=\"#{$col}-10\"]{ flex-basis: $glp_col-10;max-width: $glp_col-10;}\n        > [class*=\"#{$col}-11\"]{ flex-basis: $glp_col-11;max-width: $glp_col-11;}\n        > [class*=\"#{$col}-12\"]{ flex-basis: $glp_col-12;max-width: $glp_col-12;}\n    }\n}\n\n// Function to generate the offset\n@mixin makeOff($off)\n{\n    [class*=\"#{$gl-gridName}\"]{\n        > [data-push-left*=\"#{$off}-0\"]{ margin-left: 0; }\n        > [data-push-left*=\"#{$off}-1\"]{ margin-left: $glp_col-1; }\n        > [data-push-left*=\"#{$off}-2\"]{ margin-left: $glp_col-2; }\n        > [data-push-left*=\"#{$off}-3\"]{ margin-left: $glp_col-3; }\n        > [data-push-left*=\"#{$off}-4\"]{ margin-left: $glp_col-4; }\n        > [data-push-left*=\"#{$off}-5\"]{ margin-left: $glp_col-5; }\n        > [data-push-left*=\"#{$off}-6\"]{ margin-left: $glp_col-6; }\n        > [data-push-left*=\"#{$off}-7\"]{ margin-left: $glp_col-7; }\n        > [data-push-left*=\"#{$off}-8\"]{ margin-left: $glp_col-8; }\n        > [data-push-left*=\"#{$off}-9\"]{ margin-left: $glp_col-9; }\n        > [data-push-left*=\"#{$off}-10\"]{ margin-left: $glp_col-10; }\n        > [data-push-left*=\"#{$off}-11\"]{ margin-left: $glp_col-11; }\n\n        > [data-push-right*=\"#{$off}-0\"]{ margin-right: 0; }\n        > [data-push-right*=\"#{$off}-1\"]{ margin-right: $glp_col-1; }\n        > [data-push-right*=\"#{$off}-2\"]{ margin-right: $glp_col-2; }\n        > [data-push-right*=\"#{$off}-3\"]{ margin-right: $glp_col-3; }\n        > [data-push-right*=\"#{$off}-4\"]{ margin-right: $glp_col-4; }\n        > [data-push-right*=\"#{$off}-5\"]{ margin-right: $glp_col-5; }\n        > [data-push-right*=\"#{$off}-6\"]{ margin-right: $glp_col-6; }\n        > [data-push-right*=\"#{$off}-7\"]{ margin-right: $glp_col-7; }\n        > [data-push-right*=\"#{$off}-8\"]{ margin-right: $glp_col-8; }\n        > [data-push-right*=\"#{$off}-9\"]{ margin-right: $glp_col-9; }\n        > [data-push-right*=\"#{$off}-10\"]{ margin-right: $glp_col-10; }\n        > [data-push-right*=\"#{$off}-11\"]{ margin-right: $glp_col-11; }\n    }\n}"
  },
  {
    "path": "assets/vendor/gridlex.scss",
    "content": "/* ==========================================================================\n    GRIDLEX\n    Just a Flexbox Grid System\n========================================================================== */\n\n@import \"gridlex-vars\";\n\n.#{$gl-gridName},\n[class*=\"#{$gl-gridName}\"]{\n  box-sizing: border-box;\n  display: flex;\n  flex-flow: row wrap;\n  margin: 0 (-$gl-gutter/2);\n}\n.#{$gl-colName},\n[class*=\"#{$gl-colName}-\"]{\n  box-sizing: border-box;\n  flex: 0 0 auto;\n  padding: 0 ($gl-gutter/2) $gl-col-bottom;\n}\n.#{$gl-colName}{\n  flex: 1 1 0%;\n}\n.#{$gl-gridName}.#{$gl-colName},\n.#{$gl-gridName}[class*=\"#{$gl-colName}-\"]{\n  margin: 0;\n  padding: 0;\n}\n\n/************************\n    HELPERS SUFFIXES\n*************************/\n// FOR GRID\n[class*=\"#{$gl-gridName}-\"]{\n// No spacing between cols : noGutter\n  &[class*=\"-noGutter\"]{\n    margin: 0;\n    > [class*=\"#{$gl-colName}\"]{\n      padding: 0;\n    }\n  }\n\n// No Wrapping\n  &[class*=\"-noWrap\"]{\n    flex-wrap: nowrap;\n  }\n// Horizontal alignment\n  &[class*=\"-center\"]{\n    justify-content: center;\n  }\n  &[class*=\"-right\"]{\n    justify-content: flex-end;\n    align-self: flex-end;\n    margin-left: auto;\n  }\n// Vertical alignment\n  &[class*=\"-top\"]{\n    align-items: flex-start;\n  }\n  &[class*=\"-middle\"]{\n    align-items: center;\n  }\n  &[class*=\"-bottom\"]{\n    align-items: flex-end;\n  }\n\n// Orders\n  &[class*=\"-reverse\"]{\n    flex-direction: row-reverse;\n  }\n  &[class*=\"-column\"] {\n    flex-direction: column;\n    > [class*=\"#{$gl-colName}-\"] {\n      flex-basis: auto;\n    }\n  }\n  &[class*=\"-column-reverse\"]{\n    flex-direction: column-reverse;\n  }\n\n// Spaces between and around cols\n  &[class*=\"-spaceBetween\"]{\n    justify-content: space-between;\n  }\n  &[class*=\"-spaceAround\"]{\n    justify-content: space-around;\n  }\n\n// Equal heights columns\n  &[class*=\"-equalHeight\"] > [class*=\"#{$gl-colName}\"]{\n    display: flex;\n    > *{\n      flex: 1;\n    }\n  }\n// Removes the padding-bottom\n  &[class*=\"-noBottom\"] > [class*=\"#{$gl-colName}\"]{\n    padding-bottom: 0;\n  }\n}\n\n// FOR COL\n[class*=\"#{$gl-colName}-\"]{\n  &[class*=\"-top\"]{\n    align-self: flex-start;\n  }\n  &[class*=\"-middle\"]{\n    align-self: center;\n  }\n  &[class*=\"-bottom\"]{\n    align-self: flex-end;\n  }\n  &[class*=\"-first\"]{\n    order: -1;\n  }\n  &[class*=\"-last\"]{\n    order: 1;\n  }\n}\n\n/************************\n    GRID BY NUMBER\n*************************/\n@include makeGridByNumber(#{$gl-gridName});\n\n@media #{$gl-lg}{\n  @include makeGridByNumber(_lg);\n}\n@media #{$gl-md}{\n  @include makeGridByNumber(_md);\n}\n@media #{$gl-sm}{\n  @include makeGridByNumber(_sm);\n}\n@media #{$gl-xs}{\n  @include makeGridByNumber(_xs);\n}\n\n/************************\n    COLS SIZES\n*************************/\n@include makeCol(#{$gl-colName});\n@include makeOff(off);\n\n@media #{$gl-lg}{\n  @include makeCol(_lg);\n  @include makeOff(_lg);\n}\n@media #{$gl-md}{\n  @include makeCol(_md);\n  @include makeOff(_md);\n}\n@media #{$gl-sm}{\n  @include makeCol(_sm);\n  @include makeOff(_sm);\n}\n@media #{$gl-xs}{\n  @include makeCol(_xs);\n  @include makeOff(_xs);\n}\n\n/************************\n    HIDING COLS\n*************************/\n[class*=\"#{$gl-colName}-\"]:not([class*=\"#{$gl-colName}-0\"]) {\n  display: block;\n}\n[class*=\"#{$gl-gridName}\"][class*=\"#{$gl-colName}-\"]:not([class*=\"#{$gl-colName}-0\"]) {\n  display: flex;\n}\n[class*=\"#{$gl-colName}-\"][class*=\"#{$gl-colName}-0\"] {\n  display: none;\n}\n@media #{$gl-lg}{\n  [class*=\"#{$gl-gridName}\"] {\n    > :not([class*=\"_lg-0\"]){\n      display: block;\n    }\n    &:not([class*=\"_lg-0\"]) {\n      display: flex;\n    }\n    >[class*=\"_lg-0\"],\n    &[class*=\"-equalHeight\"] > [class*=\"_lg-0\"]{\n      display: none;\n    }\n  }\n}\n@media #{$gl-md}{\n  [class*=\"#{$gl-gridName}\"] {\n    > :not([class*=\"_md-0\"]){\n      display: block;\n    }\n    &:not([class*=\"_md-0\"]) {\n      display: flex;\n    }\n    >[class*=\"_md-0\"],\n    &[class*=\"-equalHeight\"] > [class*=\"_md-0\"]{\n      display: none;\n    }\n  }\n}\n@media #{$gl-sm}{\n  [class*=\"#{$gl-gridName}\"] {\n    > :not([class*=\"_sm-0\"]){\n      display: block;\n    }\n    &:not([class*=\"_sm-0\"]) {\n      display: flex;\n    }\n    >[class*=\"_sm-0\"],\n    &[class*=\"-equalHeight\"] > [class*=\"_sm-0\"]{\n      display: none;\n    }\n  }\n}\n@media #{$gl-xs}{\n  [class*=\"#{$gl-gridName}\"] {\n    > :not([class*=\"_xs-0\"]){\n      display: block;\n    }\n    &:not([class*=\"_xs-0\"]) {\n      display: flex;\n    }\n    >[class*=\"_xs-0\"],\n    &[class*=\"-equalHeight\"] > [class*=\"_xs-0\"]{\n      display: none;\n    }\n  }\n}\n"
  },
  {
    "path": "assets/vendor/jquery.js",
    "content": "/*!\n * jQuery JavaScript Library v3.1.1\n * https://jquery.com/\n *\n * Includes Sizzle.js\n * https://sizzlejs.com/\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license\n * https://jquery.org/license\n *\n * Date: 2016-09-22T22:30Z\n */\n( function( global, factory ) {\n\n\t\"use strict\";\n\n\tif ( typeof module === \"object\" && typeof module.exports === \"object\" ) {\n\n\t\t// For CommonJS and CommonJS-like environments where a proper `window`\n\t\t// is present, execute the factory and get jQuery.\n\t\t// For environments that do not have a `window` with a `document`\n\t\t// (such as Node.js), expose a factory as module.exports.\n\t\t// This accentuates the need for the creation of a real `window`.\n\t\t// e.g. var jQuery = require(\"jquery\")(window);\n\t\t// See ticket #14549 for more info.\n\t\tmodule.exports = global.document ?\n\t\t\tfactory( global, true ) :\n\t\t\tfunction( w ) {\n\t\t\t\tif ( !w.document ) {\n\t\t\t\t\tthrow new Error( \"jQuery requires a window with a document\" );\n\t\t\t\t}\n\t\t\t\treturn factory( w );\n\t\t\t};\n\t} else {\n\t\tfactory( global );\n\t}\n\n// Pass this if window is not defined yet\n} )( typeof window !== \"undefined\" ? window : this, function( window, noGlobal ) {\n\n// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1\n// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode\n// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common\n// enough that all such attempts are guarded in a try block.\n\"use strict\";\n\nvar arr = [];\n\nvar document = window.document;\n\nvar getProto = Object.getPrototypeOf;\n\nvar slice = arr.slice;\n\nvar concat = arr.concat;\n\nvar push = arr.push;\n\nvar indexOf = arr.indexOf;\n\nvar class2type = {};\n\nvar toString = class2type.toString;\n\nvar hasOwn = class2type.hasOwnProperty;\n\nvar fnToString = hasOwn.toString;\n\nvar ObjectFunctionString = fnToString.call( Object );\n\nvar support = {};\n\n\n\n\tfunction DOMEval( code, doc ) {\n\t\tdoc = doc || document;\n\n\t\tvar script = doc.createElement( \"script\" );\n\n\t\tscript.text = code;\n\t\tdoc.head.appendChild( script ).parentNode.removeChild( script );\n\t}\n/* global Symbol */\n// Defining this global in .eslintrc.json would create a danger of using the global\n// unguarded in another place, it seems safer to define global only for this module\n\n\n\nvar\n\tversion = \"3.1.1\",\n\n\t// Define a local copy of jQuery\n\tjQuery = function( selector, context ) {\n\n\t\t// The jQuery object is actually just the init constructor 'enhanced'\n\t\t// Need init if jQuery is called (just allow error to be thrown if not included)\n\t\treturn new jQuery.fn.init( selector, context );\n\t},\n\n\t// Support: Android <=4.0 only\n\t// Make sure we trim BOM and NBSP\n\trtrim = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g,\n\n\t// Matches dashed string for camelizing\n\trmsPrefix = /^-ms-/,\n\trdashAlpha = /-([a-z])/g,\n\n\t// Used by jQuery.camelCase as callback to replace()\n\tfcamelCase = function( all, letter ) {\n\t\treturn letter.toUpperCase();\n\t};\n\njQuery.fn = jQuery.prototype = {\n\n\t// The current version of jQuery being used\n\tjquery: version,\n\n\tconstructor: jQuery,\n\n\t// The default length of a jQuery object is 0\n\tlength: 0,\n\n\ttoArray: function() {\n\t\treturn slice.call( this );\n\t},\n\n\t// Get the Nth element in the matched element set OR\n\t// Get the whole matched element set as a clean array\n\tget: function( num ) {\n\n\t\t// Return all the elements in a clean array\n\t\tif ( num == null ) {\n\t\t\treturn slice.call( this );\n\t\t}\n\n\t\t// Return just the one element from the set\n\t\treturn num < 0 ? this[ num + this.length ] : this[ num ];\n\t},\n\n\t// Take an array of elements and push it onto the stack\n\t// (returning the new matched element set)\n\tpushStack: function( elems ) {\n\n\t\t// Build a new jQuery matched element set\n\t\tvar ret = jQuery.merge( this.constructor(), elems );\n\n\t\t// Add the old object onto the stack (as a reference)\n\t\tret.prevObject = this;\n\n\t\t// Return the newly-formed element set\n\t\treturn ret;\n\t},\n\n\t// Execute a callback for every element in the matched set.\n\teach: function( callback ) {\n\t\treturn jQuery.each( this, callback );\n\t},\n\n\tmap: function( callback ) {\n\t\treturn this.pushStack( jQuery.map( this, function( elem, i ) {\n\t\t\treturn callback.call( elem, i, elem );\n\t\t} ) );\n\t},\n\n\tslice: function() {\n\t\treturn this.pushStack( slice.apply( this, arguments ) );\n\t},\n\n\tfirst: function() {\n\t\treturn this.eq( 0 );\n\t},\n\n\tlast: function() {\n\t\treturn this.eq( -1 );\n\t},\n\n\teq: function( i ) {\n\t\tvar len = this.length,\n\t\t\tj = +i + ( i < 0 ? len : 0 );\n\t\treturn this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );\n\t},\n\n\tend: function() {\n\t\treturn this.prevObject || this.constructor();\n\t},\n\n\t// For internal use only.\n\t// Behaves like an Array's method, not like a jQuery method.\n\tpush: push,\n\tsort: arr.sort,\n\tsplice: arr.splice\n};\n\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[ 0 ] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\n\t\t// Skip the boolean and the target\n\t\ttarget = arguments[ i ] || {};\n\t\ti++;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" && !jQuery.isFunction( target ) ) {\n\t\ttarget = {};\n\t}\n\n\t// Extend jQuery itself if only one argument is passed\n\tif ( i === length ) {\n\t\ttarget = this;\n\t\ti--;\n\t}\n\n\tfor ( ; i < length; i++ ) {\n\n\t\t// Only deal with non-null/undefined values\n\t\tif ( ( options = arguments[ i ] ) != null ) {\n\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tsrc = target[ name ];\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject( copy ) ||\n\t\t\t\t\t( copyIsArray = jQuery.isArray( copy ) ) ) ) {\n\n\t\t\t\t\tif ( copyIsArray ) {\n\t\t\t\t\t\tcopyIsArray = false;\n\t\t\t\t\t\tclone = src && jQuery.isArray( src ) ? src : [];\n\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src && jQuery.isPlainObject( src ) ? src : {};\n\t\t\t\t\t}\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\njQuery.extend( {\n\n\t// Unique for each copy of jQuery on the page\n\texpando: \"jQuery\" + ( version + Math.random() ).replace( /\\D/g, \"\" ),\n\n\t// Assume jQuery is ready without the ready module\n\tisReady: true,\n\n\terror: function( msg ) {\n\t\tthrow new Error( msg );\n\t},\n\n\tnoop: function() {},\n\n\tisFunction: function( obj ) {\n\t\treturn jQuery.type( obj ) === \"function\";\n\t},\n\n\tisArray: Array.isArray,\n\n\tisWindow: function( obj ) {\n\t\treturn obj != null && obj === obj.window;\n\t},\n\n\tisNumeric: function( obj ) {\n\n\t\t// As of jQuery 3.0, isNumeric is limited to\n\t\t// strings and numbers (primitives or objects)\n\t\t// that can be coerced to finite numbers (gh-2662)\n\t\tvar type = jQuery.type( obj );\n\t\treturn ( type === \"number\" || type === \"string\" ) &&\n\n\t\t\t// parseFloat NaNs numeric-cast false positives (\"\")\n\t\t\t// ...but misinterprets leading-number strings, particularly hex literals (\"0x...\")\n\t\t\t// subtraction forces infinities to NaN\n\t\t\t!isNaN( obj - parseFloat( obj ) );\n\t},\n\n\tisPlainObject: function( obj ) {\n\t\tvar proto, Ctor;\n\n\t\t// Detect obvious negatives\n\t\t// Use toString instead of jQuery.type to catch host objects\n\t\tif ( !obj || toString.call( obj ) !== \"[object Object]\" ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tproto = getProto( obj );\n\n\t\t// Objects with no prototype (e.g., `Object.create( null )`) are plain\n\t\tif ( !proto ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Objects with prototype are plain iff they were constructed by a global Object function\n\t\tCtor = hasOwn.call( proto, \"constructor\" ) && proto.constructor;\n\t\treturn typeof Ctor === \"function\" && fnToString.call( Ctor ) === ObjectFunctionString;\n\t},\n\n\tisEmptyObject: function( obj ) {\n\n\t\t/* eslint-disable no-unused-vars */\n\t\t// See https://github.com/eslint/eslint/issues/6125\n\t\tvar name;\n\n\t\tfor ( name in obj ) {\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t},\n\n\ttype: function( obj ) {\n\t\tif ( obj == null ) {\n\t\t\treturn obj + \"\";\n\t\t}\n\n\t\t// Support: Android <=2.3 only (functionish RegExp)\n\t\treturn typeof obj === \"object\" || typeof obj === \"function\" ?\n\t\t\tclass2type[ toString.call( obj ) ] || \"object\" :\n\t\t\ttypeof obj;\n\t},\n\n\t// Evaluates a script in a global context\n\tglobalEval: function( code ) {\n\t\tDOMEval( code );\n\t},\n\n\t// Convert dashed to camelCase; used by the css and data modules\n\t// Support: IE <=9 - 11, Edge 12 - 13\n\t// Microsoft forgot to hump their vendor prefix (#9572)\n\tcamelCase: function( string ) {\n\t\treturn string.replace( rmsPrefix, \"ms-\" ).replace( rdashAlpha, fcamelCase );\n\t},\n\n\tnodeName: function( elem, name ) {\n\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n\t},\n\n\teach: function( obj, callback ) {\n\t\tvar length, i = 0;\n\n\t\tif ( isArrayLike( obj ) ) {\n\t\t\tlength = obj.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tfor ( i in obj ) {\n\t\t\t\tif ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn obj;\n\t},\n\n\t// Support: Android <=4.0 only\n\ttrim: function( text ) {\n\t\treturn text == null ?\n\t\t\t\"\" :\n\t\t\t( text + \"\" ).replace( rtrim, \"\" );\n\t},\n\n\t// results is for internal usage only\n\tmakeArray: function( arr, results ) {\n\t\tvar ret = results || [];\n\n\t\tif ( arr != null ) {\n\t\t\tif ( isArrayLike( Object( arr ) ) ) {\n\t\t\t\tjQuery.merge( ret,\n\t\t\t\t\ttypeof arr === \"string\" ?\n\t\t\t\t\t[ arr ] : arr\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpush.call( ret, arr );\n\t\t\t}\n\t\t}\n\n\t\treturn ret;\n\t},\n\n\tinArray: function( elem, arr, i ) {\n\t\treturn arr == null ? -1 : indexOf.call( arr, elem, i );\n\t},\n\n\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t// push.apply(_, arraylike) throws on ancient WebKit\n\tmerge: function( first, second ) {\n\t\tvar len = +second.length,\n\t\t\tj = 0,\n\t\t\ti = first.length;\n\n\t\tfor ( ; j < len; j++ ) {\n\t\t\tfirst[ i++ ] = second[ j ];\n\t\t}\n\n\t\tfirst.length = i;\n\n\t\treturn first;\n\t},\n\n\tgrep: function( elems, callback, invert ) {\n\t\tvar callbackInverse,\n\t\t\tmatches = [],\n\t\t\ti = 0,\n\t\t\tlength = elems.length,\n\t\t\tcallbackExpect = !invert;\n\n\t\t// Go through the array, only saving the items\n\t\t// that pass the validator function\n\t\tfor ( ; i < length; i++ ) {\n\t\t\tcallbackInverse = !callback( elems[ i ], i );\n\t\t\tif ( callbackInverse !== callbackExpect ) {\n\t\t\t\tmatches.push( elems[ i ] );\n\t\t\t}\n\t\t}\n\n\t\treturn matches;\n\t},\n\n\t// arg is for internal usage only\n\tmap: function( elems, callback, arg ) {\n\t\tvar length, value,\n\t\t\ti = 0,\n\t\t\tret = [];\n\n\t\t// Go through the array, translating each of the items to their new values\n\t\tif ( isArrayLike( elems ) ) {\n\t\t\tlength = elems.length;\n\t\t\tfor ( ; i < length; i++ ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Go through every key on the object,\n\t\t} else {\n\t\t\tfor ( i in elems ) {\n\t\t\t\tvalue = callback( elems[ i ], i, arg );\n\n\t\t\t\tif ( value != null ) {\n\t\t\t\t\tret.push( value );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Flatten any nested arrays\n\t\treturn concat.apply( [], ret );\n\t},\n\n\t// A global GUID counter for objects\n\tguid: 1,\n\n\t// Bind a function to a context, optionally partially applying any\n\t// arguments.\n\tproxy: function( fn, context ) {\n\t\tvar tmp, args, proxy;\n\n\t\tif ( typeof context === \"string\" ) {\n\t\t\ttmp = fn[ context ];\n\t\t\tcontext = fn;\n\t\t\tfn = tmp;\n\t\t}\n\n\t\t// Quick check to determine if target is callable, in the spec\n\t\t// this throws a TypeError, but we will just return undefined.\n\t\tif ( !jQuery.isFunction( fn ) ) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\t// Simulated bind\n\t\targs = slice.call( arguments, 2 );\n\t\tproxy = function() {\n\t\t\treturn fn.apply( context || this, args.concat( slice.call( arguments ) ) );\n\t\t};\n\n\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n\n\t\treturn proxy;\n\t},\n\n\tnow: Date.now,\n\n\t// jQuery.support is not used in Core but other projects attach their\n\t// properties to it so it needs to exist.\n\tsupport: support\n} );\n\nif ( typeof Symbol === \"function\" ) {\n\tjQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];\n}\n\n// Populate the class2type map\njQuery.each( \"Boolean Number String Function Array Date RegExp Object Error Symbol\".split( \" \" ),\nfunction( i, name ) {\n\tclass2type[ \"[object \" + name + \"]\" ] = name.toLowerCase();\n} );\n\nfunction isArrayLike( obj ) {\n\n\t// Support: real iOS 8.2 only (not reproducible in simulator)\n\t// `in` check used to prevent JIT error (gh-2145)\n\t// hasOwn isn't used here due to false negatives\n\t// regarding Nodelist length in IE\n\tvar length = !!obj && \"length\" in obj && obj.length,\n\t\ttype = jQuery.type( obj );\n\n\tif ( type === \"function\" || jQuery.isWindow( obj ) ) {\n\t\treturn false;\n\t}\n\n\treturn type === \"array\" || length === 0 ||\n\t\ttypeof length === \"number\" && length > 0 && ( length - 1 ) in obj;\n}\nvar Sizzle =\n/*!\n * Sizzle CSS Selector Engine v2.3.3\n * https://sizzlejs.com/\n *\n * Copyright jQuery Foundation and other contributors\n * Released under the MIT license\n * http://jquery.org/license\n *\n * Date: 2016-08-08\n */\n(function( window ) {\n\nvar i,\n\tsupport,\n\tExpr,\n\tgetText,\n\tisXML,\n\ttokenize,\n\tcompile,\n\tselect,\n\toutermostContext,\n\tsortInput,\n\thasDuplicate,\n\n\t// Local document vars\n\tsetDocument,\n\tdocument,\n\tdocElem,\n\tdocumentIsHTML,\n\trbuggyQSA,\n\trbuggyMatches,\n\tmatches,\n\tcontains,\n\n\t// Instance-specific data\n\texpando = \"sizzle\" + 1 * new Date(),\n\tpreferredDoc = window.document,\n\tdirruns = 0,\n\tdone = 0,\n\tclassCache = createCache(),\n\ttokenCache = createCache(),\n\tcompilerCache = createCache(),\n\tsortOrder = function( a, b ) {\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t}\n\t\treturn 0;\n\t},\n\n\t// Instance methods\n\thasOwn = ({}).hasOwnProperty,\n\tarr = [],\n\tpop = arr.pop,\n\tpush_native = arr.push,\n\tpush = arr.push,\n\tslice = arr.slice,\n\t// Use a stripped-down indexOf as it's faster than native\n\t// https://jsperf.com/thor-indexof-vs-for/5\n\tindexOf = function( list, elem ) {\n\t\tvar i = 0,\n\t\t\tlen = list.length;\n\t\tfor ( ; i < len; i++ ) {\n\t\t\tif ( list[i] === elem ) {\n\t\t\t\treturn i;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\tbooleans = \"checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped\",\n\n\t// Regular expressions\n\n\t// http://www.w3.org/TR/css3-selectors/#whitespace\n\twhitespace = \"[\\\\x20\\\\t\\\\r\\\\n\\\\f]\",\n\n\t// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n\tidentifier = \"(?:\\\\\\\\.|[\\\\w-]|[^\\0-\\\\xa0])+\",\n\n\t// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors\n\tattributes = \"\\\\[\" + whitespace + \"*(\" + identifier + \")(?:\" + whitespace +\n\t\t// Operator (capture 2)\n\t\t\"*([*^$|!~]?=)\" + whitespace +\n\t\t// \"Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]\"\n\t\t\"*(?:'((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\"|(\" + identifier + \"))|)\" + whitespace +\n\t\t\"*\\\\]\",\n\n\tpseudos = \":(\" + identifier + \")(?:\\\\((\" +\n\t\t// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:\n\t\t// 1. quoted (capture 3; capture 4 or capture 5)\n\t\t\"('((?:\\\\\\\\.|[^\\\\\\\\'])*)'|\\\"((?:\\\\\\\\.|[^\\\\\\\\\\\"])*)\\\")|\" +\n\t\t// 2. simple (capture 6)\n\t\t\"((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|\" + attributes + \")*)|\" +\n\t\t// 3. anything else (capture 2)\n\t\t\".*\" +\n\t\t\")\\\\)|)\",\n\n\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n\trwhitespace = new RegExp( whitespace + \"+\", \"g\" ),\n\trtrim = new RegExp( \"^\" + whitespace + \"+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)\" + whitespace + \"+$\", \"g\" ),\n\n\trcomma = new RegExp( \"^\" + whitespace + \"*,\" + whitespace + \"*\" ),\n\trcombinators = new RegExp( \"^\" + whitespace + \"*([>+~]|\" + whitespace + \")\" + whitespace + \"*\" ),\n\n\trattributeQuotes = new RegExp( \"=\" + whitespace + \"*([^\\\\]'\\\"]*?)\" + whitespace + \"*\\\\]\", \"g\" ),\n\n\trpseudo = new RegExp( pseudos ),\n\tridentifier = new RegExp( \"^\" + identifier + \"$\" ),\n\n\tmatchExpr = {\n\t\t\"ID\": new RegExp( \"^#(\" + identifier + \")\" ),\n\t\t\"CLASS\": new RegExp( \"^\\\\.(\" + identifier + \")\" ),\n\t\t\"TAG\": new RegExp( \"^(\" + identifier + \"|[*])\" ),\n\t\t\"ATTR\": new RegExp( \"^\" + attributes ),\n\t\t\"PSEUDO\": new RegExp( \"^\" + pseudos ),\n\t\t\"CHILD\": new RegExp( \"^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(\" + whitespace +\n\t\t\t\"*(even|odd|(([+-]|)(\\\\d*)n|)\" + whitespace + \"*(?:([+-]|)\" + whitespace +\n\t\t\t\"*(\\\\d+)|))\" + whitespace + \"*\\\\)|)\", \"i\" ),\n\t\t\"bool\": new RegExp( \"^(?:\" + booleans + \")$\", \"i\" ),\n\t\t// For use in libraries implementing .is()\n\t\t// We use this for POS matching in `select`\n\t\t\"needsContext\": new RegExp( \"^\" + whitespace + \"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(\" +\n\t\t\twhitespace + \"*((?:-\\\\d)?\\\\d*)\" + whitespace + \"*\\\\)|)(?=[^-]|$)\", \"i\" )\n\t},\n\n\trinputs = /^(?:input|select|textarea|button)$/i,\n\trheader = /^h\\d$/i,\n\n\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n\n\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n\n\trsibling = /[+~]/,\n\n\t// CSS escapes\n\t// http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n\trunescape = new RegExp( \"\\\\\\\\([\\\\da-f]{1,6}\" + whitespace + \"?|(\" + whitespace + \")|.)\", \"ig\" ),\n\tfunescape = function( _, escaped, escapedWhitespace ) {\n\t\tvar high = \"0x\" + escaped - 0x10000;\n\t\t// NaN means non-codepoint\n\t\t// Support: Firefox<24\n\t\t// Workaround erroneous numeric interpretation of +\"0x\"\n\t\treturn high !== high || escapedWhitespace ?\n\t\t\tescaped :\n\t\t\thigh < 0 ?\n\t\t\t\t// BMP codepoint\n\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n\t},\n\n\t// CSS string/identifier serialization\n\t// https://drafts.csswg.org/cssom/#common-serializing-idioms\n\trcssescape = /([\\0-\\x1f\\x7f]|^-?\\d)|^-$|[^\\0-\\x1f\\x7f-\\uFFFF\\w-]/g,\n\tfcssescape = function( ch, asCodePoint ) {\n\t\tif ( asCodePoint ) {\n\n\t\t\t// U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER\n\t\t\tif ( ch === \"\\0\" ) {\n\t\t\t\treturn \"\\uFFFD\";\n\t\t\t}\n\n\t\t\t// Control characters and (dependent upon position) numbers get escaped as code points\n\t\t\treturn ch.slice( 0, -1 ) + \"\\\\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + \" \";\n\t\t}\n\n\t\t// Other potentially-special ASCII characters get backslash-escaped\n\t\treturn \"\\\\\" + ch;\n\t},\n\n\t// Used for iframes\n\t// See setDocument()\n\t// Removing the function wrapper causes a \"Permission Denied\"\n\t// error in IE\n\tunloadHandler = function() {\n\t\tsetDocument();\n\t},\n\n\tdisabledAncestor = addCombinator(\n\t\tfunction( elem ) {\n\t\t\treturn elem.disabled === true && (\"form\" in elem || \"label\" in elem);\n\t\t},\n\t\t{ dir: \"parentNode\", next: \"legend\" }\n\t);\n\n// Optimize for push.apply( _, NodeList )\ntry {\n\tpush.apply(\n\t\t(arr = slice.call( preferredDoc.childNodes )),\n\t\tpreferredDoc.childNodes\n\t);\n\t// Support: Android<4.0\n\t// Detect silently failing push.apply\n\tarr[ preferredDoc.childNodes.length ].nodeType;\n} catch ( e ) {\n\tpush = { apply: arr.length ?\n\n\t\t// Leverage slice if possible\n\t\tfunction( target, els ) {\n\t\t\tpush_native.apply( target, slice.call(els) );\n\t\t} :\n\n\t\t// Support: IE<9\n\t\t// Otherwise append directly\n\t\tfunction( target, els ) {\n\t\t\tvar j = target.length,\n\t\t\t\ti = 0;\n\t\t\t// Can't trust NodeList.length\n\t\t\twhile ( (target[j++] = els[i++]) ) {}\n\t\t\ttarget.length = j - 1;\n\t\t}\n\t};\n}\n\nfunction Sizzle( selector, context, results, seed ) {\n\tvar m, i, elem, nid, match, groups, newSelector,\n\t\tnewContext = context && context.ownerDocument,\n\n\t\t// nodeType defaults to 9, since context defaults to document\n\t\tnodeType = context ? context.nodeType : 9;\n\n\tresults = results || [];\n\n\t// Return early from calls with invalid selector or context\n\tif ( typeof selector !== \"string\" || !selector ||\n\t\tnodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {\n\n\t\treturn results;\n\t}\n\n\t// Try to shortcut find operations (as opposed to filters) in HTML documents\n\tif ( !seed ) {\n\n\t\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n\t\t\tsetDocument( context );\n\t\t}\n\t\tcontext = context || document;\n\n\t\tif ( documentIsHTML ) {\n\n\t\t\t// If the selector is sufficiently simple, try using a \"get*By*\" DOM method\n\t\t\t// (excepting DocumentFragment context, where the methods don't exist)\n\t\t\tif ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {\n\n\t\t\t\t// ID selector\n\t\t\t\tif ( (m = match[1]) ) {\n\n\t\t\t\t\t// Document context\n\t\t\t\t\tif ( nodeType === 9 ) {\n\t\t\t\t\t\tif ( (elem = context.getElementById( m )) ) {\n\n\t\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\t\tif ( elem.id === m ) {\n\t\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t// Element context\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// Support: IE, Opera, Webkit\n\t\t\t\t\t\t// TODO: identify versions\n\t\t\t\t\t\t// getElementById can match elements by name instead of ID\n\t\t\t\t\t\tif ( newContext && (elem = newContext.getElementById( m )) &&\n\t\t\t\t\t\t\tcontains( context, elem ) &&\n\t\t\t\t\t\t\telem.id === m ) {\n\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\treturn results;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t// Type selector\n\t\t\t\t} else if ( match[2] ) {\n\t\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n\t\t\t\t\treturn results;\n\n\t\t\t\t// Class selector\n\t\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName &&\n\t\t\t\t\tcontext.getElementsByClassName ) {\n\n\t\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n\t\t\t\t\treturn results;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Take advantage of querySelectorAll\n\t\t\tif ( support.qsa &&\n\t\t\t\t!compilerCache[ selector + \" \" ] &&\n\t\t\t\t(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n\n\t\t\t\tif ( nodeType !== 1 ) {\n\t\t\t\t\tnewContext = context;\n\t\t\t\t\tnewSelector = selector;\n\n\t\t\t\t// qSA looks outside Element context, which is not what we want\n\t\t\t\t// Thanks to Andrew Dupont for this workaround technique\n\t\t\t\t// Support: IE <=8\n\t\t\t\t// Exclude object elements\n\t\t\t\t} else if ( context.nodeName.toLowerCase() !== \"object\" ) {\n\n\t\t\t\t\t// Capture the context ID, setting it first if necessary\n\t\t\t\t\tif ( (nid = context.getAttribute( \"id\" )) ) {\n\t\t\t\t\t\tnid = nid.replace( rcssescape, fcssescape );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tcontext.setAttribute( \"id\", (nid = expando) );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prefix every selector in the list\n\t\t\t\t\tgroups = tokenize( selector );\n\t\t\t\t\ti = groups.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tgroups[i] = \"#\" + nid + \" \" + toSelector( groups[i] );\n\t\t\t\t\t}\n\t\t\t\t\tnewSelector = groups.join( \",\" );\n\n\t\t\t\t\t// Expand context for sibling selectors\n\t\t\t\t\tnewContext = rsibling.test( selector ) && testContext( context.parentNode ) ||\n\t\t\t\t\t\tcontext;\n\t\t\t\t}\n\n\t\t\t\tif ( newSelector ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tpush.apply( results,\n\t\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t} catch ( qsaError ) {\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tif ( nid === expando ) {\n\t\t\t\t\t\t\tcontext.removeAttribute( \"id\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// All others\n\treturn select( selector.replace( rtrim, \"$1\" ), context, results, seed );\n}\n\n/**\n * Create key-value caches of limited size\n * @returns {function(string, object)} Returns the Object data after storing it on itself with\n *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n *\tdeleting the oldest entry\n */\nfunction createCache() {\n\tvar keys = [];\n\n\tfunction cache( key, value ) {\n\t\t// Use (key + \" \") to avoid collision with native prototype properties (see Issue #157)\n\t\tif ( keys.push( key + \" \" ) > Expr.cacheLength ) {\n\t\t\t// Only keep the most recent entries\n\t\t\tdelete cache[ keys.shift() ];\n\t\t}\n\t\treturn (cache[ key + \" \" ] = value);\n\t}\n\treturn cache;\n}\n\n/**\n * Mark a function for special use by Sizzle\n * @param {Function} fn The function to mark\n */\nfunction markFunction( fn ) {\n\tfn[ expando ] = true;\n\treturn fn;\n}\n\n/**\n * Support testing using an element\n * @param {Function} fn Passed the created element and returns a boolean result\n */\nfunction assert( fn ) {\n\tvar el = document.createElement(\"fieldset\");\n\n\ttry {\n\t\treturn !!fn( el );\n\t} catch (e) {\n\t\treturn false;\n\t} finally {\n\t\t// Remove from its parent by default\n\t\tif ( el.parentNode ) {\n\t\t\tel.parentNode.removeChild( el );\n\t\t}\n\t\t// release memory in IE\n\t\tel = null;\n\t}\n}\n\n/**\n * Adds the same handler for all of the specified attrs\n * @param {String} attrs Pipe-separated list of attributes\n * @param {Function} handler The method that will be applied\n */\nfunction addHandle( attrs, handler ) {\n\tvar arr = attrs.split(\"|\"),\n\t\ti = arr.length;\n\n\twhile ( i-- ) {\n\t\tExpr.attrHandle[ arr[i] ] = handler;\n\t}\n}\n\n/**\n * Checks document order of two siblings\n * @param {Element} a\n * @param {Element} b\n * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n */\nfunction siblingCheck( a, b ) {\n\tvar cur = b && a,\n\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n\t\t\ta.sourceIndex - b.sourceIndex;\n\n\t// Use IE sourceIndex if available on both nodes\n\tif ( diff ) {\n\t\treturn diff;\n\t}\n\n\t// Check if b follows a\n\tif ( cur ) {\n\t\twhile ( (cur = cur.nextSibling) ) {\n\t\t\tif ( cur === b ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn a ? 1 : -1;\n}\n\n/**\n * Returns a function to use in pseudos for input types\n * @param {String} type\n */\nfunction createInputPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn name === \"input\" && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for buttons\n * @param {String} type\n */\nfunction createButtonPseudo( type ) {\n\treturn function( elem ) {\n\t\tvar name = elem.nodeName.toLowerCase();\n\t\treturn (name === \"input\" || name === \"button\") && elem.type === type;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for :enabled/:disabled\n * @param {Boolean} disabled true for :disabled; false for :enabled\n */\nfunction createDisabledPseudo( disabled ) {\n\n\t// Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable\n\treturn function( elem ) {\n\n\t\t// Only certain elements can match :enabled or :disabled\n\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled\n\t\t// https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled\n\t\tif ( \"form\" in elem ) {\n\n\t\t\t// Check for inherited disabledness on relevant non-disabled elements:\n\t\t\t// * listed form-associated elements in a disabled fieldset\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#category-listed\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled\n\t\t\t// * option elements in a disabled optgroup\n\t\t\t//   https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled\n\t\t\t// All such elements have a \"form\" property.\n\t\t\tif ( elem.parentNode && elem.disabled === false ) {\n\n\t\t\t\t// Option elements defer to a parent optgroup if present\n\t\t\t\tif ( \"label\" in elem ) {\n\t\t\t\t\tif ( \"label\" in elem.parentNode ) {\n\t\t\t\t\t\treturn elem.parentNode.disabled === disabled;\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn elem.disabled === disabled;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Support: IE 6 - 11\n\t\t\t\t// Use the isDisabled shortcut property to check for disabled fieldset ancestors\n\t\t\t\treturn elem.isDisabled === disabled ||\n\n\t\t\t\t\t// Where there is no isDisabled, check manually\n\t\t\t\t\t/* jshint -W018 */\n\t\t\t\t\telem.isDisabled !== !disabled &&\n\t\t\t\t\t\tdisabledAncestor( elem ) === disabled;\n\t\t\t}\n\n\t\t\treturn elem.disabled === disabled;\n\n\t\t// Try to winnow out elements that can't be disabled before trusting the disabled property.\n\t\t// Some victims get caught in our net (label, legend, menu, track), but it shouldn't\n\t\t// even exist on them, let alone have a boolean value.\n\t\t} else if ( \"label\" in elem ) {\n\t\t\treturn elem.disabled === disabled;\n\t\t}\n\n\t\t// Remaining elements are neither :enabled nor :disabled\n\t\treturn false;\n\t};\n}\n\n/**\n * Returns a function to use in pseudos for positionals\n * @param {Function} fn\n */\nfunction createPositionalPseudo( fn ) {\n\treturn markFunction(function( argument ) {\n\t\targument = +argument;\n\t\treturn markFunction(function( seed, matches ) {\n\t\t\tvar j,\n\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n\t\t\t\ti = matchIndexes.length;\n\n\t\t\t// Match elements found at the specified indexes\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n\t\t\t\t}\n\t\t\t}\n\t\t});\n\t});\n}\n\n/**\n * Checks a node for validity as a Sizzle context\n * @param {Element|Object=} context\n * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value\n */\nfunction testContext( context ) {\n\treturn context && typeof context.getElementsByTagName !== \"undefined\" && context;\n}\n\n// Expose support vars for convenience\nsupport = Sizzle.support = {};\n\n/**\n * Detects XML nodes\n * @param {Element|Object} elem An element or a document\n * @returns {Boolean} True iff elem is a non-HTML XML node\n */\nisXML = Sizzle.isXML = function( elem ) {\n\t// documentElement is verified for cases where it doesn't yet exist\n\t// (such as loading iframes in IE - #4833)\n\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n\treturn documentElement ? documentElement.nodeName !== \"HTML\" : false;\n};\n\n/**\n * Sets document-related variables once based on the current document\n * @param {Element|Object} [doc] An element or document object to use to set the document\n * @returns {Object} Returns the current document\n */\nsetDocument = Sizzle.setDocument = function( node ) {\n\tvar hasCompare, subWindow,\n\t\tdoc = node ? node.ownerDocument || node : preferredDoc;\n\n\t// Return early if doc is invalid or already selected\n\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n\t\treturn document;\n\t}\n\n\t// Update global variables\n\tdocument = doc;\n\tdocElem = document.documentElement;\n\tdocumentIsHTML = !isXML( document );\n\n\t// Support: IE 9-11, Edge\n\t// Accessing iframe documents after unload throws \"permission denied\" errors (jQuery #13936)\n\tif ( preferredDoc !== document &&\n\t\t(subWindow = document.defaultView) && subWindow.top !== subWindow ) {\n\n\t\t// Support: IE 11, Edge\n\t\tif ( subWindow.addEventListener ) {\n\t\t\tsubWindow.addEventListener( \"unload\", unloadHandler, false );\n\n\t\t// Support: IE 9 - 10 only\n\t\t} else if ( subWindow.attachEvent ) {\n\t\t\tsubWindow.attachEvent( \"onunload\", unloadHandler );\n\t\t}\n\t}\n\n\t/* Attributes\n\t---------------------------------------------------------------------- */\n\n\t// Support: IE<8\n\t// Verify that getAttribute really returns attributes and not properties\n\t// (excepting IE8 booleans)\n\tsupport.attributes = assert(function( el ) {\n\t\tel.className = \"i\";\n\t\treturn !el.getAttribute(\"className\");\n\t});\n\n\t/* getElement(s)By*\n\t---------------------------------------------------------------------- */\n\n\t// Check if getElementsByTagName(\"*\") returns only elements\n\tsupport.getElementsByTagName = assert(function( el ) {\n\t\tel.appendChild( document.createComment(\"\") );\n\t\treturn !el.getElementsByTagName(\"*\").length;\n\t});\n\n\t// Support: IE<9\n\tsupport.getElementsByClassName = rnative.test( document.getElementsByClassName );\n\n\t// Support: IE<10\n\t// Check if getElementById returns elements by name\n\t// The broken getElementById methods don't pick up programmatically-set names,\n\t// so use a roundabout getElementsByName test\n\tsupport.getById = assert(function( el ) {\n\t\tdocElem.appendChild( el ).id = expando;\n\t\treturn !document.getElementsByName || !document.getElementsByName( expando ).length;\n\t});\n\n\t// ID filter and find\n\tif ( support.getById ) {\n\t\tExpr.filter[\"ID\"] = function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn elem.getAttribute(\"id\") === attrId;\n\t\t\t};\n\t\t};\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar elem = context.getElementById( id );\n\t\t\t\treturn elem ? [ elem ] : [];\n\t\t\t}\n\t\t};\n\t} else {\n\t\tExpr.filter[\"ID\"] =  function( id ) {\n\t\t\tvar attrId = id.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\tvar node = typeof elem.getAttributeNode !== \"undefined\" &&\n\t\t\t\t\telem.getAttributeNode(\"id\");\n\t\t\t\treturn node && node.value === attrId;\n\t\t\t};\n\t\t};\n\n\t\t// Support: IE 6 - 7 only\n\t\t// getElementById is not reliable as a find shortcut\n\t\tExpr.find[\"ID\"] = function( id, context ) {\n\t\t\tif ( typeof context.getElementById !== \"undefined\" && documentIsHTML ) {\n\t\t\t\tvar node, i, elems,\n\t\t\t\t\telem = context.getElementById( id );\n\n\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t// Verify the id attribute\n\t\t\t\t\tnode = elem.getAttributeNode(\"id\");\n\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t}\n\n\t\t\t\t\t// Fall back on getElementsByName\n\t\t\t\t\telems = context.getElementsByName( id );\n\t\t\t\t\ti = 0;\n\t\t\t\t\twhile ( (elem = elems[i++]) ) {\n\t\t\t\t\t\tnode = elem.getAttributeNode(\"id\");\n\t\t\t\t\t\tif ( node && node.value === id ) {\n\t\t\t\t\t\t\treturn [ elem ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn [];\n\t\t\t}\n\t\t};\n\t}\n\n\t// Tag\n\tExpr.find[\"TAG\"] = support.getElementsByTagName ?\n\t\tfunction( tag, context ) {\n\t\t\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\t\t\treturn context.getElementsByTagName( tag );\n\n\t\t\t// DocumentFragment nodes don't have gEBTN\n\t\t\t} else if ( support.qsa ) {\n\t\t\t\treturn context.querySelectorAll( tag );\n\t\t\t}\n\t\t} :\n\n\t\tfunction( tag, context ) {\n\t\t\tvar elem,\n\t\t\t\ttmp = [],\n\t\t\t\ti = 0,\n\t\t\t\t// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too\n\t\t\t\tresults = context.getElementsByTagName( tag );\n\n\t\t\t// Filter out possible comments\n\t\t\tif ( tag === \"*\" ) {\n\t\t\t\twhile ( (elem = results[i++]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\ttmp.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn tmp;\n\t\t\t}\n\t\t\treturn results;\n\t\t};\n\n\t// Class\n\tExpr.find[\"CLASS\"] = support.getElementsByClassName && function( className, context ) {\n\t\tif ( typeof context.getElementsByClassName !== \"undefined\" && documentIsHTML ) {\n\t\t\treturn context.getElementsByClassName( className );\n\t\t}\n\t};\n\n\t/* QSA/matchesSelector\n\t---------------------------------------------------------------------- */\n\n\t// QSA and matchesSelector support\n\n\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n\trbuggyMatches = [];\n\n\t// qSa(:focus) reports false when true (Chrome 21)\n\t// We allow this because of a bug in IE8/9 that throws an error\n\t// whenever `document.activeElement` is accessed on an iframe\n\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n\t// See https://bugs.jquery.com/ticket/13378\n\trbuggyQSA = [];\n\n\tif ( (support.qsa = rnative.test( document.querySelectorAll )) ) {\n\t\t// Build QSA regex\n\t\t// Regex strategy adopted from Diego Perini\n\t\tassert(function( el ) {\n\t\t\t// Select is set to empty string on purpose\n\t\t\t// This is to test IE's treatment of not explicitly\n\t\t\t// setting a boolean content attribute,\n\t\t\t// since its presence should be enough\n\t\t\t// https://bugs.jquery.com/ticket/12359\n\t\t\tdocElem.appendChild( el ).innerHTML = \"<a id='\" + expando + \"'></a>\" +\n\t\t\t\t\"<select id='\" + expando + \"-\\r\\\\' msallowcapture=''>\" +\n\t\t\t\t\"<option selected=''></option></select>\";\n\n\t\t\t// Support: IE8, Opera 11-12.16\n\t\t\t// Nothing should be selected when empty strings follow ^= or $= or *=\n\t\t\t// The test attribute must be unknown in Opera but \"safe\" for WinRT\n\t\t\t// https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section\n\t\t\tif ( el.querySelectorAll(\"[msallowcapture^='']\").length ) {\n\t\t\t\trbuggyQSA.push( \"[*^$]=\" + whitespace + \"*(?:''|\\\"\\\")\" );\n\t\t\t}\n\n\t\t\t// Support: IE8\n\t\t\t// Boolean attributes and \"value\" are not treated correctly\n\t\t\tif ( !el.querySelectorAll(\"[selected]\").length ) {\n\t\t\t\trbuggyQSA.push( \"\\\\[\" + whitespace + \"*(?:value|\" + booleans + \")\" );\n\t\t\t}\n\n\t\t\t// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+\n\t\t\tif ( !el.querySelectorAll( \"[id~=\" + expando + \"-]\" ).length ) {\n\t\t\t\trbuggyQSA.push(\"~=\");\n\t\t\t}\n\n\t\t\t// Webkit/Opera - :checked should return selected option elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( !el.querySelectorAll(\":checked\").length ) {\n\t\t\t\trbuggyQSA.push(\":checked\");\n\t\t\t}\n\n\t\t\t// Support: Safari 8+, iOS 8+\n\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=136851\n\t\t\t// In-page `selector#id sibling-combinator selector` fails\n\t\t\tif ( !el.querySelectorAll( \"a#\" + expando + \"+*\" ).length ) {\n\t\t\t\trbuggyQSA.push(\".#.+[+~]\");\n\t\t\t}\n\t\t});\n\n\t\tassert(function( el ) {\n\t\t\tel.innerHTML = \"<a href='' disabled='disabled'></a>\" +\n\t\t\t\t\"<select disabled='disabled'><option/></select>\";\n\n\t\t\t// Support: Windows 8 Native Apps\n\t\t\t// The type and name attributes are restricted during .innerHTML assignment\n\t\t\tvar input = document.createElement(\"input\");\n\t\t\tinput.setAttribute( \"type\", \"hidden\" );\n\t\t\tel.appendChild( input ).setAttribute( \"name\", \"D\" );\n\n\t\t\t// Support: IE8\n\t\t\t// Enforce case-sensitivity of name attribute\n\t\t\tif ( el.querySelectorAll(\"[name=d]\").length ) {\n\t\t\t\trbuggyQSA.push( \"name\" + whitespace + \"*[*^$|!~]?=\" );\n\t\t\t}\n\n\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n\t\t\t// IE8 throws error here and will not see later tests\n\t\t\tif ( el.querySelectorAll(\":enabled\").length !== 2 ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Support: IE9-11+\n\t\t\t// IE's :disabled selector does not pick up the children of disabled fieldsets\n\t\t\tdocElem.appendChild( el ).disabled = true;\n\t\t\tif ( el.querySelectorAll(\":disabled\").length !== 2 ) {\n\t\t\t\trbuggyQSA.push( \":enabled\", \":disabled\" );\n\t\t\t}\n\n\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n\t\t\tel.querySelectorAll(\"*,:x\");\n\t\t\trbuggyQSA.push(\",.*:\");\n\t\t});\n\t}\n\n\tif ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||\n\t\tdocElem.webkitMatchesSelector ||\n\t\tdocElem.mozMatchesSelector ||\n\t\tdocElem.oMatchesSelector ||\n\t\tdocElem.msMatchesSelector) )) ) {\n\n\t\tassert(function( el ) {\n\t\t\t// Check to see if it's possible to do matchesSelector\n\t\t\t// on a disconnected node (IE 9)\n\t\t\tsupport.disconnectedMatch = matches.call( el, \"*\" );\n\n\t\t\t// This should fail with an exception\n\t\t\t// Gecko does not error, returns false instead\n\t\t\tmatches.call( el, \"[s!='']:x\" );\n\t\t\trbuggyMatches.push( \"!=\", pseudos );\n\t\t});\n\t}\n\n\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join(\"|\") );\n\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join(\"|\") );\n\n\t/* Contains\n\t---------------------------------------------------------------------- */\n\thasCompare = rnative.test( docElem.compareDocumentPosition );\n\n\t// Element contains another\n\t// Purposefully self-exclusive\n\t// As in, an element does not contain itself\n\tcontains = hasCompare || rnative.test( docElem.contains ) ?\n\t\tfunction( a, b ) {\n\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n\t\t\t\tbup = b && b.parentNode;\n\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n\t\t\t\tadown.contains ?\n\t\t\t\t\tadown.contains( bup ) :\n\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n\t\t\t));\n\t\t} :\n\t\tfunction( a, b ) {\n\t\t\tif ( b ) {\n\t\t\t\twhile ( (b = b.parentNode) ) {\n\t\t\t\t\tif ( b === a ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n\n\t/* Sorting\n\t---------------------------------------------------------------------- */\n\n\t// Document order sorting\n\tsortOrder = hasCompare ?\n\tfunction( a, b ) {\n\n\t\t// Flag for duplicate removal\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\t// Sort on method existence if only one input has compareDocumentPosition\n\t\tvar compare = !a.compareDocumentPosition - !b.compareDocumentPosition;\n\t\tif ( compare ) {\n\t\t\treturn compare;\n\t\t}\n\n\t\t// Calculate position if both inputs belong to the same document\n\t\tcompare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?\n\t\t\ta.compareDocumentPosition( b ) :\n\n\t\t\t// Otherwise we know they are disconnected\n\t\t\t1;\n\n\t\t// Disconnected nodes\n\t\tif ( compare & 1 ||\n\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n\n\t\t\t// Choose the first element that is related to our preferred document\n\t\t\tif ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t\tif ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\t// Maintain original order\n\t\t\treturn sortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\t\t}\n\n\t\treturn compare & 4 ? -1 : 1;\n\t} :\n\tfunction( a, b ) {\n\t\t// Exit early if the nodes are identical\n\t\tif ( a === b ) {\n\t\t\thasDuplicate = true;\n\t\t\treturn 0;\n\t\t}\n\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\taup = a.parentNode,\n\t\t\tbup = b.parentNode,\n\t\t\tap = [ a ],\n\t\t\tbp = [ b ];\n\n\t\t// Parentless nodes are either documents or disconnected\n\t\tif ( !aup || !bup ) {\n\t\t\treturn a === document ? -1 :\n\t\t\t\tb === document ? 1 :\n\t\t\t\taup ? -1 :\n\t\t\t\tbup ? 1 :\n\t\t\t\tsortInput ?\n\t\t\t\t( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :\n\t\t\t\t0;\n\n\t\t// If the nodes are siblings, we can do a quick check\n\t\t} else if ( aup === bup ) {\n\t\t\treturn siblingCheck( a, b );\n\t\t}\n\n\t\t// Otherwise we need full lists of their ancestors for comparison\n\t\tcur = a;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tap.unshift( cur );\n\t\t}\n\t\tcur = b;\n\t\twhile ( (cur = cur.parentNode) ) {\n\t\t\tbp.unshift( cur );\n\t\t}\n\n\t\t// Walk down the tree looking for a discrepancy\n\t\twhile ( ap[i] === bp[i] ) {\n\t\t\ti++;\n\t\t}\n\n\t\treturn i ?\n\t\t\t// Do a sibling check if the nodes have a common ancestor\n\t\t\tsiblingCheck( ap[i], bp[i] ) :\n\n\t\t\t// Otherwise nodes in our document sort first\n\t\t\tap[i] === preferredDoc ? -1 :\n\t\t\tbp[i] === preferredDoc ? 1 :\n\t\t\t0;\n\t};\n\n\treturn document;\n};\n\nSizzle.matches = function( expr, elements ) {\n\treturn Sizzle( expr, null, null, elements );\n};\n\nSizzle.matchesSelector = function( elem, expr ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\t// Make sure that attribute selectors are quoted\n\texpr = expr.replace( rattributeQuotes, \"='$1']\" );\n\n\tif ( support.matchesSelector && documentIsHTML &&\n\t\t!compilerCache[ expr + \" \" ] &&\n\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n\n\t\ttry {\n\t\t\tvar ret = matches.call( elem, expr );\n\n\t\t\t// IE 9's matchesSelector returns false on disconnected nodes\n\t\t\tif ( ret || support.disconnectedMatch ||\n\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n\t\t\t\t\t// fragment in IE 9\n\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\t\t} catch (e) {}\n\t}\n\n\treturn Sizzle( expr, document, null, [ elem ] ).length > 0;\n};\n\nSizzle.contains = function( context, elem ) {\n\t// Set document vars if needed\n\tif ( ( context.ownerDocument || context ) !== document ) {\n\t\tsetDocument( context );\n\t}\n\treturn contains( context, elem );\n};\n\nSizzle.attr = function( elem, name ) {\n\t// Set document vars if needed\n\tif ( ( elem.ownerDocument || elem ) !== document ) {\n\t\tsetDocument( elem );\n\t}\n\n\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n\t\t// Don't get fooled by Object.prototype properties (jQuery #13807)\n\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n\t\t\tfn( elem, name, !documentIsHTML ) :\n\t\t\tundefined;\n\n\treturn val !== undefined ?\n\t\tval :\n\t\tsupport.attributes || !documentIsHTML ?\n\t\t\telem.getAttribute( name ) :\n\t\t\t(val = elem.getAttributeNode(name)) && val.specified ?\n\t\t\t\tval.value :\n\t\t\t\tnull;\n};\n\nSizzle.escape = function( sel ) {\n\treturn (sel + \"\").replace( rcssescape, fcssescape );\n};\n\nSizzle.error = function( msg ) {\n\tthrow new Error( \"Syntax error, unrecognized expression: \" + msg );\n};\n\n/**\n * Document sorting and removing duplicates\n * @param {ArrayLike} results\n */\nSizzle.uniqueSort = function( results ) {\n\tvar elem,\n\t\tduplicates = [],\n\t\tj = 0,\n\t\ti = 0;\n\n\t// Unless we *know* we can detect duplicates, assume their presence\n\thasDuplicate = !support.detectDuplicates;\n\tsortInput = !support.sortStable && results.slice( 0 );\n\tresults.sort( sortOrder );\n\n\tif ( hasDuplicate ) {\n\t\twhile ( (elem = results[i++]) ) {\n\t\t\tif ( elem === results[ i ] ) {\n\t\t\t\tj = duplicates.push( i );\n\t\t\t}\n\t\t}\n\t\twhile ( j-- ) {\n\t\t\tresults.splice( duplicates[ j ], 1 );\n\t\t}\n\t}\n\n\t// Clear input after sorting to release objects\n\t// See https://github.com/jquery/sizzle/pull/225\n\tsortInput = null;\n\n\treturn results;\n};\n\n/**\n * Utility function for retrieving the text value of an array of DOM nodes\n * @param {Array|Element} elem\n */\ngetText = Sizzle.getText = function( elem ) {\n\tvar node,\n\t\tret = \"\",\n\t\ti = 0,\n\t\tnodeType = elem.nodeType;\n\n\tif ( !nodeType ) {\n\t\t// If no nodeType, this is expected to be an array\n\t\twhile ( (node = elem[i++]) ) {\n\t\t\t// Do not traverse comment nodes\n\t\t\tret += getText( node );\n\t\t}\n\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n\t\t// Use textContent for elements\n\t\t// innerText usage removed for consistency of new lines (jQuery #11153)\n\t\tif ( typeof elem.textContent === \"string\" ) {\n\t\t\treturn elem.textContent;\n\t\t} else {\n\t\t\t// Traverse its children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tret += getText( elem );\n\t\t\t}\n\t\t}\n\t} else if ( nodeType === 3 || nodeType === 4 ) {\n\t\treturn elem.nodeValue;\n\t}\n\t// Do not include comment or processing instruction nodes\n\n\treturn ret;\n};\n\nExpr = Sizzle.selectors = {\n\n\t// Can be adjusted by the user\n\tcacheLength: 50,\n\n\tcreatePseudo: markFunction,\n\n\tmatch: matchExpr,\n\n\tattrHandle: {},\n\n\tfind: {},\n\n\trelative: {\n\t\t\">\": { dir: \"parentNode\", first: true },\n\t\t\" \": { dir: \"parentNode\" },\n\t\t\"+\": { dir: \"previousSibling\", first: true },\n\t\t\"~\": { dir: \"previousSibling\" }\n\t},\n\n\tpreFilter: {\n\t\t\"ATTR\": function( match ) {\n\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n\n\t\t\t// Move the given value to match[3] whether quoted or unquoted\n\t\t\tmatch[3] = ( match[3] || match[4] || match[5] || \"\" ).replace( runescape, funescape );\n\n\t\t\tif ( match[2] === \"~=\" ) {\n\t\t\t\tmatch[3] = \" \" + match[3] + \" \";\n\t\t\t}\n\n\t\t\treturn match.slice( 0, 4 );\n\t\t},\n\n\t\t\"CHILD\": function( match ) {\n\t\t\t/* matches from matchExpr[\"CHILD\"]\n\t\t\t\t1 type (only|nth|...)\n\t\t\t\t2 what (child|of-type)\n\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n\t\t\t\t5 sign of xn-component\n\t\t\t\t6 x of xn-component\n\t\t\t\t7 sign of y-component\n\t\t\t\t8 y of y-component\n\t\t\t*/\n\t\t\tmatch[1] = match[1].toLowerCase();\n\n\t\t\tif ( match[1].slice( 0, 3 ) === \"nth\" ) {\n\t\t\t\t// nth-* requires argument\n\t\t\t\tif ( !match[3] ) {\n\t\t\t\t\tSizzle.error( match[0] );\n\t\t\t\t}\n\n\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n\t\t\t\t// remember that false/true cast respectively to 0/1\n\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === \"even\" || match[3] === \"odd\" ) );\n\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === \"odd\" );\n\n\t\t\t// other types prohibit arguments\n\t\t\t} else if ( match[3] ) {\n\t\t\t\tSizzle.error( match[0] );\n\t\t\t}\n\n\t\t\treturn match;\n\t\t},\n\n\t\t\"PSEUDO\": function( match ) {\n\t\t\tvar excess,\n\t\t\t\tunquoted = !match[6] && match[2];\n\n\t\t\tif ( matchExpr[\"CHILD\"].test( match[0] ) ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\t// Accept quoted arguments as-is\n\t\t\tif ( match[3] ) {\n\t\t\t\tmatch[2] = match[4] || match[5] || \"\";\n\n\t\t\t// Strip excess characters from unquoted arguments\n\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n\t\t\t\t// Get excess from tokenize (recursively)\n\t\t\t\t(excess = tokenize( unquoted, true )) &&\n\t\t\t\t// advance to the next closing parenthesis\n\t\t\t\t(excess = unquoted.indexOf( \")\", unquoted.length - excess ) - unquoted.length) ) {\n\n\t\t\t\t// excess is a negative index\n\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n\t\t\t}\n\n\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n\t\t\treturn match.slice( 0, 3 );\n\t\t}\n\t},\n\n\tfilter: {\n\n\t\t\"TAG\": function( nodeNameSelector ) {\n\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn nodeNameSelector === \"*\" ?\n\t\t\t\tfunction() { return true; } :\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n\t\t\t\t};\n\t\t},\n\n\t\t\"CLASS\": function( className ) {\n\t\t\tvar pattern = classCache[ className + \" \" ];\n\n\t\t\treturn pattern ||\n\t\t\t\t(pattern = new RegExp( \"(^|\" + whitespace + \")\" + className + \"(\" + whitespace + \"|$)\" )) &&\n\t\t\t\tclassCache( className, function( elem ) {\n\t\t\t\t\treturn pattern.test( typeof elem.className === \"string\" && elem.className || typeof elem.getAttribute !== \"undefined\" && elem.getAttribute(\"class\") || \"\" );\n\t\t\t\t});\n\t\t},\n\n\t\t\"ATTR\": function( name, operator, check ) {\n\t\t\treturn function( elem ) {\n\t\t\t\tvar result = Sizzle.attr( elem, name );\n\n\t\t\t\tif ( result == null ) {\n\t\t\t\t\treturn operator === \"!=\";\n\t\t\t\t}\n\t\t\t\tif ( !operator ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\n\t\t\t\tresult += \"\";\n\n\t\t\t\treturn operator === \"=\" ? result === check :\n\t\t\t\t\toperator === \"!=\" ? result !== check :\n\t\t\t\t\toperator === \"^=\" ? check && result.indexOf( check ) === 0 :\n\t\t\t\t\toperator === \"*=\" ? check && result.indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"$=\" ? check && result.slice( -check.length ) === check :\n\t\t\t\t\toperator === \"~=\" ? ( \" \" + result.replace( rwhitespace, \" \" ) + \" \" ).indexOf( check ) > -1 :\n\t\t\t\t\toperator === \"|=\" ? result === check || result.slice( 0, check.length + 1 ) === check + \"-\" :\n\t\t\t\t\tfalse;\n\t\t\t};\n\t\t},\n\n\t\t\"CHILD\": function( type, what, argument, first, last ) {\n\t\t\tvar simple = type.slice( 0, 3 ) !== \"nth\",\n\t\t\t\tforward = type.slice( -4 ) !== \"last\",\n\t\t\t\tofType = what === \"of-type\";\n\n\t\t\treturn first === 1 && last === 0 ?\n\n\t\t\t\t// Shortcut for :nth-*(n)\n\t\t\t\tfunction( elem ) {\n\t\t\t\t\treturn !!elem.parentNode;\n\t\t\t\t} :\n\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tvar cache, uniqueCache, outerCache, node, nodeIndex, start,\n\t\t\t\t\t\tdir = simple !== forward ? \"nextSibling\" : \"previousSibling\",\n\t\t\t\t\t\tparent = elem.parentNode,\n\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n\t\t\t\t\t\tuseCache = !xml && !ofType,\n\t\t\t\t\t\tdiff = false;\n\n\t\t\t\t\tif ( parent ) {\n\n\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n\t\t\t\t\t\tif ( simple ) {\n\t\t\t\t\t\t\twhile ( dir ) {\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n\t\t\t\t\t\t\t\t\tif ( ofType ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) {\n\n\t\t\t\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven't yet done so)\n\t\t\t\t\t\t\t\tstart = dir = type === \"only\" && !start && \"nextSibling\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n\n\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n\t\t\t\t\t\tif ( forward && useCache ) {\n\n\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n\n\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\tnode = parent;\n\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\tdiff = nodeIndex && cache[ 2 ];\n\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n\n\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\n\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, nodeIndex, diff ];\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Use previously-cached element index if available\n\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t// ...in a gzip-friendly way\n\t\t\t\t\t\t\t\tnode = elem;\n\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\tcache = uniqueCache[ type ] || [];\n\t\t\t\t\t\t\t\tnodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];\n\t\t\t\t\t\t\t\tdiff = nodeIndex;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// xml :nth-child(...)\n\t\t\t\t\t\t\t// or :nth-last-child(...) or :nth(-last)?-of-type(...)\n\t\t\t\t\t\t\tif ( diff === false ) {\n\t\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n\t\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n\t\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n\n\t\t\t\t\t\t\t\t\tif ( ( ofType ?\n\t\t\t\t\t\t\t\t\t\tnode.nodeName.toLowerCase() === name :\n\t\t\t\t\t\t\t\t\t\tnode.nodeType === 1 ) &&\n\t\t\t\t\t\t\t\t\t\t++diff ) {\n\n\t\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n\t\t\t\t\t\t\t\t\t\tif ( useCache ) {\n\t\t\t\t\t\t\t\t\t\t\touterCache = node[ expando ] || (node[ expando ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache = outerCache[ node.uniqueID ] ||\n\t\t\t\t\t\t\t\t\t\t\t\t(outerCache[ node.uniqueID ] = {});\n\n\t\t\t\t\t\t\t\t\t\t\tuniqueCache[ type ] = [ dirruns, diff ];\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n\t\t\t\t\t\tdiff -= last;\n\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t},\n\n\t\t\"PSEUDO\": function( pseudo, argument ) {\n\t\t\t// pseudo-class names are case-insensitive\n\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n\t\t\t// Remember that setFilters inherits from pseudos\n\t\t\tvar args,\n\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n\t\t\t\t\tSizzle.error( \"unsupported pseudo: \" + pseudo );\n\n\t\t\t// The user may use createPseudo to indicate that\n\t\t\t// arguments are needed to create the filter function\n\t\t\t// just as Sizzle does\n\t\t\tif ( fn[ expando ] ) {\n\t\t\t\treturn fn( argument );\n\t\t\t}\n\n\t\t\t// But maintain support for old signatures\n\t\t\tif ( fn.length > 1 ) {\n\t\t\t\targs = [ pseudo, pseudo, \"\", argument ];\n\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n\t\t\t\t\tmarkFunction(function( seed, matches ) {\n\t\t\t\t\t\tvar idx,\n\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n\t\t\t\t\t\t\ti = matched.length;\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tidx = indexOf( seed, matched[i] );\n\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}) :\n\t\t\t\t\tfunction( elem ) {\n\t\t\t\t\t\treturn fn( elem, 0, args );\n\t\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn fn;\n\t\t}\n\t},\n\n\tpseudos: {\n\t\t// Potentially complex pseudos\n\t\t\"not\": markFunction(function( selector ) {\n\t\t\t// Trim the selector passed to compile\n\t\t\t// to avoid treating leading and trailing\n\t\t\t// spaces as combinators\n\t\t\tvar input = [],\n\t\t\t\tresults = [],\n\t\t\t\tmatcher = compile( selector.replace( rtrim, \"$1\" ) );\n\n\t\t\treturn matcher[ expando ] ?\n\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n\t\t\t\t\tvar elem,\n\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n\t\t\t\t\t\ti = seed.length;\n\n\t\t\t\t\t// Match elements unmatched by `matcher`\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}) :\n\t\t\t\tfunction( elem, context, xml ) {\n\t\t\t\t\tinput[0] = elem;\n\t\t\t\t\tmatcher( input, null, xml, results );\n\t\t\t\t\t// Don't keep the element (issue #299)\n\t\t\t\t\tinput[0] = null;\n\t\t\t\t\treturn !results.pop();\n\t\t\t\t};\n\t\t}),\n\n\t\t\"has\": markFunction(function( selector ) {\n\t\t\treturn function( elem ) {\n\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n\t\t\t};\n\t\t}),\n\n\t\t\"contains\": markFunction(function( text ) {\n\t\t\ttext = text.replace( runescape, funescape );\n\t\t\treturn function( elem ) {\n\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n\t\t\t};\n\t\t}),\n\n\t\t// \"Whether an element is represented by a :lang() selector\n\t\t// is based solely on the element's language value\n\t\t// being equal to the identifier C,\n\t\t// or beginning with the identifier C immediately followed by \"-\".\n\t\t// The matching of C against the element's language value is performed case-insensitively.\n\t\t// The identifier C does not have to be a valid language name.\"\n\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n\t\t\"lang\": markFunction( function( lang ) {\n\t\t\t// lang value must be a valid identifier\n\t\t\tif ( !ridentifier.test(lang || \"\") ) {\n\t\t\t\tSizzle.error( \"unsupported lang: \" + lang );\n\t\t\t}\n\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n\t\t\treturn function( elem ) {\n\t\t\t\tvar elemLang;\n\t\t\t\tdo {\n\t\t\t\t\tif ( (elemLang = documentIsHTML ?\n\t\t\t\t\t\telem.lang :\n\t\t\t\t\t\telem.getAttribute(\"xml:lang\") || elem.getAttribute(\"lang\")) ) {\n\n\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + \"-\" ) === 0;\n\t\t\t\t\t}\n\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n\t\t\t\treturn false;\n\t\t\t};\n\t\t}),\n\n\t\t// Miscellaneous\n\t\t\"target\": function( elem ) {\n\t\t\tvar hash = window.location && window.location.hash;\n\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n\t\t},\n\n\t\t\"root\": function( elem ) {\n\t\t\treturn elem === docElem;\n\t\t},\n\n\t\t\"focus\": function( elem ) {\n\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n\t\t},\n\n\t\t// Boolean properties\n\t\t\"enabled\": createDisabledPseudo( false ),\n\t\t\"disabled\": createDisabledPseudo( true ),\n\n\t\t\"checked\": function( elem ) {\n\t\t\t// In CSS3, :checked should return both checked and selected elements\n\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n\t\t\treturn (nodeName === \"input\" && !!elem.checked) || (nodeName === \"option\" && !!elem.selected);\n\t\t},\n\n\t\t\"selected\": function( elem ) {\n\t\t\t// Accessing this property makes selected-by-default\n\t\t\t// options in Safari work properly\n\t\t\tif ( elem.parentNode ) {\n\t\t\t\telem.parentNode.selectedIndex;\n\t\t\t}\n\n\t\t\treturn elem.selected === true;\n\t\t},\n\n\t\t// Contents\n\t\t\"empty\": function( elem ) {\n\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n\t\t\t// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),\n\t\t\t//   but not by others (comment: 8; processing instruction: 7; etc.)\n\t\t\t// nodeType < 6 works because attributes (2) do not appear as children\n\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n\t\t\t\tif ( elem.nodeType < 6 ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t},\n\n\t\t\"parent\": function( elem ) {\n\t\t\treturn !Expr.pseudos[\"empty\"]( elem );\n\t\t},\n\n\t\t// Element/input types\n\t\t\"header\": function( elem ) {\n\t\t\treturn rheader.test( elem.nodeName );\n\t\t},\n\n\t\t\"input\": function( elem ) {\n\t\t\treturn rinputs.test( elem.nodeName );\n\t\t},\n\n\t\t\"button\": function( elem ) {\n\t\t\tvar name = elem.nodeName.toLowerCase();\n\t\t\treturn name === \"input\" && elem.type === \"button\" || name === \"button\";\n\t\t},\n\n\t\t\"text\": function( elem ) {\n\t\t\tvar attr;\n\t\t\treturn elem.nodeName.toLowerCase() === \"input\" &&\n\t\t\t\telem.type === \"text\" &&\n\n\t\t\t\t// Support: IE<8\n\t\t\t\t// New HTML5 attribute values (e.g., \"search\") appear with elem.type === \"text\"\n\t\t\t\t( (attr = elem.getAttribute(\"type\")) == null || attr.toLowerCase() === \"text\" );\n\t\t},\n\n\t\t// Position-in-collection\n\t\t\"first\": createPositionalPseudo(function() {\n\t\t\treturn [ 0 ];\n\t\t}),\n\n\t\t\"last\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\treturn [ length - 1 ];\n\t\t}),\n\n\t\t\"eq\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\treturn [ argument < 0 ? argument + length : argument ];\n\t\t}),\n\n\t\t\"even\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"odd\": createPositionalPseudo(function( matchIndexes, length ) {\n\t\t\tvar i = 1;\n\t\t\tfor ( ; i < length; i += 2 ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"lt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; --i >= 0; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t}),\n\n\t\t\"gt\": createPositionalPseudo(function( matchIndexes, length, argument ) {\n\t\t\tvar i = argument < 0 ? argument + length : argument;\n\t\t\tfor ( ; ++i < length; ) {\n\t\t\t\tmatchIndexes.push( i );\n\t\t\t}\n\t\t\treturn matchIndexes;\n\t\t})\n\t}\n};\n\nExpr.pseudos[\"nth\"] = Expr.pseudos[\"eq\"];\n\n// Add button/input type pseudos\nfor ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n\tExpr.pseudos[ i ] = createInputPseudo( i );\n}\nfor ( i in { submit: true, reset: true } ) {\n\tExpr.pseudos[ i ] = createButtonPseudo( i );\n}\n\n// Easy API for creating new setFilters\nfunction setFilters() {}\nsetFilters.prototype = Expr.filters = Expr.pseudos;\nExpr.setFilters = new setFilters();\n\ntokenize = Sizzle.tokenize = function( selector, parseOnly ) {\n\tvar matched, match, tokens, type,\n\t\tsoFar, groups, preFilters,\n\t\tcached = tokenCache[ selector + \" \" ];\n\n\tif ( cached ) {\n\t\treturn parseOnly ? 0 : cached.slice( 0 );\n\t}\n\n\tsoFar = selector;\n\tgroups = [];\n\tpreFilters = Expr.preFilter;\n\n\twhile ( soFar ) {\n\n\t\t// Comma and first run\n\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n\t\t\tif ( match ) {\n\t\t\t\t// Don't consume trailing commas as valid\n\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n\t\t\t}\n\t\t\tgroups.push( (tokens = []) );\n\t\t}\n\n\t\tmatched = false;\n\n\t\t// Combinators\n\t\tif ( (match = rcombinators.exec( soFar )) ) {\n\t\t\tmatched = match.shift();\n\t\t\ttokens.push({\n\t\t\t\tvalue: matched,\n\t\t\t\t// Cast descendant combinators to space\n\t\t\t\ttype: match[0].replace( rtrim, \" \" )\n\t\t\t});\n\t\t\tsoFar = soFar.slice( matched.length );\n\t\t}\n\n\t\t// Filters\n\t\tfor ( type in Expr.filter ) {\n\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n\t\t\t\tmatched = match.shift();\n\t\t\t\ttokens.push({\n\t\t\t\t\tvalue: matched,\n\t\t\t\t\ttype: type,\n\t\t\t\t\tmatches: match\n\t\t\t\t});\n\t\t\t\tsoFar = soFar.slice( matched.length );\n\t\t\t}\n\t\t}\n\n\t\tif ( !matched ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Return the length of the invalid excess\n\t// if we're just parsing\n\t// Otherwise, throw an error or return tokens\n\treturn parseOnly ?\n\t\tsoFar.length :\n\t\tsoFar ?\n\t\t\tSizzle.error( selector ) :\n\t\t\t// Cache the tokens\n\t\t\ttokenCache( selector, groups ).slice( 0 );\n};\n\nfunction toSelector( tokens ) {\n\tvar i = 0,\n\t\tlen = tokens.length,\n\t\tselector = \"\";\n\tfor ( ; i < len; i++ ) {\n\t\tselector += tokens[i].value;\n\t}\n\treturn selector;\n}\n\nfunction addCombinator( matcher, combinator, base ) {\n\tvar dir = combinator.dir,\n\t\tskip = combinator.next,\n\t\tkey = skip || dir,\n\t\tcheckNonElements = base && key === \"parentNode\",\n\t\tdoneName = done++;\n\n\treturn combinator.first ?\n\t\t// Check against closest ancestor/preceding element\n\t\tfunction( elem, context, xml ) {\n\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\treturn matcher( elem, context, xml );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t} :\n\n\t\t// Check against all ancestor/preceding elements\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar oldCache, uniqueCache, outerCache,\n\t\t\t\tnewCache = [ dirruns, doneName ];\n\n\t\t\t// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching\n\t\t\tif ( xml ) {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n\n\t\t\t\t\t\t// Support: IE <9 only\n\t\t\t\t\t\t// Defend against cloned attroperties (jQuery gh-1709)\n\t\t\t\t\t\tuniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});\n\n\t\t\t\t\t\tif ( skip && skip === elem.nodeName.toLowerCase() ) {\n\t\t\t\t\t\t\telem = elem[ dir ] || elem;\n\t\t\t\t\t\t} else if ( (oldCache = uniqueCache[ key ]) &&\n\t\t\t\t\t\t\toldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {\n\n\t\t\t\t\t\t\t// Assign to newCache so results back-propagate to previous elements\n\t\t\t\t\t\t\treturn (newCache[ 2 ] = oldCache[ 2 ]);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// Reuse newcache so results back-propagate to previous elements\n\t\t\t\t\t\t\tuniqueCache[ key ] = newCache;\n\n\t\t\t\t\t\t\t// A match means we're done; a fail means we have to keep checking\n\t\t\t\t\t\t\tif ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn false;\n\t\t};\n}\n\nfunction elementMatcher( matchers ) {\n\treturn matchers.length > 1 ?\n\t\tfunction( elem, context, xml ) {\n\t\t\tvar i = matchers.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t} :\n\t\tmatchers[0];\n}\n\nfunction multipleContexts( selector, contexts, results ) {\n\tvar i = 0,\n\t\tlen = contexts.length;\n\tfor ( ; i < len; i++ ) {\n\t\tSizzle( selector, contexts[i], results );\n\t}\n\treturn results;\n}\n\nfunction condense( unmatched, map, filter, context, xml ) {\n\tvar elem,\n\t\tnewUnmatched = [],\n\t\ti = 0,\n\t\tlen = unmatched.length,\n\t\tmapped = map != null;\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (elem = unmatched[i]) ) {\n\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n\t\t\t\tnewUnmatched.push( elem );\n\t\t\t\tif ( mapped ) {\n\t\t\t\t\tmap.push( i );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn newUnmatched;\n}\n\nfunction setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n\tif ( postFilter && !postFilter[ expando ] ) {\n\t\tpostFilter = setMatcher( postFilter );\n\t}\n\tif ( postFinder && !postFinder[ expando ] ) {\n\t\tpostFinder = setMatcher( postFinder, postSelector );\n\t}\n\treturn markFunction(function( seed, results, context, xml ) {\n\t\tvar temp, i, elem,\n\t\t\tpreMap = [],\n\t\t\tpostMap = [],\n\t\t\tpreexisting = results.length,\n\n\t\t\t// Get initial elements from seed or context\n\t\t\telems = seed || multipleContexts( selector || \"*\", context.nodeType ? [ context ] : context, [] ),\n\n\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n\t\t\t\telems,\n\n\t\t\tmatcherOut = matcher ?\n\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n\n\t\t\t\t\t// ...intermediate processing is necessary\n\t\t\t\t\t[] :\n\n\t\t\t\t\t// ...otherwise use results directly\n\t\t\t\t\tresults :\n\t\t\t\tmatcherIn;\n\n\t\t// Find primary matches\n\t\tif ( matcher ) {\n\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n\t\t}\n\n\t\t// Apply postFilter\n\t\tif ( postFilter ) {\n\t\t\ttemp = condense( matcherOut, postMap );\n\t\t\tpostFilter( temp, [], context, xml );\n\n\t\t\t// Un-match failing elements by moving them back to matcherIn\n\t\t\ti = temp.length;\n\t\t\twhile ( i-- ) {\n\t\t\t\tif ( (elem = temp[i]) ) {\n\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( seed ) {\n\t\t\tif ( postFinder || preFilter ) {\n\t\t\t\tif ( postFinder ) {\n\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n\t\t\t\t\ttemp = [];\n\t\t\t\t\ti = matcherOut.length;\n\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n\t\t\t\t}\n\n\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n\t\t\t\ti = matcherOut.length;\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n\t\t\t\t\t\t(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {\n\n\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Add elements to results, through postFinder if defined\n\t\t} else {\n\t\t\tmatcherOut = condense(\n\t\t\t\tmatcherOut === results ?\n\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n\t\t\t\t\tmatcherOut\n\t\t\t);\n\t\t\tif ( postFinder ) {\n\t\t\t\tpostFinder( null, results, matcherOut, xml );\n\t\t\t} else {\n\t\t\t\tpush.apply( results, matcherOut );\n\t\t\t}\n\t\t}\n\t});\n}\n\nfunction matcherFromTokens( tokens ) {\n\tvar checkContext, matcher, j,\n\t\tlen = tokens.length,\n\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n\t\timplicitRelative = leadingRelative || Expr.relative[\" \"],\n\t\ti = leadingRelative ? 1 : 0,\n\n\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n\t\tmatchContext = addCombinator( function( elem ) {\n\t\t\treturn elem === checkContext;\n\t\t}, implicitRelative, true ),\n\t\tmatchAnyContext = addCombinator( function( elem ) {\n\t\t\treturn indexOf( checkContext, elem ) > -1;\n\t\t}, implicitRelative, true ),\n\t\tmatchers = [ function( elem, context, xml ) {\n\t\t\tvar ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n\t\t\t\t(checkContext = context).nodeType ?\n\t\t\t\t\tmatchContext( elem, context, xml ) :\n\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n\t\t\t// Avoid hanging onto element (issue #299)\n\t\t\tcheckContext = null;\n\t\t\treturn ret;\n\t\t} ];\n\n\tfor ( ; i < len; i++ ) {\n\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n\t\t} else {\n\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n\n\t\t\t// Return special upon seeing a positional matcher\n\t\t\tif ( matcher[ expando ] ) {\n\t\t\t\t// Find the next relative operator (if any) for proper handling\n\t\t\t\tj = ++i;\n\t\t\t\tfor ( ; j < len; j++ ) {\n\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn setMatcher(\n\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n\t\t\t\t\ti > 1 && toSelector(\n\t\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n\t\t\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === \" \" ? \"*\" : \"\" })\n\t\t\t\t\t).replace( rtrim, \"$1\" ),\n\t\t\t\t\tmatcher,\n\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n\t\t\t\t\tj < len && toSelector( tokens )\n\t\t\t\t);\n\t\t\t}\n\t\t\tmatchers.push( matcher );\n\t\t}\n\t}\n\n\treturn elementMatcher( matchers );\n}\n\nfunction matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n\tvar bySet = setMatchers.length > 0,\n\t\tbyElement = elementMatchers.length > 0,\n\t\tsuperMatcher = function( seed, context, xml, results, outermost ) {\n\t\t\tvar elem, j, matcher,\n\t\t\t\tmatchedCount = 0,\n\t\t\t\ti = \"0\",\n\t\t\t\tunmatched = seed && [],\n\t\t\t\tsetMatched = [],\n\t\t\t\tcontextBackup = outermostContext,\n\t\t\t\t// We must always have either seed elements or outermost context\n\t\t\t\telems = seed || byElement && Expr.find[\"TAG\"]( \"*\", outermost ),\n\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),\n\t\t\t\tlen = elems.length;\n\n\t\t\tif ( outermost ) {\n\t\t\t\toutermostContext = context === document || context || outermost;\n\t\t\t}\n\n\t\t\t// Add elements passing elementMatchers directly to results\n\t\t\t// Support: IE<9, Safari\n\t\t\t// Tolerate NodeList properties (IE: \"length\"; Safari: <number>) matching elements by id\n\t\t\tfor ( ; i !== len && (elem = elems[i]) != null; i++ ) {\n\t\t\t\tif ( byElement && elem ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\tif ( !context && elem.ownerDocument !== document ) {\n\t\t\t\t\t\tsetDocument( elem );\n\t\t\t\t\t\txml = !documentIsHTML;\n\t\t\t\t\t}\n\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n\t\t\t\t\t\tif ( matcher( elem, context || document, xml) ) {\n\t\t\t\t\t\t\tresults.push( elem );\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( outermost ) {\n\t\t\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Track unmatched elements for set filters\n\t\t\t\tif ( bySet ) {\n\t\t\t\t\t// They will have gone through all possible matchers\n\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n\t\t\t\t\t\tmatchedCount--;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Lengthen the array for every element, matched or not\n\t\t\t\t\tif ( seed ) {\n\t\t\t\t\t\tunmatched.push( elem );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// `i` is now the count of elements visited above, and adding it to `matchedCount`\n\t\t\t// makes the latter nonnegative.\n\t\t\tmatchedCount += i;\n\n\t\t\t// Apply set filters to unmatched elements\n\t\t\t// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`\n\t\t\t// equals `i`), unless we didn't visit _any_ elements in the above loop because we have\n\t\t\t// no element matchers and no seed.\n\t\t\t// Incrementing an initially-string \"0\" `i` allows `i` to remain a string only in that\n\t\t\t// case, which will result in a \"00\" `matchedCount` that differs from `i` but is also\n\t\t\t// numerically zero.\n\t\t\tif ( bySet && i !== matchedCount ) {\n\t\t\t\tj = 0;\n\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n\t\t\t\t}\n\n\t\t\t\tif ( seed ) {\n\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n\t\t\t\t\tif ( matchedCount > 0 ) {\n\t\t\t\t\t\twhile ( i-- ) {\n\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Discard index placeholder values to get only actual matches\n\t\t\t\t\tsetMatched = condense( setMatched );\n\t\t\t\t}\n\n\t\t\t\t// Add matches to results\n\t\t\t\tpush.apply( results, setMatched );\n\n\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n\n\t\t\t\t\tSizzle.uniqueSort( results );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Override manipulation of globals by nested matchers\n\t\t\tif ( outermost ) {\n\t\t\t\tdirruns = dirrunsUnique;\n\t\t\t\toutermostContext = contextBackup;\n\t\t\t}\n\n\t\t\treturn unmatched;\n\t\t};\n\n\treturn bySet ?\n\t\tmarkFunction( superMatcher ) :\n\t\tsuperMatcher;\n}\n\ncompile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {\n\tvar i,\n\t\tsetMatchers = [],\n\t\telementMatchers = [],\n\t\tcached = compilerCache[ selector + \" \" ];\n\n\tif ( !cached ) {\n\t\t// Generate a function of recursive functions that can be used to check each element\n\t\tif ( !match ) {\n\t\t\tmatch = tokenize( selector );\n\t\t}\n\t\ti = match.length;\n\t\twhile ( i-- ) {\n\t\t\tcached = matcherFromTokens( match[i] );\n\t\t\tif ( cached[ expando ] ) {\n\t\t\t\tsetMatchers.push( cached );\n\t\t\t} else {\n\t\t\t\telementMatchers.push( cached );\n\t\t\t}\n\t\t}\n\n\t\t// Cache the compiled function\n\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n\n\t\t// Save selector and tokenization\n\t\tcached.selector = selector;\n\t}\n\treturn cached;\n};\n\n/**\n * A low-level selection function that works with Sizzle's compiled\n *  selector functions\n * @param {String|Function} selector A selector or a pre-compiled\n *  selector function built with Sizzle.compile\n * @param {Element} context\n * @param {Array} [results]\n * @param {Array} [seed] A set of elements to match against\n */\nselect = Sizzle.select = function( selector, context, results, seed ) {\n\tvar i, tokens, token, type, find,\n\t\tcompiled = typeof selector === \"function\" && selector,\n\t\tmatch = !seed && tokenize( (selector = compiled.selector || selector) );\n\n\tresults = results || [];\n\n\t// Try to minimize operations if there is only one selector in the list and no seed\n\t// (the latter of which guarantees us context)\n\tif ( match.length === 1 ) {\n\n\t\t// Reduce context if the leading compound selector is an ID\n\t\ttokens = match[0] = match[0].slice( 0 );\n\t\tif ( tokens.length > 2 && (token = tokens[0]).type === \"ID\" &&\n\t\t\t\tcontext.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {\n\n\t\t\tcontext = ( Expr.find[\"ID\"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n\t\t\tif ( !context ) {\n\t\t\t\treturn results;\n\n\t\t\t// Precompiled matchers will still verify ancestry, so step up a level\n\t\t\t} else if ( compiled ) {\n\t\t\t\tcontext = context.parentNode;\n\t\t\t}\n\n\t\t\tselector = selector.slice( tokens.shift().value.length );\n\t\t}\n\n\t\t// Fetch a seed set for right-to-left matching\n\t\ti = matchExpr[\"needsContext\"].test( selector ) ? 0 : tokens.length;\n\t\twhile ( i-- ) {\n\t\t\ttoken = tokens[i];\n\n\t\t\t// Abort if we hit a combinator\n\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( (find = Expr.find[ type ]) ) {\n\t\t\t\t// Search, expanding context for leading sibling combinators\n\t\t\t\tif ( (seed = find(\n\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n\t\t\t\t\trsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context\n\t\t\t\t)) ) {\n\n\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n\t\t\t\t\ttokens.splice( i, 1 );\n\t\t\t\t\tselector = seed.length && toSelector( tokens );\n\t\t\t\t\tif ( !selector ) {\n\t\t\t\t\t\tpush.apply( results, seed );\n\t\t\t\t\t\treturn results;\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compile and execute a filtering function if one is not provided\n\t// Provide `match` to avoid retokenization if we modified the selector above\n\t( compiled || compile( selector, match ) )(\n\t\tseed,\n\t\tcontext,\n\t\t!documentIsHTML,\n\t\tresults,\n\t\t!context || rsibling.test( selector ) && testContext( context.parentNode ) || context\n\t);\n\treturn results;\n};\n\n// One-time assignments\n\n// Sort stability\nsupport.sortStable = expando.split(\"\").sort( sortOrder ).join(\"\") === expando;\n\n// Support: Chrome 14-35+\n// Always assume duplicates if they aren't passed to the comparison function\nsupport.detectDuplicates = !!hasDuplicate;\n\n// Initialize against the default document\nsetDocument();\n\n// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n// Detached nodes confoundingly follow *each other*\nsupport.sortDetached = assert(function( el ) {\n\t// Should return 1, but returns 4 (following)\n\treturn el.compareDocumentPosition( document.createElement(\"fieldset\") ) & 1;\n});\n\n// Support: IE<8\n// Prevent attribute/property \"interpolation\"\n// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\nif ( !assert(function( el ) {\n\tel.innerHTML = \"<a href='#'></a>\";\n\treturn el.firstChild.getAttribute(\"href\") === \"#\" ;\n}) ) {\n\taddHandle( \"type|href|height|width\", function( elem, name, isXML ) {\n\t\tif ( !isXML ) {\n\t\t\treturn elem.getAttribute( name, name.toLowerCase() === \"type\" ? 1 : 2 );\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use defaultValue in place of getAttribute(\"value\")\nif ( !support.attributes || !assert(function( el ) {\n\tel.innerHTML = \"<input/>\";\n\tel.firstChild.setAttribute( \"value\", \"\" );\n\treturn el.firstChild.getAttribute( \"value\" ) === \"\";\n}) ) {\n\taddHandle( \"value\", function( elem, name, isXML ) {\n\t\tif ( !isXML && elem.nodeName.toLowerCase() === \"input\" ) {\n\t\t\treturn elem.defaultValue;\n\t\t}\n\t});\n}\n\n// Support: IE<9\n// Use getAttributeNode to fetch booleans when getAttribute lies\nif ( !assert(function( el ) {\n\treturn el.getAttribute(\"disabled\") == null;\n}) ) {\n\taddHandle( booleans, function( elem, name, isXML ) {\n\t\tvar val;\n\t\tif ( !isXML ) {\n\t\t\treturn elem[ name ] === true ? name.toLowerCase() :\n\t\t\t\t\t(val = elem.getAttributeNode( name )) && val.specified ?\n\t\t\t\t\tval.value :\n\t\t\t\tnull;\n\t\t}\n\t});\n}\n\nreturn Sizzle;\n\n})( window );\n\n\n\njQuery.find = Sizzle;\njQuery.expr = Sizzle.selectors;\n\n// Deprecated\njQuery.expr[ \":\" ] = jQuery.expr.pseudos;\njQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;\njQuery.text = Sizzle.getText;\njQuery.isXMLDoc = Sizzle.isXML;\njQuery.contains = Sizzle.contains;\njQuery.escapeSelector = Sizzle.escape;\n\n\n\n\nvar dir = function( elem, dir, until ) {\n\tvar matched = [],\n\t\ttruncate = until !== undefined;\n\n\twhile ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {\n\t\tif ( elem.nodeType === 1 ) {\n\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmatched.push( elem );\n\t\t}\n\t}\n\treturn matched;\n};\n\n\nvar siblings = function( n, elem ) {\n\tvar matched = [];\n\n\tfor ( ; n; n = n.nextSibling ) {\n\t\tif ( n.nodeType === 1 && n !== elem ) {\n\t\t\tmatched.push( n );\n\t\t}\n\t}\n\n\treturn matched;\n};\n\n\nvar rneedsContext = jQuery.expr.match.needsContext;\n\nvar rsingleTag = ( /^<([a-z][^\\/\\0>:\\x20\\t\\r\\n\\f]*)[\\x20\\t\\r\\n\\f]*\\/?>(?:<\\/\\1>|)$/i );\n\n\n\nvar risSimple = /^.[^:#\\[\\.,]*$/;\n\n// Implement the identical functionality for filter and not\nfunction winnow( elements, qualifier, not ) {\n\tif ( jQuery.isFunction( qualifier ) ) {\n\t\treturn jQuery.grep( elements, function( elem, i ) {\n\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n\t\t} );\n\t}\n\n\t// Single element\n\tif ( qualifier.nodeType ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( elem === qualifier ) !== not;\n\t\t} );\n\t}\n\n\t// Arraylike of elements (jQuery, arguments, Array)\n\tif ( typeof qualifier !== \"string\" ) {\n\t\treturn jQuery.grep( elements, function( elem ) {\n\t\t\treturn ( indexOf.call( qualifier, elem ) > -1 ) !== not;\n\t\t} );\n\t}\n\n\t// Simple selector that can be filtered directly, removing non-Elements\n\tif ( risSimple.test( qualifier ) ) {\n\t\treturn jQuery.filter( qualifier, elements, not );\n\t}\n\n\t// Complex selector, compare the two sets, removing non-Elements\n\tqualifier = jQuery.filter( qualifier, elements );\n\treturn jQuery.grep( elements, function( elem ) {\n\t\treturn ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1;\n\t} );\n}\n\njQuery.filter = function( expr, elems, not ) {\n\tvar elem = elems[ 0 ];\n\n\tif ( not ) {\n\t\texpr = \":not(\" + expr + \")\";\n\t}\n\n\tif ( elems.length === 1 && elem.nodeType === 1 ) {\n\t\treturn jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];\n\t}\n\n\treturn jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n\t\treturn elem.nodeType === 1;\n\t} ) );\n};\n\njQuery.fn.extend( {\n\tfind: function( selector ) {\n\t\tvar i, ret,\n\t\t\tlen = this.length,\n\t\t\tself = this;\n\n\t\tif ( typeof selector !== \"string\" ) {\n\t\t\treturn this.pushStack( jQuery( selector ).filter( function() {\n\t\t\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} ) );\n\t\t}\n\n\t\tret = this.pushStack( [] );\n\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\tjQuery.find( selector, self[ i ], ret );\n\t\t}\n\n\t\treturn len > 1 ? jQuery.uniqueSort( ret ) : ret;\n\t},\n\tfilter: function( selector ) {\n\t\treturn this.pushStack( winnow( this, selector || [], false ) );\n\t},\n\tnot: function( selector ) {\n\t\treturn this.pushStack( winnow( this, selector || [], true ) );\n\t},\n\tis: function( selector ) {\n\t\treturn !!winnow(\n\t\t\tthis,\n\n\t\t\t// If this is a positional/relative selector, check membership in the returned set\n\t\t\t// so $(\"p:first\").is(\"p:last\") won't return true for a doc with two \"p\".\n\t\t\ttypeof selector === \"string\" && rneedsContext.test( selector ) ?\n\t\t\t\tjQuery( selector ) :\n\t\t\t\tselector || [],\n\t\t\tfalse\n\t\t).length;\n\t}\n} );\n\n\n// Initialize a jQuery object\n\n\n// A central reference to the root jQuery(document)\nvar rootjQuery,\n\n\t// A simple way to check for HTML strings\n\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n\t// Strict HTML recognition (#11290: must start with <)\n\t// Shortcut simple #id case for speed\n\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]+))$/,\n\n\tinit = jQuery.fn.init = function( selector, context, root ) {\n\t\tvar match, elem;\n\n\t\t// HANDLE: $(\"\"), $(null), $(undefined), $(false)\n\t\tif ( !selector ) {\n\t\t\treturn this;\n\t\t}\n\n\t\t// Method init() accepts an alternate rootjQuery\n\t\t// so migrate can support jQuery.sub (gh-2101)\n\t\troot = root || rootjQuery;\n\n\t\t// Handle HTML strings\n\t\tif ( typeof selector === \"string\" ) {\n\t\t\tif ( selector[ 0 ] === \"<\" &&\n\t\t\t\tselector[ selector.length - 1 ] === \">\" &&\n\t\t\t\tselector.length >= 3 ) {\n\n\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n\t\t\t\tmatch = [ null, selector, null ];\n\n\t\t\t} else {\n\t\t\t\tmatch = rquickExpr.exec( selector );\n\t\t\t}\n\n\t\t\t// Match html or make sure no context is specified for #id\n\t\t\tif ( match && ( match[ 1 ] || !context ) ) {\n\n\t\t\t\t// HANDLE: $(html) -> $(array)\n\t\t\t\tif ( match[ 1 ] ) {\n\t\t\t\t\tcontext = context instanceof jQuery ? context[ 0 ] : context;\n\n\t\t\t\t\t// Option to run scripts is true for back-compat\n\t\t\t\t\t// Intentionally let the error be thrown if parseHTML is not present\n\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n\t\t\t\t\t\tmatch[ 1 ],\n\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t) );\n\n\t\t\t\t\t// HANDLE: $(html, props)\n\t\t\t\t\tif ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {\n\t\t\t\t\t\tfor ( match in context ) {\n\n\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n\n\t\t\t\t\t\t\t// ...and otherwise set as attributes\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\treturn this;\n\n\t\t\t\t// HANDLE: $(#id)\n\t\t\t\t} else {\n\t\t\t\t\telem = document.getElementById( match[ 2 ] );\n\n\t\t\t\t\tif ( elem ) {\n\n\t\t\t\t\t\t// Inject the element directly into the jQuery object\n\t\t\t\t\t\tthis[ 0 ] = elem;\n\t\t\t\t\t\tthis.length = 1;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\n\t\t\t// HANDLE: $(expr, $(...))\n\t\t\t} else if ( !context || context.jquery ) {\n\t\t\t\treturn ( context || root ).find( selector );\n\n\t\t\t// HANDLE: $(expr, context)\n\t\t\t// (which is just equivalent to: $(context).find(expr)\n\t\t\t} else {\n\t\t\t\treturn this.constructor( context ).find( selector );\n\t\t\t}\n\n\t\t// HANDLE: $(DOMElement)\n\t\t} else if ( selector.nodeType ) {\n\t\t\tthis[ 0 ] = selector;\n\t\t\tthis.length = 1;\n\t\t\treturn this;\n\n\t\t// HANDLE: $(function)\n\t\t// Shortcut for document ready\n\t\t} else if ( jQuery.isFunction( selector ) ) {\n\t\t\treturn root.ready !== undefined ?\n\t\t\t\troot.ready( selector ) :\n\n\t\t\t\t// Execute immediately if ready is not present\n\t\t\t\tselector( jQuery );\n\t\t}\n\n\t\treturn jQuery.makeArray( selector, this );\n\t};\n\n// Give the init function the jQuery prototype for later instantiation\ninit.prototype = jQuery.fn;\n\n// Initialize central reference\nrootjQuery = jQuery( document );\n\n\nvar rparentsprev = /^(?:parents|prev(?:Until|All))/,\n\n\t// Methods guaranteed to produce a unique set when starting from a unique set\n\tguaranteedUnique = {\n\t\tchildren: true,\n\t\tcontents: true,\n\t\tnext: true,\n\t\tprev: true\n\t};\n\njQuery.fn.extend( {\n\thas: function( target ) {\n\t\tvar targets = jQuery( target, this ),\n\t\t\tl = targets.length;\n\n\t\treturn this.filter( function() {\n\t\t\tvar i = 0;\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tif ( jQuery.contains( this, targets[ i ] ) ) {\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\tclosest: function( selectors, context ) {\n\t\tvar cur,\n\t\t\ti = 0,\n\t\t\tl = this.length,\n\t\t\tmatched = [],\n\t\t\ttargets = typeof selectors !== \"string\" && jQuery( selectors );\n\n\t\t// Positional selectors never match, since there's no _selection_ context\n\t\tif ( !rneedsContext.test( selectors ) ) {\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tfor ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {\n\n\t\t\t\t\t// Always skip document fragments\n\t\t\t\t\tif ( cur.nodeType < 11 && ( targets ?\n\t\t\t\t\t\ttargets.index( cur ) > -1 :\n\n\t\t\t\t\t\t// Don't pass non-elements to Sizzle\n\t\t\t\t\t\tcur.nodeType === 1 &&\n\t\t\t\t\t\t\tjQuery.find.matchesSelector( cur, selectors ) ) ) {\n\n\t\t\t\t\t\tmatched.push( cur );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );\n\t},\n\n\t// Determine the position of an element within the set\n\tindex: function( elem ) {\n\n\t\t// No argument, return index in parent\n\t\tif ( !elem ) {\n\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n\t\t}\n\n\t\t// Index in selector\n\t\tif ( typeof elem === \"string\" ) {\n\t\t\treturn indexOf.call( jQuery( elem ), this[ 0 ] );\n\t\t}\n\n\t\t// Locate the position of the desired element\n\t\treturn indexOf.call( this,\n\n\t\t\t// If it receives a jQuery object, the first element is used\n\t\t\telem.jquery ? elem[ 0 ] : elem\n\t\t);\n\t},\n\n\tadd: function( selector, context ) {\n\t\treturn this.pushStack(\n\t\t\tjQuery.uniqueSort(\n\t\t\t\tjQuery.merge( this.get(), jQuery( selector, context ) )\n\t\t\t)\n\t\t);\n\t},\n\n\taddBack: function( selector ) {\n\t\treturn this.add( selector == null ?\n\t\t\tthis.prevObject : this.prevObject.filter( selector )\n\t\t);\n\t}\n} );\n\nfunction sibling( cur, dir ) {\n\twhile ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}\n\treturn cur;\n}\n\njQuery.each( {\n\tparent: function( elem ) {\n\t\tvar parent = elem.parentNode;\n\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n\t},\n\tparents: function( elem ) {\n\t\treturn dir( elem, \"parentNode\" );\n\t},\n\tparentsUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"parentNode\", until );\n\t},\n\tnext: function( elem ) {\n\t\treturn sibling( elem, \"nextSibling\" );\n\t},\n\tprev: function( elem ) {\n\t\treturn sibling( elem, \"previousSibling\" );\n\t},\n\tnextAll: function( elem ) {\n\t\treturn dir( elem, \"nextSibling\" );\n\t},\n\tprevAll: function( elem ) {\n\t\treturn dir( elem, \"previousSibling\" );\n\t},\n\tnextUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"nextSibling\", until );\n\t},\n\tprevUntil: function( elem, i, until ) {\n\t\treturn dir( elem, \"previousSibling\", until );\n\t},\n\tsiblings: function( elem ) {\n\t\treturn siblings( ( elem.parentNode || {} ).firstChild, elem );\n\t},\n\tchildren: function( elem ) {\n\t\treturn siblings( elem.firstChild );\n\t},\n\tcontents: function( elem ) {\n\t\treturn elem.contentDocument || jQuery.merge( [], elem.childNodes );\n\t}\n}, function( name, fn ) {\n\tjQuery.fn[ name ] = function( until, selector ) {\n\t\tvar matched = jQuery.map( this, fn, until );\n\n\t\tif ( name.slice( -5 ) !== \"Until\" ) {\n\t\t\tselector = until;\n\t\t}\n\n\t\tif ( selector && typeof selector === \"string\" ) {\n\t\t\tmatched = jQuery.filter( selector, matched );\n\t\t}\n\n\t\tif ( this.length > 1 ) {\n\n\t\t\t// Remove duplicates\n\t\t\tif ( !guaranteedUnique[ name ] ) {\n\t\t\t\tjQuery.uniqueSort( matched );\n\t\t\t}\n\n\t\t\t// Reverse order for parents* and prev-derivatives\n\t\t\tif ( rparentsprev.test( name ) ) {\n\t\t\t\tmatched.reverse();\n\t\t\t}\n\t\t}\n\n\t\treturn this.pushStack( matched );\n\t};\n} );\nvar rnothtmlwhite = ( /[^\\x20\\t\\r\\n\\f]+/g );\n\n\n\n// Convert String-formatted options into Object-formatted ones\nfunction createOptions( options ) {\n\tvar object = {};\n\tjQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {\n\t\tobject[ flag ] = true;\n\t} );\n\treturn object;\n}\n\n/*\n * Create a callback list using the following parameters:\n *\n *\toptions: an optional list of space-separated options that will change how\n *\t\t\tthe callback list behaves or a more traditional option object\n *\n * By default a callback list will act like an event callback list and can be\n * \"fired\" multiple times.\n *\n * Possible options:\n *\n *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n *\n *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n *\t\t\t\t\tafter the list has been fired right away with the latest \"memorized\"\n *\t\t\t\t\tvalues (like a Deferred)\n *\n *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n *\n *\tstopOnFalse:\tinterrupt callings when a callback returns false\n *\n */\njQuery.Callbacks = function( options ) {\n\n\t// Convert options from String-formatted to Object-formatted if needed\n\t// (we check in cache first)\n\toptions = typeof options === \"string\" ?\n\t\tcreateOptions( options ) :\n\t\tjQuery.extend( {}, options );\n\n\tvar // Flag to know if list is currently firing\n\t\tfiring,\n\n\t\t// Last fire value for non-forgettable lists\n\t\tmemory,\n\n\t\t// Flag to know if list was already fired\n\t\tfired,\n\n\t\t// Flag to prevent firing\n\t\tlocked,\n\n\t\t// Actual callback list\n\t\tlist = [],\n\n\t\t// Queue of execution data for repeatable lists\n\t\tqueue = [],\n\n\t\t// Index of currently firing callback (modified by add/remove as needed)\n\t\tfiringIndex = -1,\n\n\t\t// Fire callbacks\n\t\tfire = function() {\n\n\t\t\t// Enforce single-firing\n\t\t\tlocked = options.once;\n\n\t\t\t// Execute callbacks for all pending executions,\n\t\t\t// respecting firingIndex overrides and runtime changes\n\t\t\tfired = firing = true;\n\t\t\tfor ( ; queue.length; firingIndex = -1 ) {\n\t\t\t\tmemory = queue.shift();\n\t\t\t\twhile ( ++firingIndex < list.length ) {\n\n\t\t\t\t\t// Run callback and check for early termination\n\t\t\t\t\tif ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&\n\t\t\t\t\t\toptions.stopOnFalse ) {\n\n\t\t\t\t\t\t// Jump to end and forget the data so .add doesn't re-fire\n\t\t\t\t\t\tfiringIndex = list.length;\n\t\t\t\t\t\tmemory = false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Forget the data if we're done with it\n\t\t\tif ( !options.memory ) {\n\t\t\t\tmemory = false;\n\t\t\t}\n\n\t\t\tfiring = false;\n\n\t\t\t// Clean up if we're done firing for good\n\t\t\tif ( locked ) {\n\n\t\t\t\t// Keep an empty list if we have data for future add calls\n\t\t\t\tif ( memory ) {\n\t\t\t\t\tlist = [];\n\n\t\t\t\t// Otherwise, this object is spent\n\t\t\t\t} else {\n\t\t\t\t\tlist = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// Actual Callbacks object\n\t\tself = {\n\n\t\t\t// Add a callback or a collection of callbacks to the list\n\t\t\tadd: function() {\n\t\t\t\tif ( list ) {\n\n\t\t\t\t\t// If we have memory from a past run, we should fire after adding\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfiringIndex = list.length - 1;\n\t\t\t\t\t\tqueue.push( memory );\n\t\t\t\t\t}\n\n\t\t\t\t\t( function add( args ) {\n\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n\t\t\t\t\t\t\tif ( jQuery.isFunction( arg ) ) {\n\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n\t\t\t\t\t\t\t\t\tlist.push( arg );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else if ( arg && arg.length && jQuery.type( arg ) !== \"string\" ) {\n\n\t\t\t\t\t\t\t\t// Inspect recursively\n\t\t\t\t\t\t\t\tadd( arg );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\t\t\t\t\t} )( arguments );\n\n\t\t\t\t\tif ( memory && !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Remove a callback from the list\n\t\t\tremove: function() {\n\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n\t\t\t\t\tvar index;\n\t\t\t\t\twhile ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n\t\t\t\t\t\tlist.splice( index, 1 );\n\n\t\t\t\t\t\t// Handle firing indexes\n\t\t\t\t\t\tif ( index <= firingIndex ) {\n\t\t\t\t\t\t\tfiringIndex--;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Check if a given callback is in the list.\n\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n\t\t\thas: function( fn ) {\n\t\t\t\treturn fn ?\n\t\t\t\t\tjQuery.inArray( fn, list ) > -1 :\n\t\t\t\t\tlist.length > 0;\n\t\t\t},\n\n\t\t\t// Remove all callbacks from the list\n\t\t\tempty: function() {\n\t\t\t\tif ( list ) {\n\t\t\t\t\tlist = [];\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Disable .fire and .add\n\t\t\t// Abort any current/pending executions\n\t\t\t// Clear all callbacks and values\n\t\t\tdisable: function() {\n\t\t\t\tlocked = queue = [];\n\t\t\t\tlist = memory = \"\";\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tdisabled: function() {\n\t\t\t\treturn !list;\n\t\t\t},\n\n\t\t\t// Disable .fire\n\t\t\t// Also disable .add unless we have memory (since it would have no effect)\n\t\t\t// Abort any pending executions\n\t\t\tlock: function() {\n\t\t\t\tlocked = queue = [];\n\t\t\t\tif ( !memory && !firing ) {\n\t\t\t\t\tlist = memory = \"\";\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\t\t\tlocked: function() {\n\t\t\t\treturn !!locked;\n\t\t\t},\n\n\t\t\t// Call all callbacks with the given context and arguments\n\t\t\tfireWith: function( context, args ) {\n\t\t\t\tif ( !locked ) {\n\t\t\t\t\targs = args || [];\n\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n\t\t\t\t\tqueue.push( args );\n\t\t\t\t\tif ( !firing ) {\n\t\t\t\t\t\tfire();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// Call all the callbacks with the given arguments\n\t\t\tfire: function() {\n\t\t\t\tself.fireWith( this, arguments );\n\t\t\t\treturn this;\n\t\t\t},\n\n\t\t\t// To know if the callbacks have already been called at least once\n\t\t\tfired: function() {\n\t\t\t\treturn !!fired;\n\t\t\t}\n\t\t};\n\n\treturn self;\n};\n\n\nfunction Identity( v ) {\n\treturn v;\n}\nfunction Thrower( ex ) {\n\tthrow ex;\n}\n\nfunction adoptValue( value, resolve, reject ) {\n\tvar method;\n\n\ttry {\n\n\t\t// Check for promise aspect first to privilege synchronous behavior\n\t\tif ( value && jQuery.isFunction( ( method = value.promise ) ) ) {\n\t\t\tmethod.call( value ).done( resolve ).fail( reject );\n\n\t\t// Other thenables\n\t\t} else if ( value && jQuery.isFunction( ( method = value.then ) ) ) {\n\t\t\tmethod.call( value, resolve, reject );\n\n\t\t// Other non-thenables\n\t\t} else {\n\n\t\t\t// Support: Android 4.0 only\n\t\t\t// Strict mode functions invoked without .call/.apply get global-object context\n\t\t\tresolve.call( undefined, value );\n\t\t}\n\n\t// For Promises/A+, convert exceptions into rejections\n\t// Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in\n\t// Deferred#then to conditionally suppress rejection.\n\t} catch ( value ) {\n\n\t\t// Support: Android 4.0 only\n\t\t// Strict mode functions invoked without .call/.apply get global-object context\n\t\treject.call( undefined, value );\n\t}\n}\n\njQuery.extend( {\n\n\tDeferred: function( func ) {\n\t\tvar tuples = [\n\n\t\t\t\t// action, add listener, callbacks,\n\t\t\t\t// ... .then handlers, argument index, [final state]\n\t\t\t\t[ \"notify\", \"progress\", jQuery.Callbacks( \"memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"memory\" ), 2 ],\n\t\t\t\t[ \"resolve\", \"done\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 0, \"resolved\" ],\n\t\t\t\t[ \"reject\", \"fail\", jQuery.Callbacks( \"once memory\" ),\n\t\t\t\t\tjQuery.Callbacks( \"once memory\" ), 1, \"rejected\" ]\n\t\t\t],\n\t\t\tstate = \"pending\",\n\t\t\tpromise = {\n\t\t\t\tstate: function() {\n\t\t\t\t\treturn state;\n\t\t\t\t},\n\t\t\t\talways: function() {\n\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\t\t\t\t\"catch\": function( fn ) {\n\t\t\t\t\treturn promise.then( null, fn );\n\t\t\t\t},\n\n\t\t\t\t// Keep pipe for back-compat\n\t\t\t\tpipe: function( /* fnDone, fnFail, fnProgress */ ) {\n\t\t\t\t\tvar fns = arguments;\n\n\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n\n\t\t\t\t\t\t\t// Map tuples (progress, done, fail) to arguments (done, fail, progress)\n\t\t\t\t\t\t\tvar fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];\n\n\t\t\t\t\t\t\t// deferred.progress(function() { bind to newDefer or newDefer.notify })\n\t\t\t\t\t\t\t// deferred.done(function() { bind to newDefer or newDefer.resolve })\n\t\t\t\t\t\t\t// deferred.fail(function() { bind to newDefer or newDefer.reject })\n\t\t\t\t\t\t\tdeferred[ tuple[ 1 ] ]( function() {\n\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n\t\t\t\t\t\t\t\t\treturned.promise()\n\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify )\n\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tnewDefer[ tuple[ 0 ] + \"With\" ](\n\t\t\t\t\t\t\t\t\t\tthis,\n\t\t\t\t\t\t\t\t\t\tfn ? [ returned ] : arguments\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t} );\n\t\t\t\t\t\tfns = null;\n\t\t\t\t\t} ).promise();\n\t\t\t\t},\n\t\t\t\tthen: function( onFulfilled, onRejected, onProgress ) {\n\t\t\t\t\tvar maxDepth = 0;\n\t\t\t\t\tfunction resolve( depth, deferred, handler, special ) {\n\t\t\t\t\t\treturn function() {\n\t\t\t\t\t\t\tvar that = this,\n\t\t\t\t\t\t\t\targs = arguments,\n\t\t\t\t\t\t\t\tmightThrow = function() {\n\t\t\t\t\t\t\t\t\tvar returned, then;\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.3\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-59\n\t\t\t\t\t\t\t\t\t// Ignore double-resolution attempts\n\t\t\t\t\t\t\t\t\tif ( depth < maxDepth ) {\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\treturned = handler.apply( that, args );\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.1\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-48\n\t\t\t\t\t\t\t\t\tif ( returned === deferred.promise() ) {\n\t\t\t\t\t\t\t\t\t\tthrow new TypeError( \"Thenable self-resolution\" );\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Support: Promises/A+ sections 2.3.3.1, 3.5\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-54\n\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-75\n\t\t\t\t\t\t\t\t\t// Retrieve `then` only once\n\t\t\t\t\t\t\t\t\tthen = returned &&\n\n\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.4\n\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-64\n\t\t\t\t\t\t\t\t\t\t// Only check objects and functions for thenability\n\t\t\t\t\t\t\t\t\t\t( typeof returned === \"object\" ||\n\t\t\t\t\t\t\t\t\t\t\ttypeof returned === \"function\" ) &&\n\t\t\t\t\t\t\t\t\t\treturned.then;\n\n\t\t\t\t\t\t\t\t\t// Handle a returned thenable\n\t\t\t\t\t\t\t\t\tif ( jQuery.isFunction( then ) ) {\n\n\t\t\t\t\t\t\t\t\t\t// Special processors (notify) just wait for resolution\n\t\t\t\t\t\t\t\t\t\tif ( special ) {\n\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special )\n\t\t\t\t\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t\t\t\t// Normal processors (resolve) also hook into progress\n\t\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t\t// ...and disregard older resolution values\n\t\t\t\t\t\t\t\t\t\t\tmaxDepth++;\n\n\t\t\t\t\t\t\t\t\t\t\tthen.call(\n\t\t\t\t\t\t\t\t\t\t\t\treturned,\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Thrower, special ),\n\t\t\t\t\t\t\t\t\t\t\t\tresolve( maxDepth, deferred, Identity,\n\t\t\t\t\t\t\t\t\t\t\t\t\tdeferred.notifyWith )\n\t\t\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Handle all other returned values\n\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\tif ( handler !== Identity ) {\n\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\targs = [ returned ];\n\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t// Process the value(s)\n\t\t\t\t\t\t\t\t\t\t// Default process is resolve\n\t\t\t\t\t\t\t\t\t\t( special || deferred.resolveWith )( that, args );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t// Only normal processors (resolve) catch and reject exceptions\n\t\t\t\t\t\t\t\tprocess = special ?\n\t\t\t\t\t\t\t\t\tmightThrow :\n\t\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\t\t\t\tmightThrow();\n\t\t\t\t\t\t\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t\t\t\t\t\t\tif ( jQuery.Deferred.exceptionHook ) {\n\t\t\t\t\t\t\t\t\t\t\t\tjQuery.Deferred.exceptionHook( e,\n\t\t\t\t\t\t\t\t\t\t\t\t\tprocess.stackTrace );\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.4.1\n\t\t\t\t\t\t\t\t\t\t\t// https://promisesaplus.com/#point-61\n\t\t\t\t\t\t\t\t\t\t\t// Ignore post-resolution exceptions\n\t\t\t\t\t\t\t\t\t\t\tif ( depth + 1 >= maxDepth ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Only substitute handlers pass on context\n\t\t\t\t\t\t\t\t\t\t\t\t// and multiple values (non-spec behavior)\n\t\t\t\t\t\t\t\t\t\t\t\tif ( handler !== Thrower ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tthat = undefined;\n\t\t\t\t\t\t\t\t\t\t\t\t\targs = [ e ];\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\tdeferred.rejectWith( that, args );\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t// Support: Promises/A+ section 2.3.3.3.1\n\t\t\t\t\t\t\t// https://promisesaplus.com/#point-57\n\t\t\t\t\t\t\t// Re-resolve promises immediately to dodge false rejection from\n\t\t\t\t\t\t\t// subsequent errors\n\t\t\t\t\t\t\tif ( depth ) {\n\t\t\t\t\t\t\t\tprocess();\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t// Call an optional hook to record the stack, in case of exception\n\t\t\t\t\t\t\t\t// since it's otherwise lost when execution goes async\n\t\t\t\t\t\t\t\tif ( jQuery.Deferred.getStackHook ) {\n\t\t\t\t\t\t\t\t\tprocess.stackTrace = jQuery.Deferred.getStackHook();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\twindow.setTimeout( process );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\n\t\t\t\t\treturn jQuery.Deferred( function( newDefer ) {\n\n\t\t\t\t\t\t// progress_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 0 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tjQuery.isFunction( onProgress ) ?\n\t\t\t\t\t\t\t\t\tonProgress :\n\t\t\t\t\t\t\t\t\tIdentity,\n\t\t\t\t\t\t\t\tnewDefer.notifyWith\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// fulfilled_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 1 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tjQuery.isFunction( onFulfilled ) ?\n\t\t\t\t\t\t\t\t\tonFulfilled :\n\t\t\t\t\t\t\t\t\tIdentity\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\t// rejected_handlers.add( ... )\n\t\t\t\t\t\ttuples[ 2 ][ 3 ].add(\n\t\t\t\t\t\t\tresolve(\n\t\t\t\t\t\t\t\t0,\n\t\t\t\t\t\t\t\tnewDefer,\n\t\t\t\t\t\t\t\tjQuery.isFunction( onRejected ) ?\n\t\t\t\t\t\t\t\t\tonRejected :\n\t\t\t\t\t\t\t\t\tThrower\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t);\n\t\t\t\t\t} ).promise();\n\t\t\t\t},\n\n\t\t\t\t// Get a promise for this deferred\n\t\t\t\t// If obj is provided, the promise aspect is added to the object\n\t\t\t\tpromise: function( obj ) {\n\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdeferred = {};\n\n\t\t// Add list-specific methods\n\t\tjQuery.each( tuples, function( i, tuple ) {\n\t\t\tvar list = tuple[ 2 ],\n\t\t\t\tstateString = tuple[ 5 ];\n\n\t\t\t// promise.progress = list.add\n\t\t\t// promise.done = list.add\n\t\t\t// promise.fail = list.add\n\t\t\tpromise[ tuple[ 1 ] ] = list.add;\n\n\t\t\t// Handle state\n\t\t\tif ( stateString ) {\n\t\t\t\tlist.add(\n\t\t\t\t\tfunction() {\n\n\t\t\t\t\t\t// state = \"resolved\" (i.e., fulfilled)\n\t\t\t\t\t\t// state = \"rejected\"\n\t\t\t\t\t\tstate = stateString;\n\t\t\t\t\t},\n\n\t\t\t\t\t// rejected_callbacks.disable\n\t\t\t\t\t// fulfilled_callbacks.disable\n\t\t\t\t\ttuples[ 3 - i ][ 2 ].disable,\n\n\t\t\t\t\t// progress_callbacks.lock\n\t\t\t\t\ttuples[ 0 ][ 2 ].lock\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// progress_handlers.fire\n\t\t\t// fulfilled_handlers.fire\n\t\t\t// rejected_handlers.fire\n\t\t\tlist.add( tuple[ 3 ].fire );\n\n\t\t\t// deferred.notify = function() { deferred.notifyWith(...) }\n\t\t\t// deferred.resolve = function() { deferred.resolveWith(...) }\n\t\t\t// deferred.reject = function() { deferred.rejectWith(...) }\n\t\t\tdeferred[ tuple[ 0 ] ] = function() {\n\t\t\t\tdeferred[ tuple[ 0 ] + \"With\" ]( this === deferred ? undefined : this, arguments );\n\t\t\t\treturn this;\n\t\t\t};\n\n\t\t\t// deferred.notifyWith = list.fireWith\n\t\t\t// deferred.resolveWith = list.fireWith\n\t\t\t// deferred.rejectWith = list.fireWith\n\t\t\tdeferred[ tuple[ 0 ] + \"With\" ] = list.fireWith;\n\t\t} );\n\n\t\t// Make the deferred a promise\n\t\tpromise.promise( deferred );\n\n\t\t// Call given func if any\n\t\tif ( func ) {\n\t\t\tfunc.call( deferred, deferred );\n\t\t}\n\n\t\t// All done!\n\t\treturn deferred;\n\t},\n\n\t// Deferred helper\n\twhen: function( singleValue ) {\n\t\tvar\n\n\t\t\t// count of uncompleted subordinates\n\t\t\tremaining = arguments.length,\n\n\t\t\t// count of unprocessed arguments\n\t\t\ti = remaining,\n\n\t\t\t// subordinate fulfillment data\n\t\t\tresolveContexts = Array( i ),\n\t\t\tresolveValues = slice.call( arguments ),\n\n\t\t\t// the master Deferred\n\t\t\tmaster = jQuery.Deferred(),\n\n\t\t\t// subordinate callback factory\n\t\t\tupdateFunc = function( i ) {\n\t\t\t\treturn function( value ) {\n\t\t\t\t\tresolveContexts[ i ] = this;\n\t\t\t\t\tresolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;\n\t\t\t\t\tif ( !( --remaining ) ) {\n\t\t\t\t\t\tmaster.resolveWith( resolveContexts, resolveValues );\n\t\t\t\t\t}\n\t\t\t\t};\n\t\t\t};\n\n\t\t// Single- and empty arguments are adopted like Promise.resolve\n\t\tif ( remaining <= 1 ) {\n\t\t\tadoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject );\n\n\t\t\t// Use .then() to unwrap secondary thenables (cf. gh-3000)\n\t\t\tif ( master.state() === \"pending\" ||\n\t\t\t\tjQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {\n\n\t\t\t\treturn master.then();\n\t\t\t}\n\t\t}\n\n\t\t// Multiple arguments are aggregated like Promise.all array elements\n\t\twhile ( i-- ) {\n\t\t\tadoptValue( resolveValues[ i ], updateFunc( i ), master.reject );\n\t\t}\n\n\t\treturn master.promise();\n\t}\n} );\n\n\n// These usually indicate a programmer mistake during development,\n// warn about them ASAP rather than swallowing them by default.\nvar rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;\n\njQuery.Deferred.exceptionHook = function( error, stack ) {\n\n\t// Support: IE 8 - 9 only\n\t// Console exists when dev tools are open, which can happen at any time\n\tif ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {\n\t\twindow.console.warn( \"jQuery.Deferred exception: \" + error.message, error.stack, stack );\n\t}\n};\n\n\n\n\njQuery.readyException = function( error ) {\n\twindow.setTimeout( function() {\n\t\tthrow error;\n\t} );\n};\n\n\n\n\n// The deferred used on DOM ready\nvar readyList = jQuery.Deferred();\n\njQuery.fn.ready = function( fn ) {\n\n\treadyList\n\t\t.then( fn )\n\n\t\t// Wrap jQuery.readyException in a function so that the lookup\n\t\t// happens at the time of error handling instead of callback\n\t\t// registration.\n\t\t.catch( function( error ) {\n\t\t\tjQuery.readyException( error );\n\t\t} );\n\n\treturn this;\n};\n\njQuery.extend( {\n\n\t// Is the DOM ready to be used? Set to true once it occurs.\n\tisReady: false,\n\n\t// A counter to track how many items to wait for before\n\t// the ready event fires. See #6781\n\treadyWait: 1,\n\n\t// Hold (or release) the ready event\n\tholdReady: function( hold ) {\n\t\tif ( hold ) {\n\t\t\tjQuery.readyWait++;\n\t\t} else {\n\t\t\tjQuery.ready( true );\n\t\t}\n\t},\n\n\t// Handle when the DOM is ready\n\tready: function( wait ) {\n\n\t\t// Abort if there are pending holds or we're already ready\n\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Remember that the DOM is ready\n\t\tjQuery.isReady = true;\n\n\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If there are functions bound, to execute\n\t\treadyList.resolveWith( document, [ jQuery ] );\n\t}\n} );\n\njQuery.ready.then = readyList.then;\n\n// The ready event handler and self cleanup method\nfunction completed() {\n\tdocument.removeEventListener( \"DOMContentLoaded\", completed );\n\twindow.removeEventListener( \"load\", completed );\n\tjQuery.ready();\n}\n\n// Catch cases where $(document).ready() is called\n// after the browser event has already occurred.\n// Support: IE <=9 - 10 only\n// Older IE sometimes signals \"interactive\" too soon\nif ( document.readyState === \"complete\" ||\n\t( document.readyState !== \"loading\" && !document.documentElement.doScroll ) ) {\n\n\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n\twindow.setTimeout( jQuery.ready );\n\n} else {\n\n\t// Use the handy event callback\n\tdocument.addEventListener( \"DOMContentLoaded\", completed );\n\n\t// A fallback to window.onload, that will always work\n\twindow.addEventListener( \"load\", completed );\n}\n\n\n\n\n// Multifunctional method to get and set values of a collection\n// The value/s can optionally be executed if it's a function\nvar access = function( elems, fn, key, value, chainable, emptyGet, raw ) {\n\tvar i = 0,\n\t\tlen = elems.length,\n\t\tbulk = key == null;\n\n\t// Sets many values\n\tif ( jQuery.type( key ) === \"object\" ) {\n\t\tchainable = true;\n\t\tfor ( i in key ) {\n\t\t\taccess( elems, fn, i, key[ i ], true, emptyGet, raw );\n\t\t}\n\n\t// Sets one value\n\t} else if ( value !== undefined ) {\n\t\tchainable = true;\n\n\t\tif ( !jQuery.isFunction( value ) ) {\n\t\t\traw = true;\n\t\t}\n\n\t\tif ( bulk ) {\n\n\t\t\t// Bulk operations run against the entire set\n\t\t\tif ( raw ) {\n\t\t\t\tfn.call( elems, value );\n\t\t\t\tfn = null;\n\n\t\t\t// ...except when executing function values\n\t\t\t} else {\n\t\t\t\tbulk = fn;\n\t\t\t\tfn = function( elem, key, value ) {\n\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( fn ) {\n\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\tfn(\n\t\t\t\t\telems[ i ], key, raw ?\n\t\t\t\t\tvalue :\n\t\t\t\t\tvalue.call( elems[ i ], i, fn( elems[ i ], key ) )\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( chainable ) {\n\t\treturn elems;\n\t}\n\n\t// Gets\n\tif ( bulk ) {\n\t\treturn fn.call( elems );\n\t}\n\n\treturn len ? fn( elems[ 0 ], key ) : emptyGet;\n};\nvar acceptData = function( owner ) {\n\n\t// Accepts only:\n\t//  - Node\n\t//    - Node.ELEMENT_NODE\n\t//    - Node.DOCUMENT_NODE\n\t//  - Object\n\t//    - Any\n\treturn owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );\n};\n\n\n\n\nfunction Data() {\n\tthis.expando = jQuery.expando + Data.uid++;\n}\n\nData.uid = 1;\n\nData.prototype = {\n\n\tcache: function( owner ) {\n\n\t\t// Check if the owner object already has a cache\n\t\tvar value = owner[ this.expando ];\n\n\t\t// If not, create one\n\t\tif ( !value ) {\n\t\t\tvalue = {};\n\n\t\t\t// We can accept data for non-element nodes in modern browsers,\n\t\t\t// but we should not, see #8335.\n\t\t\t// Always return an empty object.\n\t\t\tif ( acceptData( owner ) ) {\n\n\t\t\t\t// If it is a node unlikely to be stringify-ed or looped over\n\t\t\t\t// use plain assignment\n\t\t\t\tif ( owner.nodeType ) {\n\t\t\t\t\towner[ this.expando ] = value;\n\n\t\t\t\t// Otherwise secure it in a non-enumerable property\n\t\t\t\t// configurable must be true to allow the property to be\n\t\t\t\t// deleted when data is removed\n\t\t\t\t} else {\n\t\t\t\t\tObject.defineProperty( owner, this.expando, {\n\t\t\t\t\t\tvalue: value,\n\t\t\t\t\t\tconfigurable: true\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn value;\n\t},\n\tset: function( owner, data, value ) {\n\t\tvar prop,\n\t\t\tcache = this.cache( owner );\n\n\t\t// Handle: [ owner, key, value ] args\n\t\t// Always use camelCase key (gh-2257)\n\t\tif ( typeof data === \"string\" ) {\n\t\t\tcache[ jQuery.camelCase( data ) ] = value;\n\n\t\t// Handle: [ owner, { properties } ] args\n\t\t} else {\n\n\t\t\t// Copy the properties one-by-one to the cache object\n\t\t\tfor ( prop in data ) {\n\t\t\t\tcache[ jQuery.camelCase( prop ) ] = data[ prop ];\n\t\t\t}\n\t\t}\n\t\treturn cache;\n\t},\n\tget: function( owner, key ) {\n\t\treturn key === undefined ?\n\t\t\tthis.cache( owner ) :\n\n\t\t\t// Always use camelCase key (gh-2257)\n\t\t\towner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];\n\t},\n\taccess: function( owner, key, value ) {\n\n\t\t// In cases where either:\n\t\t//\n\t\t//   1. No key was specified\n\t\t//   2. A string key was specified, but no value provided\n\t\t//\n\t\t// Take the \"read\" path and allow the get method to determine\n\t\t// which value to return, respectively either:\n\t\t//\n\t\t//   1. The entire cache object\n\t\t//   2. The data stored at the key\n\t\t//\n\t\tif ( key === undefined ||\n\t\t\t\t( ( key && typeof key === \"string\" ) && value === undefined ) ) {\n\n\t\t\treturn this.get( owner, key );\n\t\t}\n\n\t\t// When the key is not a string, or both a key and value\n\t\t// are specified, set or extend (existing objects) with either:\n\t\t//\n\t\t//   1. An object of properties\n\t\t//   2. A key and value\n\t\t//\n\t\tthis.set( owner, key, value );\n\n\t\t// Since the \"set\" path can have two possible entry points\n\t\t// return the expected data based on which path was taken[*]\n\t\treturn value !== undefined ? value : key;\n\t},\n\tremove: function( owner, key ) {\n\t\tvar i,\n\t\t\tcache = owner[ this.expando ];\n\n\t\tif ( cache === undefined ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( key !== undefined ) {\n\n\t\t\t// Support array or space separated string of keys\n\t\t\tif ( jQuery.isArray( key ) ) {\n\n\t\t\t\t// If key is an array of keys...\n\t\t\t\t// We always set camelCase keys, so remove that.\n\t\t\t\tkey = key.map( jQuery.camelCase );\n\t\t\t} else {\n\t\t\t\tkey = jQuery.camelCase( key );\n\n\t\t\t\t// If a key with the spaces exists, use it.\n\t\t\t\t// Otherwise, create an array by matching non-whitespace\n\t\t\t\tkey = key in cache ?\n\t\t\t\t\t[ key ] :\n\t\t\t\t\t( key.match( rnothtmlwhite ) || [] );\n\t\t\t}\n\n\t\t\ti = key.length;\n\n\t\t\twhile ( i-- ) {\n\t\t\t\tdelete cache[ key[ i ] ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove the expando if there's no more data\n\t\tif ( key === undefined || jQuery.isEmptyObject( cache ) ) {\n\n\t\t\t// Support: Chrome <=35 - 45\n\t\t\t// Webkit & Blink performance suffers when deleting properties\n\t\t\t// from DOM nodes, so set to undefined instead\n\t\t\t// https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)\n\t\t\tif ( owner.nodeType ) {\n\t\t\t\towner[ this.expando ] = undefined;\n\t\t\t} else {\n\t\t\t\tdelete owner[ this.expando ];\n\t\t\t}\n\t\t}\n\t},\n\thasData: function( owner ) {\n\t\tvar cache = owner[ this.expando ];\n\t\treturn cache !== undefined && !jQuery.isEmptyObject( cache );\n\t}\n};\nvar dataPriv = new Data();\n\nvar dataUser = new Data();\n\n\n\n//\tImplementation Summary\n//\n//\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n//\t2. Improve the module's maintainability by reducing the storage\n//\t\tpaths to a single mechanism.\n//\t3. Use the same single mechanism to support \"private\" and \"user\" data.\n//\t4. _Never_ expose \"private\" data to user code (TODO: Drop _data, _removeData)\n//\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n//\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n\nvar rbrace = /^(?:\\{[\\w\\W]*\\}|\\[[\\w\\W]*\\])$/,\n\trmultiDash = /[A-Z]/g;\n\nfunction getData( data ) {\n\tif ( data === \"true\" ) {\n\t\treturn true;\n\t}\n\n\tif ( data === \"false\" ) {\n\t\treturn false;\n\t}\n\n\tif ( data === \"null\" ) {\n\t\treturn null;\n\t}\n\n\t// Only convert to a number if it doesn't change the string\n\tif ( data === +data + \"\" ) {\n\t\treturn +data;\n\t}\n\n\tif ( rbrace.test( data ) ) {\n\t\treturn JSON.parse( data );\n\t}\n\n\treturn data;\n}\n\nfunction dataAttr( elem, key, data ) {\n\tvar name;\n\n\t// If nothing was found internally, try to fetch any\n\t// data from the HTML5 data-* attribute\n\tif ( data === undefined && elem.nodeType === 1 ) {\n\t\tname = \"data-\" + key.replace( rmultiDash, \"-$&\" ).toLowerCase();\n\t\tdata = elem.getAttribute( name );\n\n\t\tif ( typeof data === \"string\" ) {\n\t\t\ttry {\n\t\t\t\tdata = getData( data );\n\t\t\t} catch ( e ) {}\n\n\t\t\t// Make sure we set the data so it isn't changed later\n\t\t\tdataUser.set( elem, key, data );\n\t\t} else {\n\t\t\tdata = undefined;\n\t\t}\n\t}\n\treturn data;\n}\n\njQuery.extend( {\n\thasData: function( elem ) {\n\t\treturn dataUser.hasData( elem ) || dataPriv.hasData( elem );\n\t},\n\n\tdata: function( elem, name, data ) {\n\t\treturn dataUser.access( elem, name, data );\n\t},\n\n\tremoveData: function( elem, name ) {\n\t\tdataUser.remove( elem, name );\n\t},\n\n\t// TODO: Now that all calls to _data and _removeData have been replaced\n\t// with direct calls to dataPriv methods, these can be deprecated.\n\t_data: function( elem, name, data ) {\n\t\treturn dataPriv.access( elem, name, data );\n\t},\n\n\t_removeData: function( elem, name ) {\n\t\tdataPriv.remove( elem, name );\n\t}\n} );\n\njQuery.fn.extend( {\n\tdata: function( key, value ) {\n\t\tvar i, name, data,\n\t\t\telem = this[ 0 ],\n\t\t\tattrs = elem && elem.attributes;\n\n\t\t// Gets all values\n\t\tif ( key === undefined ) {\n\t\t\tif ( this.length ) {\n\t\t\t\tdata = dataUser.get( elem );\n\n\t\t\t\tif ( elem.nodeType === 1 && !dataPriv.get( elem, \"hasDataAttrs\" ) ) {\n\t\t\t\t\ti = attrs.length;\n\t\t\t\t\twhile ( i-- ) {\n\n\t\t\t\t\t\t// Support: IE 11 only\n\t\t\t\t\t\t// The attrs elements can be null (#14894)\n\t\t\t\t\t\tif ( attrs[ i ] ) {\n\t\t\t\t\t\t\tname = attrs[ i ].name;\n\t\t\t\t\t\t\tif ( name.indexOf( \"data-\" ) === 0 ) {\n\t\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice( 5 ) );\n\t\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tdataPriv.set( elem, \"hasDataAttrs\", true );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn data;\n\t\t}\n\n\t\t// Sets multiple values\n\t\tif ( typeof key === \"object\" ) {\n\t\t\treturn this.each( function() {\n\t\t\t\tdataUser.set( this, key );\n\t\t\t} );\n\t\t}\n\n\t\treturn access( this, function( value ) {\n\t\t\tvar data;\n\n\t\t\t// The calling jQuery object (element matches) is not empty\n\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n\t\t\t// `value` parameter was not undefined. An empty jQuery object\n\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n\t\t\t// throw an exception if an attempt to read a data cache is made.\n\t\t\tif ( elem && value === undefined ) {\n\n\t\t\t\t// Attempt to get data from the cache\n\t\t\t\t// The key will always be camelCased in Data\n\t\t\t\tdata = dataUser.get( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// Attempt to \"discover\" the data in\n\t\t\t\t// HTML5 custom data-* attrs\n\t\t\t\tdata = dataAttr( elem, key );\n\t\t\t\tif ( data !== undefined ) {\n\t\t\t\t\treturn data;\n\t\t\t\t}\n\n\t\t\t\t// We tried really hard, but the data doesn't exist.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Set the data...\n\t\t\tthis.each( function() {\n\n\t\t\t\t// We always store the camelCased key\n\t\t\t\tdataUser.set( this, key, value );\n\t\t\t} );\n\t\t}, null, value, arguments.length > 1, null, true );\n\t},\n\n\tremoveData: function( key ) {\n\t\treturn this.each( function() {\n\t\t\tdataUser.remove( this, key );\n\t\t} );\n\t}\n} );\n\n\njQuery.extend( {\n\tqueue: function( elem, type, data ) {\n\t\tvar queue;\n\n\t\tif ( elem ) {\n\t\t\ttype = ( type || \"fx\" ) + \"queue\";\n\t\t\tqueue = dataPriv.get( elem, type );\n\n\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n\t\t\tif ( data ) {\n\t\t\t\tif ( !queue || jQuery.isArray( data ) ) {\n\t\t\t\t\tqueue = dataPriv.access( elem, type, jQuery.makeArray( data ) );\n\t\t\t\t} else {\n\t\t\t\t\tqueue.push( data );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn queue || [];\n\t\t}\n\t},\n\n\tdequeue: function( elem, type ) {\n\t\ttype = type || \"fx\";\n\n\t\tvar queue = jQuery.queue( elem, type ),\n\t\t\tstartLength = queue.length,\n\t\t\tfn = queue.shift(),\n\t\t\thooks = jQuery._queueHooks( elem, type ),\n\t\t\tnext = function() {\n\t\t\t\tjQuery.dequeue( elem, type );\n\t\t\t};\n\n\t\t// If the fx queue is dequeued, always remove the progress sentinel\n\t\tif ( fn === \"inprogress\" ) {\n\t\t\tfn = queue.shift();\n\t\t\tstartLength--;\n\t\t}\n\n\t\tif ( fn ) {\n\n\t\t\t// Add a progress sentinel to prevent the fx queue from being\n\t\t\t// automatically dequeued\n\t\t\tif ( type === \"fx\" ) {\n\t\t\t\tqueue.unshift( \"inprogress\" );\n\t\t\t}\n\n\t\t\t// Clear up the last queue stop function\n\t\t\tdelete hooks.stop;\n\t\t\tfn.call( elem, next, hooks );\n\t\t}\n\n\t\tif ( !startLength && hooks ) {\n\t\t\thooks.empty.fire();\n\t\t}\n\t},\n\n\t// Not public - generate a queueHooks object, or return the current one\n\t_queueHooks: function( elem, type ) {\n\t\tvar key = type + \"queueHooks\";\n\t\treturn dataPriv.get( elem, key ) || dataPriv.access( elem, key, {\n\t\t\tempty: jQuery.Callbacks( \"once memory\" ).add( function() {\n\t\t\t\tdataPriv.remove( elem, [ type + \"queue\", key ] );\n\t\t\t} )\n\t\t} );\n\t}\n} );\n\njQuery.fn.extend( {\n\tqueue: function( type, data ) {\n\t\tvar setter = 2;\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tdata = type;\n\t\t\ttype = \"fx\";\n\t\t\tsetter--;\n\t\t}\n\n\t\tif ( arguments.length < setter ) {\n\t\t\treturn jQuery.queue( this[ 0 ], type );\n\t\t}\n\n\t\treturn data === undefined ?\n\t\t\tthis :\n\t\t\tthis.each( function() {\n\t\t\t\tvar queue = jQuery.queue( this, type, data );\n\n\t\t\t\t// Ensure a hooks for this queue\n\t\t\t\tjQuery._queueHooks( this, type );\n\n\t\t\t\tif ( type === \"fx\" && queue[ 0 ] !== \"inprogress\" ) {\n\t\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t\t}\n\t\t\t} );\n\t},\n\tdequeue: function( type ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.dequeue( this, type );\n\t\t} );\n\t},\n\tclearQueue: function( type ) {\n\t\treturn this.queue( type || \"fx\", [] );\n\t},\n\n\t// Get a promise resolved when queues of a certain type\n\t// are emptied (fx is the type by default)\n\tpromise: function( type, obj ) {\n\t\tvar tmp,\n\t\t\tcount = 1,\n\t\t\tdefer = jQuery.Deferred(),\n\t\t\telements = this,\n\t\t\ti = this.length,\n\t\t\tresolve = function() {\n\t\t\t\tif ( !( --count ) ) {\n\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n\t\t\t\t}\n\t\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tobj = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\ttype = type || \"fx\";\n\n\t\twhile ( i-- ) {\n\t\t\ttmp = dataPriv.get( elements[ i ], type + \"queueHooks\" );\n\t\t\tif ( tmp && tmp.empty ) {\n\t\t\t\tcount++;\n\t\t\t\ttmp.empty.add( resolve );\n\t\t\t}\n\t\t}\n\t\tresolve();\n\t\treturn defer.promise( obj );\n\t}\n} );\nvar pnum = ( /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/ ).source;\n\nvar rcssNum = new RegExp( \"^(?:([+-])=|)(\" + pnum + \")([a-z%]*)$\", \"i\" );\n\n\nvar cssExpand = [ \"Top\", \"Right\", \"Bottom\", \"Left\" ];\n\nvar isHiddenWithinTree = function( elem, el ) {\n\n\t\t// isHiddenWithinTree might be called from jQuery#filter function;\n\t\t// in that case, element will be second argument\n\t\telem = el || elem;\n\n\t\t// Inline style trumps all\n\t\treturn elem.style.display === \"none\" ||\n\t\t\telem.style.display === \"\" &&\n\n\t\t\t// Otherwise, check computed style\n\t\t\t// Support: Firefox <=43 - 45\n\t\t\t// Disconnected elements can have computed display: none, so first confirm that elem is\n\t\t\t// in the document.\n\t\t\tjQuery.contains( elem.ownerDocument, elem ) &&\n\n\t\t\tjQuery.css( elem, \"display\" ) === \"none\";\n\t};\n\nvar swap = function( elem, options, callback, args ) {\n\tvar ret, name,\n\t\told = {};\n\n\t// Remember the old values, and insert the new ones\n\tfor ( name in options ) {\n\t\told[ name ] = elem.style[ name ];\n\t\telem.style[ name ] = options[ name ];\n\t}\n\n\tret = callback.apply( elem, args || [] );\n\n\t// Revert the old values\n\tfor ( name in options ) {\n\t\telem.style[ name ] = old[ name ];\n\t}\n\n\treturn ret;\n};\n\n\n\n\nfunction adjustCSS( elem, prop, valueParts, tween ) {\n\tvar adjusted,\n\t\tscale = 1,\n\t\tmaxIterations = 20,\n\t\tcurrentValue = tween ?\n\t\t\tfunction() {\n\t\t\t\treturn tween.cur();\n\t\t\t} :\n\t\t\tfunction() {\n\t\t\t\treturn jQuery.css( elem, prop, \"\" );\n\t\t\t},\n\t\tinitial = currentValue(),\n\t\tunit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" ),\n\n\t\t// Starting value computation is required for potential unit mismatches\n\t\tinitialInUnit = ( jQuery.cssNumber[ prop ] || unit !== \"px\" && +initial ) &&\n\t\t\trcssNum.exec( jQuery.css( elem, prop ) );\n\n\tif ( initialInUnit && initialInUnit[ 3 ] !== unit ) {\n\n\t\t// Trust units reported by jQuery.css\n\t\tunit = unit || initialInUnit[ 3 ];\n\n\t\t// Make sure we update the tween properties later on\n\t\tvalueParts = valueParts || [];\n\n\t\t// Iteratively approximate from a nonzero starting point\n\t\tinitialInUnit = +initial || 1;\n\n\t\tdo {\n\n\t\t\t// If previous iteration zeroed out, double until we get *something*.\n\t\t\t// Use string for doubling so we don't accidentally see scale as unchanged below\n\t\t\tscale = scale || \".5\";\n\n\t\t\t// Adjust and apply\n\t\t\tinitialInUnit = initialInUnit / scale;\n\t\t\tjQuery.style( elem, prop, initialInUnit + unit );\n\n\t\t// Update scale, tolerating zero or NaN from tween.cur()\n\t\t// Break the loop if scale is unchanged or perfect, or if we've just had enough.\n\t\t} while (\n\t\t\tscale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations\n\t\t);\n\t}\n\n\tif ( valueParts ) {\n\t\tinitialInUnit = +initialInUnit || +initial || 0;\n\n\t\t// Apply relative offset (+=/-=) if specified\n\t\tadjusted = valueParts[ 1 ] ?\n\t\t\tinitialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :\n\t\t\t+valueParts[ 2 ];\n\t\tif ( tween ) {\n\t\t\ttween.unit = unit;\n\t\t\ttween.start = initialInUnit;\n\t\t\ttween.end = adjusted;\n\t\t}\n\t}\n\treturn adjusted;\n}\n\n\nvar defaultDisplayMap = {};\n\nfunction getDefaultDisplay( elem ) {\n\tvar temp,\n\t\tdoc = elem.ownerDocument,\n\t\tnodeName = elem.nodeName,\n\t\tdisplay = defaultDisplayMap[ nodeName ];\n\n\tif ( display ) {\n\t\treturn display;\n\t}\n\n\ttemp = doc.body.appendChild( doc.createElement( nodeName ) );\n\tdisplay = jQuery.css( temp, \"display\" );\n\n\ttemp.parentNode.removeChild( temp );\n\n\tif ( display === \"none\" ) {\n\t\tdisplay = \"block\";\n\t}\n\tdefaultDisplayMap[ nodeName ] = display;\n\n\treturn display;\n}\n\nfunction showHide( elements, show ) {\n\tvar display, elem,\n\t\tvalues = [],\n\t\tindex = 0,\n\t\tlength = elements.length;\n\n\t// Determine new display value for elements that need to change\n\tfor ( ; index < length; index++ ) {\n\t\telem = elements[ index ];\n\t\tif ( !elem.style ) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tdisplay = elem.style.display;\n\t\tif ( show ) {\n\n\t\t\t// Since we force visibility upon cascade-hidden elements, an immediate (and slow)\n\t\t\t// check is required in this first loop unless we have a nonempty display value (either\n\t\t\t// inline or about-to-be-restored)\n\t\t\tif ( display === \"none\" ) {\n\t\t\t\tvalues[ index ] = dataPriv.get( elem, \"display\" ) || null;\n\t\t\t\tif ( !values[ index ] ) {\n\t\t\t\t\telem.style.display = \"\";\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( elem.style.display === \"\" && isHiddenWithinTree( elem ) ) {\n\t\t\t\tvalues[ index ] = getDefaultDisplay( elem );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( display !== \"none\" ) {\n\t\t\t\tvalues[ index ] = \"none\";\n\n\t\t\t\t// Remember what we're overwriting\n\t\t\t\tdataPriv.set( elem, \"display\", display );\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set the display of the elements in a second loop to avoid constant reflow\n\tfor ( index = 0; index < length; index++ ) {\n\t\tif ( values[ index ] != null ) {\n\t\t\telements[ index ].style.display = values[ index ];\n\t\t}\n\t}\n\n\treturn elements;\n}\n\njQuery.fn.extend( {\n\tshow: function() {\n\t\treturn showHide( this, true );\n\t},\n\thide: function() {\n\t\treturn showHide( this );\n\t},\n\ttoggle: function( state ) {\n\t\tif ( typeof state === \"boolean\" ) {\n\t\t\treturn state ? this.show() : this.hide();\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tif ( isHiddenWithinTree( this ) ) {\n\t\t\t\tjQuery( this ).show();\n\t\t\t} else {\n\t\t\t\tjQuery( this ).hide();\n\t\t\t}\n\t\t} );\n\t}\n} );\nvar rcheckableType = ( /^(?:checkbox|radio)$/i );\n\nvar rtagName = ( /<([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]+)/i );\n\nvar rscriptType = ( /^$|\\/(?:java|ecma)script/i );\n\n\n\n// We have to close these tags to support XHTML (#13200)\nvar wrapMap = {\n\n\t// Support: IE <=9 only\n\toption: [ 1, \"<select multiple='multiple'>\", \"</select>\" ],\n\n\t// XHTML parsers do not magically insert elements in the\n\t// same way that tag soup parsers do. So we cannot shorten\n\t// this by omitting <tbody> or other required elements.\n\tthead: [ 1, \"<table>\", \"</table>\" ],\n\tcol: [ 2, \"<table><colgroup>\", \"</colgroup></table>\" ],\n\ttr: [ 2, \"<table><tbody>\", \"</tbody></table>\" ],\n\ttd: [ 3, \"<table><tbody><tr>\", \"</tr></tbody></table>\" ],\n\n\t_default: [ 0, \"\", \"\" ]\n};\n\n// Support: IE <=9 only\nwrapMap.optgroup = wrapMap.option;\n\nwrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\nwrapMap.th = wrapMap.td;\n\n\nfunction getAll( context, tag ) {\n\n\t// Support: IE <=9 - 11 only\n\t// Use typeof to avoid zero-argument method invocation on host objects (#15151)\n\tvar ret;\n\n\tif ( typeof context.getElementsByTagName !== \"undefined\" ) {\n\t\tret = context.getElementsByTagName( tag || \"*\" );\n\n\t} else if ( typeof context.querySelectorAll !== \"undefined\" ) {\n\t\tret = context.querySelectorAll( tag || \"*\" );\n\n\t} else {\n\t\tret = [];\n\t}\n\n\tif ( tag === undefined || tag && jQuery.nodeName( context, tag ) ) {\n\t\treturn jQuery.merge( [ context ], ret );\n\t}\n\n\treturn ret;\n}\n\n\n// Mark scripts as having already been evaluated\nfunction setGlobalEval( elems, refElements ) {\n\tvar i = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\tdataPriv.set(\n\t\t\telems[ i ],\n\t\t\t\"globalEval\",\n\t\t\t!refElements || dataPriv.get( refElements[ i ], \"globalEval\" )\n\t\t);\n\t}\n}\n\n\nvar rhtml = /<|&#?\\w+;/;\n\nfunction buildFragment( elems, context, scripts, selection, ignored ) {\n\tvar elem, tmp, tag, wrap, contains, j,\n\t\tfragment = context.createDocumentFragment(),\n\t\tnodes = [],\n\t\ti = 0,\n\t\tl = elems.length;\n\n\tfor ( ; i < l; i++ ) {\n\t\telem = elems[ i ];\n\n\t\tif ( elem || elem === 0 ) {\n\n\t\t\t// Add nodes directly\n\t\t\tif ( jQuery.type( elem ) === \"object\" ) {\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n\n\t\t\t// Convert non-html into a text node\n\t\t\t} else if ( !rhtml.test( elem ) ) {\n\t\t\t\tnodes.push( context.createTextNode( elem ) );\n\n\t\t\t// Convert html into DOM nodes\n\t\t\t} else {\n\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement( \"div\" ) );\n\n\t\t\t\t// Deserialize a standard representation\n\t\t\t\ttag = ( rtagName.exec( elem ) || [ \"\", \"\" ] )[ 1 ].toLowerCase();\n\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n\t\t\t\ttmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];\n\n\t\t\t\t// Descend through wrappers to the right content\n\t\t\t\tj = wrap[ 0 ];\n\t\t\t\twhile ( j-- ) {\n\t\t\t\t\ttmp = tmp.lastChild;\n\t\t\t\t}\n\n\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n\n\t\t\t\t// Remember the top-level container\n\t\t\t\ttmp = fragment.firstChild;\n\n\t\t\t\t// Ensure the created nodes are orphaned (#12392)\n\t\t\t\ttmp.textContent = \"\";\n\t\t\t}\n\t\t}\n\t}\n\n\t// Remove wrapper from fragment\n\tfragment.textContent = \"\";\n\n\ti = 0;\n\twhile ( ( elem = nodes[ i++ ] ) ) {\n\n\t\t// Skip elements already in the context collection (trac-4087)\n\t\tif ( selection && jQuery.inArray( elem, selection ) > -1 ) {\n\t\t\tif ( ignored ) {\n\t\t\t\tignored.push( elem );\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t// Append to fragment\n\t\ttmp = getAll( fragment.appendChild( elem ), \"script\" );\n\n\t\t// Preserve script evaluation history\n\t\tif ( contains ) {\n\t\t\tsetGlobalEval( tmp );\n\t\t}\n\n\t\t// Capture executables\n\t\tif ( scripts ) {\n\t\t\tj = 0;\n\t\t\twhile ( ( elem = tmp[ j++ ] ) ) {\n\t\t\t\tif ( rscriptType.test( elem.type || \"\" ) ) {\n\t\t\t\t\tscripts.push( elem );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn fragment;\n}\n\n\n( function() {\n\tvar fragment = document.createDocumentFragment(),\n\t\tdiv = fragment.appendChild( document.createElement( \"div\" ) ),\n\t\tinput = document.createElement( \"input\" );\n\n\t// Support: Android 4.0 - 4.3 only\n\t// Check state lost if the name is set (#11217)\n\t// Support: Windows Web Apps (WWA)\n\t// `name` and `type` must use .setAttribute for WWA (#14901)\n\tinput.setAttribute( \"type\", \"radio\" );\n\tinput.setAttribute( \"checked\", \"checked\" );\n\tinput.setAttribute( \"name\", \"t\" );\n\n\tdiv.appendChild( input );\n\n\t// Support: Android <=4.1 only\n\t// Older WebKit doesn't clone checked state correctly in fragments\n\tsupport.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;\n\n\t// Support: IE <=11 only\n\t// Make sure textarea (and checkbox) defaultValue is properly cloned\n\tdiv.innerHTML = \"<textarea>x</textarea>\";\n\tsupport.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;\n} )();\nvar documentElement = document.documentElement;\n\n\n\nvar\n\trkeyEvent = /^key/,\n\trmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,\n\trtypenamespace = /^([^.]*)(?:\\.(.+)|)/;\n\nfunction returnTrue() {\n\treturn true;\n}\n\nfunction returnFalse() {\n\treturn false;\n}\n\n// Support: IE <=9 only\n// See #13393 for more info\nfunction safeActiveElement() {\n\ttry {\n\t\treturn document.activeElement;\n\t} catch ( err ) { }\n}\n\nfunction on( elem, types, selector, data, fn, one ) {\n\tvar origFn, type;\n\n\t// Types can be a map of types/handlers\n\tif ( typeof types === \"object\" ) {\n\n\t\t// ( types-Object, selector, data )\n\t\tif ( typeof selector !== \"string\" ) {\n\n\t\t\t// ( types-Object, data )\n\t\t\tdata = data || selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tfor ( type in types ) {\n\t\t\ton( elem, type, selector, data, types[ type ], one );\n\t\t}\n\t\treturn elem;\n\t}\n\n\tif ( data == null && fn == null ) {\n\n\t\t// ( types, fn )\n\t\tfn = selector;\n\t\tdata = selector = undefined;\n\t} else if ( fn == null ) {\n\t\tif ( typeof selector === \"string\" ) {\n\n\t\t\t// ( types, selector, fn )\n\t\t\tfn = data;\n\t\t\tdata = undefined;\n\t\t} else {\n\n\t\t\t// ( types, data, fn )\n\t\t\tfn = data;\n\t\t\tdata = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t}\n\tif ( fn === false ) {\n\t\tfn = returnFalse;\n\t} else if ( !fn ) {\n\t\treturn elem;\n\t}\n\n\tif ( one === 1 ) {\n\t\torigFn = fn;\n\t\tfn = function( event ) {\n\n\t\t\t// Can use an empty set, since event contains the info\n\t\t\tjQuery().off( event );\n\t\t\treturn origFn.apply( this, arguments );\n\t\t};\n\n\t\t// Use same guid so caller can remove using origFn\n\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n\t}\n\treturn elem.each( function() {\n\t\tjQuery.event.add( this, types, fn, data, selector );\n\t} );\n}\n\n/*\n * Helper functions for managing events -- not part of the public interface.\n * Props to Dean Edwards' addEvent library for many of the ideas.\n */\njQuery.event = {\n\n\tglobal: {},\n\n\tadd: function( elem, types, handler, data, selector ) {\n\n\t\tvar handleObjIn, eventHandle, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = dataPriv.get( elem );\n\n\t\t// Don't attach events to noData or text/comment nodes (but allow plain objects)\n\t\tif ( !elemData ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Caller can pass in an object of custom data in lieu of the handler\n\t\tif ( handler.handler ) {\n\t\t\thandleObjIn = handler;\n\t\t\thandler = handleObjIn.handler;\n\t\t\tselector = handleObjIn.selector;\n\t\t}\n\n\t\t// Ensure that invalid selectors throw exceptions at attach time\n\t\t// Evaluate against documentElement in case elem is a non-element node (e.g., document)\n\t\tif ( selector ) {\n\t\t\tjQuery.find.matchesSelector( documentElement, selector );\n\t\t}\n\n\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n\t\tif ( !handler.guid ) {\n\t\t\thandler.guid = jQuery.guid++;\n\t\t}\n\n\t\t// Init the element's event structure and main handler, if this is the first\n\t\tif ( !( events = elemData.events ) ) {\n\t\t\tevents = elemData.events = {};\n\t\t}\n\t\tif ( !( eventHandle = elemData.handle ) ) {\n\t\t\teventHandle = elemData.handle = function( e ) {\n\n\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n\t\t\t\t// when an event is called after a page has unloaded\n\t\t\t\treturn typeof jQuery !== \"undefined\" && jQuery.event.triggered !== e.type ?\n\t\t\t\t\tjQuery.event.dispatch.apply( elem, arguments ) : undefined;\n\t\t\t};\n\t\t}\n\n\t\t// Handle multiple events separated by a space\n\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\ttype = origType = tmp[ 1 ];\n\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// There *must* be a type, no attaching namespace-only handlers\n\t\t\tif ( !type ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// If event changes its type, use the special event handlers for the changed type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// If selector defined, determine special event api type, otherwise given type\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\n\t\t\t// Update special based on newly reset type\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\n\t\t\t// handleObj is passed to all event handlers\n\t\t\thandleObj = jQuery.extend( {\n\t\t\t\ttype: type,\n\t\t\t\torigType: origType,\n\t\t\t\tdata: data,\n\t\t\t\thandler: handler,\n\t\t\t\tguid: handler.guid,\n\t\t\t\tselector: selector,\n\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n\t\t\t\tnamespace: namespaces.join( \".\" )\n\t\t\t}, handleObjIn );\n\n\t\t\t// Init the event handler queue if we're the first\n\t\t\tif ( !( handlers = events[ type ] ) ) {\n\t\t\t\thandlers = events[ type ] = [];\n\t\t\t\thandlers.delegateCount = 0;\n\n\t\t\t\t// Only use addEventListener if the special events handler returns false\n\t\t\t\tif ( !special.setup ||\n\t\t\t\t\tspecial.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n\n\t\t\t\t\tif ( elem.addEventListener ) {\n\t\t\t\t\t\telem.addEventListener( type, eventHandle );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( special.add ) {\n\t\t\t\tspecial.add.call( elem, handleObj );\n\n\t\t\t\tif ( !handleObj.handler.guid ) {\n\t\t\t\t\thandleObj.handler.guid = handler.guid;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add to the element's handler list, delegates in front\n\t\t\tif ( selector ) {\n\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n\t\t\t} else {\n\t\t\t\thandlers.push( handleObj );\n\t\t\t}\n\n\t\t\t// Keep track of which events have ever been used, for event optimization\n\t\t\tjQuery.event.global[ type ] = true;\n\t\t}\n\n\t},\n\n\t// Detach an event or set of events from an element\n\tremove: function( elem, types, handler, selector, mappedTypes ) {\n\n\t\tvar j, origCount, tmp,\n\t\t\tevents, t, handleObj,\n\t\t\tspecial, handlers, type, namespaces, origType,\n\t\t\telemData = dataPriv.hasData( elem ) && dataPriv.get( elem );\n\n\t\tif ( !elemData || !( events = elemData.events ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Once for each type.namespace in types; type may be omitted\n\t\ttypes = ( types || \"\" ).match( rnothtmlwhite ) || [ \"\" ];\n\t\tt = types.length;\n\t\twhile ( t-- ) {\n\t\t\ttmp = rtypenamespace.exec( types[ t ] ) || [];\n\t\t\ttype = origType = tmp[ 1 ];\n\t\t\tnamespaces = ( tmp[ 2 ] || \"\" ).split( \".\" ).sort();\n\n\t\t\t// Unbind all events (on this namespace, if provided) for the element\n\t\t\tif ( !type ) {\n\t\t\t\tfor ( type in events ) {\n\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tspecial = jQuery.event.special[ type ] || {};\n\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n\t\t\thandlers = events[ type ] || [];\n\t\t\ttmp = tmp[ 2 ] &&\n\t\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" );\n\n\t\t\t// Remove matching events\n\t\t\torigCount = j = handlers.length;\n\t\t\twhile ( j-- ) {\n\t\t\t\thandleObj = handlers[ j ];\n\n\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n\t\t\t\t\t( !selector || selector === handleObj.selector ||\n\t\t\t\t\t\tselector === \"**\" && handleObj.selector ) ) {\n\t\t\t\t\thandlers.splice( j, 1 );\n\n\t\t\t\t\tif ( handleObj.selector ) {\n\t\t\t\t\t\thandlers.delegateCount--;\n\t\t\t\t\t}\n\t\t\t\t\tif ( special.remove ) {\n\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n\t\t\tif ( origCount && !handlers.length ) {\n\t\t\t\tif ( !special.teardown ||\n\t\t\t\t\tspecial.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n\n\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n\t\t\t\t}\n\n\t\t\t\tdelete events[ type ];\n\t\t\t}\n\t\t}\n\n\t\t// Remove data and the expando if it's no longer used\n\t\tif ( jQuery.isEmptyObject( events ) ) {\n\t\t\tdataPriv.remove( elem, \"handle events\" );\n\t\t}\n\t},\n\n\tdispatch: function( nativeEvent ) {\n\n\t\t// Make a writable jQuery.Event from the native event object\n\t\tvar event = jQuery.event.fix( nativeEvent );\n\n\t\tvar i, j, ret, matched, handleObj, handlerQueue,\n\t\t\targs = new Array( arguments.length ),\n\t\t\thandlers = ( dataPriv.get( this, \"events\" ) || {} )[ event.type ] || [],\n\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n\n\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n\t\targs[ 0 ] = event;\n\n\t\tfor ( i = 1; i < arguments.length; i++ ) {\n\t\t\targs[ i ] = arguments[ i ];\n\t\t}\n\n\t\tevent.delegateTarget = this;\n\n\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine handlers\n\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n\n\t\t// Run delegates first; they may want to stop propagation beneath us\n\t\ti = 0;\n\t\twhile ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {\n\t\t\tevent.currentTarget = matched.elem;\n\n\t\t\tj = 0;\n\t\t\twhile ( ( handleObj = matched.handlers[ j++ ] ) &&\n\t\t\t\t!event.isImmediatePropagationStopped() ) {\n\n\t\t\t\t// Triggered event must either 1) have no namespace, or 2) have namespace(s)\n\t\t\t\t// a subset or equal to those in the bound event (both can have no namespace).\n\t\t\t\tif ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {\n\n\t\t\t\t\tevent.handleObj = handleObj;\n\t\t\t\t\tevent.data = handleObj.data;\n\n\t\t\t\t\tret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||\n\t\t\t\t\t\thandleObj.handler ).apply( matched.elem, args );\n\n\t\t\t\t\tif ( ret !== undefined ) {\n\t\t\t\t\t\tif ( ( event.result = ret ) === false ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\tevent.stopPropagation();\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Call the postDispatch hook for the mapped type\n\t\tif ( special.postDispatch ) {\n\t\t\tspecial.postDispatch.call( this, event );\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\thandlers: function( event, handlers ) {\n\t\tvar i, handleObj, sel, matchedHandlers, matchedSelectors,\n\t\t\thandlerQueue = [],\n\t\t\tdelegateCount = handlers.delegateCount,\n\t\t\tcur = event.target;\n\n\t\t// Find delegate handlers\n\t\tif ( delegateCount &&\n\n\t\t\t// Support: IE <=9\n\t\t\t// Black-hole SVG <use> instance trees (trac-13180)\n\t\t\tcur.nodeType &&\n\n\t\t\t// Support: Firefox <=42\n\t\t\t// Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)\n\t\t\t// https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click\n\t\t\t// Support: IE 11 only\n\t\t\t// ...but not arrow key \"clicks\" of radio inputs, which can have `button` -1 (gh-2343)\n\t\t\t!( event.type === \"click\" && event.button >= 1 ) ) {\n\n\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n\n\t\t\t\t// Don't check non-elements (#13208)\n\t\t\t\t// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)\n\t\t\t\tif ( cur.nodeType === 1 && !( event.type === \"click\" && cur.disabled === true ) ) {\n\t\t\t\t\tmatchedHandlers = [];\n\t\t\t\t\tmatchedSelectors = {};\n\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n\t\t\t\t\t\thandleObj = handlers[ i ];\n\n\t\t\t\t\t\t// Don't conflict with Object.prototype properties (#13203)\n\t\t\t\t\t\tsel = handleObj.selector + \" \";\n\n\t\t\t\t\t\tif ( matchedSelectors[ sel ] === undefined ) {\n\t\t\t\t\t\t\tmatchedSelectors[ sel ] = handleObj.needsContext ?\n\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) > -1 :\n\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( matchedSelectors[ sel ] ) {\n\t\t\t\t\t\t\tmatchedHandlers.push( handleObj );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tif ( matchedHandlers.length ) {\n\t\t\t\t\t\thandlerQueue.push( { elem: cur, handlers: matchedHandlers } );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Add the remaining (directly-bound) handlers\n\t\tcur = this;\n\t\tif ( delegateCount < handlers.length ) {\n\t\t\thandlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );\n\t\t}\n\n\t\treturn handlerQueue;\n\t},\n\n\taddProp: function( name, hook ) {\n\t\tObject.defineProperty( jQuery.Event.prototype, name, {\n\t\t\tenumerable: true,\n\t\t\tconfigurable: true,\n\n\t\t\tget: jQuery.isFunction( hook ) ?\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn hook( this.originalEvent );\n\t\t\t\t\t}\n\t\t\t\t} :\n\t\t\t\tfunction() {\n\t\t\t\t\tif ( this.originalEvent ) {\n\t\t\t\t\t\t\treturn this.originalEvent[ name ];\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\tset: function( value ) {\n\t\t\t\tObject.defineProperty( this, name, {\n\t\t\t\t\tenumerable: true,\n\t\t\t\t\tconfigurable: true,\n\t\t\t\t\twritable: true,\n\t\t\t\t\tvalue: value\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\t},\n\n\tfix: function( originalEvent ) {\n\t\treturn originalEvent[ jQuery.expando ] ?\n\t\t\toriginalEvent :\n\t\t\tnew jQuery.Event( originalEvent );\n\t},\n\n\tspecial: {\n\t\tload: {\n\n\t\t\t// Prevent triggered image.load events from bubbling to window.load\n\t\t\tnoBubble: true\n\t\t},\n\t\tfocus: {\n\n\t\t\t// Fire native event if possible so blur/focus sequence is correct\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this !== safeActiveElement() && this.focus ) {\n\t\t\t\t\tthis.focus();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusin\"\n\t\t},\n\t\tblur: {\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this === safeActiveElement() && this.blur ) {\n\t\t\t\t\tthis.blur();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\t\t\tdelegateType: \"focusout\"\n\t\t},\n\t\tclick: {\n\n\t\t\t// For checkbox, fire native event so checked state will be right\n\t\t\ttrigger: function() {\n\t\t\t\tif ( this.type === \"checkbox\" && this.click && jQuery.nodeName( this, \"input\" ) ) {\n\t\t\t\t\tthis.click();\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t// For cross-browser consistency, don't fire native .click() on links\n\t\t\t_default: function( event ) {\n\t\t\t\treturn jQuery.nodeName( event.target, \"a\" );\n\t\t\t}\n\t\t},\n\n\t\tbeforeunload: {\n\t\t\tpostDispatch: function( event ) {\n\n\t\t\t\t// Support: Firefox 20+\n\t\t\t\t// Firefox doesn't alert if the returnValue field is not set.\n\t\t\t\tif ( event.result !== undefined && event.originalEvent ) {\n\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n};\n\njQuery.removeEvent = function( elem, type, handle ) {\n\n\t// This \"if\" is needed for plain objects\n\tif ( elem.removeEventListener ) {\n\t\telem.removeEventListener( type, handle );\n\t}\n};\n\njQuery.Event = function( src, props ) {\n\n\t// Allow instantiation without the 'new' keyword\n\tif ( !( this instanceof jQuery.Event ) ) {\n\t\treturn new jQuery.Event( src, props );\n\t}\n\n\t// Event object\n\tif ( src && src.type ) {\n\t\tthis.originalEvent = src;\n\t\tthis.type = src.type;\n\n\t\t// Events bubbling up the document may have been marked as prevented\n\t\t// by a handler lower down the tree; reflect the correct value.\n\t\tthis.isDefaultPrevented = src.defaultPrevented ||\n\t\t\t\tsrc.defaultPrevented === undefined &&\n\n\t\t\t\t// Support: Android <=2.3 only\n\t\t\t\tsrc.returnValue === false ?\n\t\t\treturnTrue :\n\t\t\treturnFalse;\n\n\t\t// Create target properties\n\t\t// Support: Safari <=6 - 7 only\n\t\t// Target should not be a text node (#504, #13143)\n\t\tthis.target = ( src.target && src.target.nodeType === 3 ) ?\n\t\t\tsrc.target.parentNode :\n\t\t\tsrc.target;\n\n\t\tthis.currentTarget = src.currentTarget;\n\t\tthis.relatedTarget = src.relatedTarget;\n\n\t// Event type\n\t} else {\n\t\tthis.type = src;\n\t}\n\n\t// Put explicitly provided properties onto the event object\n\tif ( props ) {\n\t\tjQuery.extend( this, props );\n\t}\n\n\t// Create a timestamp if incoming event doesn't have one\n\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n\n\t// Mark it as fixed\n\tthis[ jQuery.expando ] = true;\n};\n\n// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\njQuery.Event.prototype = {\n\tconstructor: jQuery.Event,\n\tisDefaultPrevented: returnFalse,\n\tisPropagationStopped: returnFalse,\n\tisImmediatePropagationStopped: returnFalse,\n\tisSimulated: false,\n\n\tpreventDefault: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isDefaultPrevented = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.preventDefault();\n\t\t}\n\t},\n\tstopPropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isPropagationStopped = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.stopPropagation();\n\t\t}\n\t},\n\tstopImmediatePropagation: function() {\n\t\tvar e = this.originalEvent;\n\n\t\tthis.isImmediatePropagationStopped = returnTrue;\n\n\t\tif ( e && !this.isSimulated ) {\n\t\t\te.stopImmediatePropagation();\n\t\t}\n\n\t\tthis.stopPropagation();\n\t}\n};\n\n// Includes all common event props including KeyEvent and MouseEvent specific props\njQuery.each( {\n\taltKey: true,\n\tbubbles: true,\n\tcancelable: true,\n\tchangedTouches: true,\n\tctrlKey: true,\n\tdetail: true,\n\teventPhase: true,\n\tmetaKey: true,\n\tpageX: true,\n\tpageY: true,\n\tshiftKey: true,\n\tview: true,\n\t\"char\": true,\n\tcharCode: true,\n\tkey: true,\n\tkeyCode: true,\n\tbutton: true,\n\tbuttons: true,\n\tclientX: true,\n\tclientY: true,\n\toffsetX: true,\n\toffsetY: true,\n\tpointerId: true,\n\tpointerType: true,\n\tscreenX: true,\n\tscreenY: true,\n\ttargetTouches: true,\n\ttoElement: true,\n\ttouches: true,\n\n\twhich: function( event ) {\n\t\tvar button = event.button;\n\n\t\t// Add which for key events\n\t\tif ( event.which == null && rkeyEvent.test( event.type ) ) {\n\t\t\treturn event.charCode != null ? event.charCode : event.keyCode;\n\t\t}\n\n\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n\t\tif ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {\n\t\t\tif ( button & 1 ) {\n\t\t\t\treturn 1;\n\t\t\t}\n\n\t\t\tif ( button & 2 ) {\n\t\t\t\treturn 3;\n\t\t\t}\n\n\t\t\tif ( button & 4 ) {\n\t\t\t\treturn 2;\n\t\t\t}\n\n\t\t\treturn 0;\n\t\t}\n\n\t\treturn event.which;\n\t}\n}, jQuery.event.addProp );\n\n// Create mouseenter/leave events using mouseover/out and event-time checks\n// so that event delegation works in jQuery.\n// Do the same for pointerenter/pointerleave and pointerover/pointerout\n//\n// Support: Safari 7 only\n// Safari sends mouseenter too often; see:\n// https://bugs.chromium.org/p/chromium/issues/detail?id=470258\n// for the description of the bug (it existed in older Chrome versions as well).\njQuery.each( {\n\tmouseenter: \"mouseover\",\n\tmouseleave: \"mouseout\",\n\tpointerenter: \"pointerover\",\n\tpointerleave: \"pointerout\"\n}, function( orig, fix ) {\n\tjQuery.event.special[ orig ] = {\n\t\tdelegateType: fix,\n\t\tbindType: fix,\n\n\t\thandle: function( event ) {\n\t\t\tvar ret,\n\t\t\t\ttarget = this,\n\t\t\t\trelated = event.relatedTarget,\n\t\t\t\thandleObj = event.handleObj;\n\n\t\t\t// For mouseenter/leave call the handler if related is outside the target.\n\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n\t\t\tif ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {\n\t\t\t\tevent.type = handleObj.origType;\n\t\t\t\tret = handleObj.handler.apply( this, arguments );\n\t\t\t\tevent.type = fix;\n\t\t\t}\n\t\t\treturn ret;\n\t\t}\n\t};\n} );\n\njQuery.fn.extend( {\n\n\ton: function( types, selector, data, fn ) {\n\t\treturn on( this, types, selector, data, fn );\n\t},\n\tone: function( types, selector, data, fn ) {\n\t\treturn on( this, types, selector, data, fn, 1 );\n\t},\n\toff: function( types, selector, fn ) {\n\t\tvar handleObj, type;\n\t\tif ( types && types.preventDefault && types.handleObj ) {\n\n\t\t\t// ( event )  dispatched jQuery.Event\n\t\t\thandleObj = types.handleObj;\n\t\t\tjQuery( types.delegateTarget ).off(\n\t\t\t\thandleObj.namespace ?\n\t\t\t\t\thandleObj.origType + \".\" + handleObj.namespace :\n\t\t\t\t\thandleObj.origType,\n\t\t\t\thandleObj.selector,\n\t\t\t\thandleObj.handler\n\t\t\t);\n\t\t\treturn this;\n\t\t}\n\t\tif ( typeof types === \"object\" ) {\n\n\t\t\t// ( types-object [, selector] )\n\t\t\tfor ( type in types ) {\n\t\t\t\tthis.off( type, selector, types[ type ] );\n\t\t\t}\n\t\t\treturn this;\n\t\t}\n\t\tif ( selector === false || typeof selector === \"function\" ) {\n\n\t\t\t// ( types [, fn] )\n\t\t\tfn = selector;\n\t\t\tselector = undefined;\n\t\t}\n\t\tif ( fn === false ) {\n\t\t\tfn = returnFalse;\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.remove( this, types, fn, selector );\n\t\t} );\n\t}\n} );\n\n\nvar\n\n\t/* eslint-disable max-len */\n\n\t// See https://github.com/eslint/eslint/issues/3229\n\trxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\\/\\0>\\x20\\t\\r\\n\\f]*)[^>]*)\\/>/gi,\n\n\t/* eslint-enable */\n\n\t// Support: IE <=10 - 11, Edge 12 - 13\n\t// In IE/Edge using regex groups here causes severe slowdowns.\n\t// See https://connect.microsoft.com/IE/feedback/details/1736512/\n\trnoInnerhtml = /<script|<style|<link/i,\n\n\t// checked=\"checked\" or checked\n\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n\trscriptTypeMasked = /^true\\/(.*)/,\n\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g;\n\nfunction manipulationTarget( elem, content ) {\n\tif ( jQuery.nodeName( elem, \"table\" ) &&\n\t\tjQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, \"tr\" ) ) {\n\n\t\treturn elem.getElementsByTagName( \"tbody\" )[ 0 ] || elem;\n\t}\n\n\treturn elem;\n}\n\n// Replace/restore the type attribute of script elements for safe DOM manipulation\nfunction disableScript( elem ) {\n\telem.type = ( elem.getAttribute( \"type\" ) !== null ) + \"/\" + elem.type;\n\treturn elem;\n}\nfunction restoreScript( elem ) {\n\tvar match = rscriptTypeMasked.exec( elem.type );\n\n\tif ( match ) {\n\t\telem.type = match[ 1 ];\n\t} else {\n\t\telem.removeAttribute( \"type\" );\n\t}\n\n\treturn elem;\n}\n\nfunction cloneCopyEvent( src, dest ) {\n\tvar i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n\n\tif ( dest.nodeType !== 1 ) {\n\t\treturn;\n\t}\n\n\t// 1. Copy private data: events, handlers, etc.\n\tif ( dataPriv.hasData( src ) ) {\n\t\tpdataOld = dataPriv.access( src );\n\t\tpdataCur = dataPriv.set( dest, pdataOld );\n\t\tevents = pdataOld.events;\n\n\t\tif ( events ) {\n\t\t\tdelete pdataCur.handle;\n\t\t\tpdataCur.events = {};\n\n\t\t\tfor ( type in events ) {\n\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// 2. Copy user data\n\tif ( dataUser.hasData( src ) ) {\n\t\tudataOld = dataUser.access( src );\n\t\tudataCur = jQuery.extend( {}, udataOld );\n\n\t\tdataUser.set( dest, udataCur );\n\t}\n}\n\n// Fix IE bugs, see support tests\nfunction fixInput( src, dest ) {\n\tvar nodeName = dest.nodeName.toLowerCase();\n\n\t// Fails to persist the checked state of a cloned checkbox or radio button.\n\tif ( nodeName === \"input\" && rcheckableType.test( src.type ) ) {\n\t\tdest.checked = src.checked;\n\n\t// Fails to return the selected option to the default selected state when cloning options\n\t} else if ( nodeName === \"input\" || nodeName === \"textarea\" ) {\n\t\tdest.defaultValue = src.defaultValue;\n\t}\n}\n\nfunction domManip( collection, args, callback, ignored ) {\n\n\t// Flatten any nested arrays\n\targs = concat.apply( [], args );\n\n\tvar fragment, first, scripts, hasScripts, node, doc,\n\t\ti = 0,\n\t\tl = collection.length,\n\t\tiNoClone = l - 1,\n\t\tvalue = args[ 0 ],\n\t\tisFunction = jQuery.isFunction( value );\n\n\t// We can't cloneNode fragments that contain checked, in WebKit\n\tif ( isFunction ||\n\t\t\t( l > 1 && typeof value === \"string\" &&\n\t\t\t\t!support.checkClone && rchecked.test( value ) ) ) {\n\t\treturn collection.each( function( index ) {\n\t\t\tvar self = collection.eq( index );\n\t\t\tif ( isFunction ) {\n\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n\t\t\t}\n\t\t\tdomManip( self, args, callback, ignored );\n\t\t} );\n\t}\n\n\tif ( l ) {\n\t\tfragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );\n\t\tfirst = fragment.firstChild;\n\n\t\tif ( fragment.childNodes.length === 1 ) {\n\t\t\tfragment = first;\n\t\t}\n\n\t\t// Require either new content or an interest in ignored elements to invoke the callback\n\t\tif ( first || ignored ) {\n\t\t\tscripts = jQuery.map( getAll( fragment, \"script\" ), disableScript );\n\t\t\thasScripts = scripts.length;\n\n\t\t\t// Use the original fragment for the last item\n\t\t\t// instead of the first because it can end up\n\t\t\t// being emptied incorrectly in certain situations (#8070).\n\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\tnode = fragment;\n\n\t\t\t\tif ( i !== iNoClone ) {\n\t\t\t\t\tnode = jQuery.clone( node, true, true );\n\n\t\t\t\t\t// Keep references to cloned scripts for later restoration\n\t\t\t\t\tif ( hasScripts ) {\n\n\t\t\t\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t\t\t\t// push.apply(_, arraylike) throws on ancient WebKit\n\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, \"script\" ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcallback.call( collection[ i ], node, i );\n\t\t\t}\n\n\t\t\tif ( hasScripts ) {\n\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n\n\t\t\t\t// Reenable scripts\n\t\t\t\tjQuery.map( scripts, restoreScript );\n\n\t\t\t\t// Evaluate executable scripts on first document insertion\n\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n\t\t\t\t\tnode = scripts[ i ];\n\t\t\t\t\tif ( rscriptType.test( node.type || \"\" ) &&\n\t\t\t\t\t\t!dataPriv.access( node, \"globalEval\" ) &&\n\t\t\t\t\t\tjQuery.contains( doc, node ) ) {\n\n\t\t\t\t\t\tif ( node.src ) {\n\n\t\t\t\t\t\t\t// Optional AJAX dependency, but won't run scripts if not present\n\t\t\t\t\t\t\tif ( jQuery._evalUrl ) {\n\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tDOMEval( node.textContent.replace( rcleanScript, \"\" ), doc );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn collection;\n}\n\nfunction remove( elem, selector, keepData ) {\n\tvar node,\n\t\tnodes = selector ? jQuery.filter( selector, elem ) : elem,\n\t\ti = 0;\n\n\tfor ( ; ( node = nodes[ i ] ) != null; i++ ) {\n\t\tif ( !keepData && node.nodeType === 1 ) {\n\t\t\tjQuery.cleanData( getAll( node ) );\n\t\t}\n\n\t\tif ( node.parentNode ) {\n\t\t\tif ( keepData && jQuery.contains( node.ownerDocument, node ) ) {\n\t\t\t\tsetGlobalEval( getAll( node, \"script\" ) );\n\t\t\t}\n\t\t\tnode.parentNode.removeChild( node );\n\t\t}\n\t}\n\n\treturn elem;\n}\n\njQuery.extend( {\n\thtmlPrefilter: function( html ) {\n\t\treturn html.replace( rxhtmlTag, \"<$1></$2>\" );\n\t},\n\n\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n\t\tvar i, l, srcElements, destElements,\n\t\t\tclone = elem.cloneNode( true ),\n\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n\n\t\t// Fix IE cloning issues\n\t\tif ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&\n\t\t\t\t!jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2\n\t\t\tdestElements = getAll( clone );\n\t\t\tsrcElements = getAll( elem );\n\n\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n\t\t\t}\n\t\t}\n\n\t\t// Copy the events from the original to the clone\n\t\tif ( dataAndEvents ) {\n\t\t\tif ( deepDataAndEvents ) {\n\t\t\t\tsrcElements = srcElements || getAll( elem );\n\t\t\t\tdestElements = destElements || getAll( clone );\n\n\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcloneCopyEvent( elem, clone );\n\t\t\t}\n\t\t}\n\n\t\t// Preserve script evaluation history\n\t\tdestElements = getAll( clone, \"script\" );\n\t\tif ( destElements.length > 0 ) {\n\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, \"script\" ) );\n\t\t}\n\n\t\t// Return the cloned set\n\t\treturn clone;\n\t},\n\n\tcleanData: function( elems ) {\n\t\tvar data, elem, type,\n\t\t\tspecial = jQuery.event.special,\n\t\t\ti = 0;\n\n\t\tfor ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {\n\t\t\tif ( acceptData( elem ) ) {\n\t\t\t\tif ( ( data = elem[ dataPriv.expando ] ) ) {\n\t\t\t\t\tif ( data.events ) {\n\t\t\t\t\t\tfor ( type in data.events ) {\n\t\t\t\t\t\t\tif ( special[ type ] ) {\n\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n\n\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove's overhead\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\telem[ dataPriv.expando ] = undefined;\n\t\t\t\t}\n\t\t\t\tif ( elem[ dataUser.expando ] ) {\n\n\t\t\t\t\t// Support: Chrome <=35 - 45+\n\t\t\t\t\t// Assign undefined instead of using delete, see Data#remove\n\t\t\t\t\telem[ dataUser.expando ] = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n} );\n\njQuery.fn.extend( {\n\tdetach: function( selector ) {\n\t\treturn remove( this, selector, true );\n\t},\n\n\tremove: function( selector ) {\n\t\treturn remove( this, selector );\n\t},\n\n\ttext: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\treturn value === undefined ?\n\t\t\t\tjQuery.text( this ) :\n\t\t\t\tthis.empty().each( function() {\n\t\t\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\t\t\tthis.textContent = value;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t}, null, value, arguments.length );\n\t},\n\n\tappend: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.appendChild( elem );\n\t\t\t}\n\t\t} );\n\t},\n\n\tprepend: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n\t\t\t\tvar target = manipulationTarget( this, elem );\n\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n\t\t\t}\n\t\t} );\n\t},\n\n\tbefore: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this );\n\t\t\t}\n\t\t} );\n\t},\n\n\tafter: function() {\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tif ( this.parentNode ) {\n\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n\t\t\t}\n\t\t} );\n\t},\n\n\tempty: function() {\n\t\tvar elem,\n\t\t\ti = 0;\n\n\t\tfor ( ; ( elem = this[ i ] ) != null; i++ ) {\n\t\t\tif ( elem.nodeType === 1 ) {\n\n\t\t\t\t// Prevent memory leaks\n\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\n\t\t\t\t// Remove any remaining nodes\n\t\t\t\telem.textContent = \"\";\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tclone: function( dataAndEvents, deepDataAndEvents ) {\n\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n\n\t\treturn this.map( function() {\n\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n\t\t} );\n\t},\n\n\thtml: function( value ) {\n\t\treturn access( this, function( value ) {\n\t\t\tvar elem = this[ 0 ] || {},\n\t\t\t\ti = 0,\n\t\t\t\tl = this.length;\n\n\t\t\tif ( value === undefined && elem.nodeType === 1 ) {\n\t\t\t\treturn elem.innerHTML;\n\t\t\t}\n\n\t\t\t// See if we can take a shortcut and just use innerHTML\n\t\t\tif ( typeof value === \"string\" && !rnoInnerhtml.test( value ) &&\n\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ \"\", \"\" ] )[ 1 ].toLowerCase() ] ) {\n\n\t\t\t\tvalue = jQuery.htmlPrefilter( value );\n\n\t\t\t\ttry {\n\t\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\t\telem = this[ i ] || {};\n\n\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n\t\t\t\t\t\t\telem.innerHTML = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\telem = 0;\n\n\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n\t\t\t\t} catch ( e ) {}\n\t\t\t}\n\n\t\t\tif ( elem ) {\n\t\t\t\tthis.empty().append( value );\n\t\t\t}\n\t\t}, null, value, arguments.length );\n\t},\n\n\treplaceWith: function() {\n\t\tvar ignored = [];\n\n\t\t// Make the changes, replacing each non-ignored context element with the new content\n\t\treturn domManip( this, arguments, function( elem ) {\n\t\t\tvar parent = this.parentNode;\n\n\t\t\tif ( jQuery.inArray( this, ignored ) < 0 ) {\n\t\t\t\tjQuery.cleanData( getAll( this ) );\n\t\t\t\tif ( parent ) {\n\t\t\t\t\tparent.replaceChild( elem, this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Force callback invocation\n\t\t}, ignored );\n\t}\n} );\n\njQuery.each( {\n\tappendTo: \"append\",\n\tprependTo: \"prepend\",\n\tinsertBefore: \"before\",\n\tinsertAfter: \"after\",\n\treplaceAll: \"replaceWith\"\n}, function( name, original ) {\n\tjQuery.fn[ name ] = function( selector ) {\n\t\tvar elems,\n\t\t\tret = [],\n\t\t\tinsert = jQuery( selector ),\n\t\t\tlast = insert.length - 1,\n\t\t\ti = 0;\n\n\t\tfor ( ; i <= last; i++ ) {\n\t\t\telems = i === last ? this : this.clone( true );\n\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n\n\t\t\t// Support: Android <=4.0 only, PhantomJS 1 only\n\t\t\t// .get() because push.apply(_, arraylike) throws on ancient WebKit\n\t\t\tpush.apply( ret, elems.get() );\n\t\t}\n\n\t\treturn this.pushStack( ret );\n\t};\n} );\nvar rmargin = ( /^margin/ );\n\nvar rnumnonpx = new RegExp( \"^(\" + pnum + \")(?!px)[a-z%]+$\", \"i\" );\n\nvar getStyles = function( elem ) {\n\n\t\t// Support: IE <=11 only, Firefox <=30 (#15098, #14150)\n\t\t// IE throws on elements created in popups\n\t\t// FF meanwhile throws on frame elements through \"defaultView.getComputedStyle\"\n\t\tvar view = elem.ownerDocument.defaultView;\n\n\t\tif ( !view || !view.opener ) {\n\t\t\tview = window;\n\t\t}\n\n\t\treturn view.getComputedStyle( elem );\n\t};\n\n\n\n( function() {\n\n\t// Executing both pixelPosition & boxSizingReliable tests require only one layout\n\t// so they're executed at the same time to save the second computation.\n\tfunction computeStyleTests() {\n\n\t\t// This is a singleton, we need to execute it only once\n\t\tif ( !div ) {\n\t\t\treturn;\n\t\t}\n\n\t\tdiv.style.cssText =\n\t\t\t\"box-sizing:border-box;\" +\n\t\t\t\"position:relative;display:block;\" +\n\t\t\t\"margin:auto;border:1px;padding:1px;\" +\n\t\t\t\"top:1%;width:50%\";\n\t\tdiv.innerHTML = \"\";\n\t\tdocumentElement.appendChild( container );\n\n\t\tvar divStyle = window.getComputedStyle( div );\n\t\tpixelPositionVal = divStyle.top !== \"1%\";\n\n\t\t// Support: Android 4.0 - 4.3 only, Firefox <=3 - 44\n\t\treliableMarginLeftVal = divStyle.marginLeft === \"2px\";\n\t\tboxSizingReliableVal = divStyle.width === \"4px\";\n\n\t\t// Support: Android 4.0 - 4.3 only\n\t\t// Some styles come back with percentage values, even though they shouldn't\n\t\tdiv.style.marginRight = \"50%\";\n\t\tpixelMarginRightVal = divStyle.marginRight === \"4px\";\n\n\t\tdocumentElement.removeChild( container );\n\n\t\t// Nullify the div so it wouldn't be stored in the memory and\n\t\t// it will also be a sign that checks already performed\n\t\tdiv = null;\n\t}\n\n\tvar pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,\n\t\tcontainer = document.createElement( \"div\" ),\n\t\tdiv = document.createElement( \"div\" );\n\n\t// Finish early in limited (non-browser) environments\n\tif ( !div.style ) {\n\t\treturn;\n\t}\n\n\t// Support: IE <=9 - 11 only\n\t// Style of cloned element affects source element cloned (#8908)\n\tdiv.style.backgroundClip = \"content-box\";\n\tdiv.cloneNode( true ).style.backgroundClip = \"\";\n\tsupport.clearCloneStyle = div.style.backgroundClip === \"content-box\";\n\n\tcontainer.style.cssText = \"border:0;width:8px;height:0;top:0;left:-9999px;\" +\n\t\t\"padding:0;margin-top:1px;position:absolute\";\n\tcontainer.appendChild( div );\n\n\tjQuery.extend( support, {\n\t\tpixelPosition: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn pixelPositionVal;\n\t\t},\n\t\tboxSizingReliable: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn boxSizingReliableVal;\n\t\t},\n\t\tpixelMarginRight: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn pixelMarginRightVal;\n\t\t},\n\t\treliableMarginLeft: function() {\n\t\t\tcomputeStyleTests();\n\t\t\treturn reliableMarginLeftVal;\n\t\t}\n\t} );\n} )();\n\n\nfunction curCSS( elem, name, computed ) {\n\tvar width, minWidth, maxWidth, ret,\n\t\tstyle = elem.style;\n\n\tcomputed = computed || getStyles( elem );\n\n\t// Support: IE <=9 only\n\t// getPropertyValue is only needed for .css('filter') (#12537)\n\tif ( computed ) {\n\t\tret = computed.getPropertyValue( name ) || computed[ name ];\n\n\t\tif ( ret === \"\" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n\t\t\tret = jQuery.style( elem, name );\n\t\t}\n\n\t\t// A tribute to the \"awesome hack by Dean Edwards\"\n\t\t// Android Browser returns percentage for some values,\n\t\t// but width seems to be reliably pixels.\n\t\t// This is against the CSSOM draft spec:\n\t\t// https://drafts.csswg.org/cssom/#resolved-values\n\t\tif ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n\n\t\t\t// Remember the original values\n\t\t\twidth = style.width;\n\t\t\tminWidth = style.minWidth;\n\t\t\tmaxWidth = style.maxWidth;\n\n\t\t\t// Put in the new values to get a computed value out\n\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n\t\t\tret = computed.width;\n\n\t\t\t// Revert the changed values\n\t\t\tstyle.width = width;\n\t\t\tstyle.minWidth = minWidth;\n\t\t\tstyle.maxWidth = maxWidth;\n\t\t}\n\t}\n\n\treturn ret !== undefined ?\n\n\t\t// Support: IE <=9 - 11 only\n\t\t// IE returns zIndex value as an integer.\n\t\tret + \"\" :\n\t\tret;\n}\n\n\nfunction addGetHookIf( conditionFn, hookFn ) {\n\n\t// Define the hook, we'll check on the first run if it's really needed.\n\treturn {\n\t\tget: function() {\n\t\t\tif ( conditionFn() ) {\n\n\t\t\t\t// Hook not needed (or it's not possible to use it due\n\t\t\t\t// to missing dependency), remove it.\n\t\t\t\tdelete this.get;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Hook needed; redefine it so that the support test is not executed again.\n\t\t\treturn ( this.get = hookFn ).apply( this, arguments );\n\t\t}\n\t};\n}\n\n\nvar\n\n\t// Swappable if display is none or starts with table\n\t// except \"table\", \"table-cell\", or \"table-caption\"\n\t// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n\tcssShow = { position: \"absolute\", visibility: \"hidden\", display: \"block\" },\n\tcssNormalTransform = {\n\t\tletterSpacing: \"0\",\n\t\tfontWeight: \"400\"\n\t},\n\n\tcssPrefixes = [ \"Webkit\", \"Moz\", \"ms\" ],\n\temptyStyle = document.createElement( \"div\" ).style;\n\n// Return a css property mapped to a potentially vendor prefixed property\nfunction vendorPropName( name ) {\n\n\t// Shortcut for names that are not vendor prefixed\n\tif ( name in emptyStyle ) {\n\t\treturn name;\n\t}\n\n\t// Check for vendor prefixed names\n\tvar capName = name[ 0 ].toUpperCase() + name.slice( 1 ),\n\t\ti = cssPrefixes.length;\n\n\twhile ( i-- ) {\n\t\tname = cssPrefixes[ i ] + capName;\n\t\tif ( name in emptyStyle ) {\n\t\t\treturn name;\n\t\t}\n\t}\n}\n\nfunction setPositiveNumber( elem, value, subtract ) {\n\n\t// Any relative (+/-) values have already been\n\t// normalized at this point\n\tvar matches = rcssNum.exec( value );\n\treturn matches ?\n\n\t\t// Guard against undefined \"subtract\", e.g., when used as in cssHooks\n\t\tMath.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || \"px\" ) :\n\t\tvalue;\n}\n\nfunction augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n\tvar i,\n\t\tval = 0;\n\n\t// If we already have the right measurement, avoid augmentation\n\tif ( extra === ( isBorderBox ? \"border\" : \"content\" ) ) {\n\t\ti = 4;\n\n\t// Otherwise initialize for horizontal or vertical properties\n\t} else {\n\t\ti = name === \"width\" ? 1 : 0;\n\t}\n\n\tfor ( ; i < 4; i += 2 ) {\n\n\t\t// Both box models exclude margin, so add it if we want it\n\t\tif ( extra === \"margin\" ) {\n\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true, styles );\n\t\t}\n\n\t\tif ( isBorderBox ) {\n\n\t\t\t// border-box includes padding, so remove it if we want content\n\t\t\tif ( extra === \"content\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\t\t\t}\n\n\t\t\t// At this point, extra isn't border nor margin, so remove border\n\t\t\tif ( extra !== \"margin\" ) {\n\t\t\t\tval -= jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t} else {\n\n\t\t\t// At this point, extra isn't content, so add padding\n\t\t\tval += jQuery.css( elem, \"padding\" + cssExpand[ i ], true, styles );\n\n\t\t\t// At this point, extra isn't content nor padding, so add border\n\t\t\tif ( extra !== \"padding\" ) {\n\t\t\t\tval += jQuery.css( elem, \"border\" + cssExpand[ i ] + \"Width\", true, styles );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn val;\n}\n\nfunction getWidthOrHeight( elem, name, extra ) {\n\n\t// Start with offset property, which is equivalent to the border-box value\n\tvar val,\n\t\tvalueIsBorderBox = true,\n\t\tstyles = getStyles( elem ),\n\t\tisBorderBox = jQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\";\n\n\t// Support: IE <=11 only\n\t// Running getBoundingClientRect on a disconnected node\n\t// in IE throws an error.\n\tif ( elem.getClientRects().length ) {\n\t\tval = elem.getBoundingClientRect()[ name ];\n\t}\n\n\t// Some non-html elements return undefined for offsetWidth, so check for null/undefined\n\t// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n\t// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n\tif ( val <= 0 || val == null ) {\n\n\t\t// Fall back to computed then uncomputed css if necessary\n\t\tval = curCSS( elem, name, styles );\n\t\tif ( val < 0 || val == null ) {\n\t\t\tval = elem.style[ name ];\n\t\t}\n\n\t\t// Computed unit is not pixels. Stop here and return.\n\t\tif ( rnumnonpx.test( val ) ) {\n\t\t\treturn val;\n\t\t}\n\n\t\t// Check for style in case a browser which returns unreliable values\n\t\t// for getComputedStyle silently falls back to the reliable elem.style\n\t\tvalueIsBorderBox = isBorderBox &&\n\t\t\t( support.boxSizingReliable() || val === elem.style[ name ] );\n\n\t\t// Normalize \"\", auto, and prepare for extra\n\t\tval = parseFloat( val ) || 0;\n\t}\n\n\t// Use the active box-sizing model to add/subtract irrelevant styles\n\treturn ( val +\n\t\taugmentWidthOrHeight(\n\t\t\telem,\n\t\t\tname,\n\t\t\textra || ( isBorderBox ? \"border\" : \"content\" ),\n\t\t\tvalueIsBorderBox,\n\t\t\tstyles\n\t\t)\n\t) + \"px\";\n}\n\njQuery.extend( {\n\n\t// Add in style property hooks for overriding the default\n\t// behavior of getting and setting a style property\n\tcssHooks: {\n\t\topacity: {\n\t\t\tget: function( elem, computed ) {\n\t\t\t\tif ( computed ) {\n\n\t\t\t\t\t// We should always get a number back from opacity\n\t\t\t\t\tvar ret = curCSS( elem, \"opacity\" );\n\t\t\t\t\treturn ret === \"\" ? \"1\" : ret;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Don't automatically add \"px\" to these possibly-unitless properties\n\tcssNumber: {\n\t\t\"animationIterationCount\": true,\n\t\t\"columnCount\": true,\n\t\t\"fillOpacity\": true,\n\t\t\"flexGrow\": true,\n\t\t\"flexShrink\": true,\n\t\t\"fontWeight\": true,\n\t\t\"lineHeight\": true,\n\t\t\"opacity\": true,\n\t\t\"order\": true,\n\t\t\"orphans\": true,\n\t\t\"widows\": true,\n\t\t\"zIndex\": true,\n\t\t\"zoom\": true\n\t},\n\n\t// Add in properties whose names you wish to fix before\n\t// setting or getting the value\n\tcssProps: {\n\t\t\"float\": \"cssFloat\"\n\t},\n\n\t// Get and set the style property on a DOM Node\n\tstyle: function( elem, name, value, extra ) {\n\n\t\t// Don't set styles on text and comment nodes\n\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Make sure that we're working with the right name\n\t\tvar ret, type, hooks,\n\t\t\torigName = jQuery.camelCase( name ),\n\t\t\tstyle = elem.style;\n\n\t\tname = jQuery.cssProps[ origName ] ||\n\t\t\t( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );\n\n\t\t// Gets hook for the prefixed version, then unprefixed version\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// Check if we're setting a value\n\t\tif ( value !== undefined ) {\n\t\t\ttype = typeof value;\n\n\t\t\t// Convert \"+=\" or \"-=\" to relative numbers (#7345)\n\t\t\tif ( type === \"string\" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {\n\t\t\t\tvalue = adjustCSS( elem, name, ret );\n\n\t\t\t\t// Fixes bug #9237\n\t\t\t\ttype = \"number\";\n\t\t\t}\n\n\t\t\t// Make sure that null and NaN values aren't set (#7116)\n\t\t\tif ( value == null || value !== value ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// If a number was passed in, add the unit (except for certain CSS properties)\n\t\t\tif ( type === \"number\" ) {\n\t\t\t\tvalue += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? \"\" : \"px\" );\n\t\t\t}\n\n\t\t\t// background-* props affect original clone's values\n\t\t\tif ( !support.clearCloneStyle && value === \"\" && name.indexOf( \"background\" ) === 0 ) {\n\t\t\t\tstyle[ name ] = \"inherit\";\n\t\t\t}\n\n\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n\t\t\tif ( !hooks || !( \"set\" in hooks ) ||\n\t\t\t\t( value = hooks.set( elem, value, extra ) ) !== undefined ) {\n\n\t\t\t\tstyle[ name ] = value;\n\t\t\t}\n\n\t\t} else {\n\n\t\t\t// If a hook was provided get the non-computed value from there\n\t\t\tif ( hooks && \"get\" in hooks &&\n\t\t\t\t( ret = hooks.get( elem, false, extra ) ) !== undefined ) {\n\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\t// Otherwise just get the value from the style object\n\t\t\treturn style[ name ];\n\t\t}\n\t},\n\n\tcss: function( elem, name, extra, styles ) {\n\t\tvar val, num, hooks,\n\t\t\torigName = jQuery.camelCase( name );\n\n\t\t// Make sure that we're working with the right name\n\t\tname = jQuery.cssProps[ origName ] ||\n\t\t\t( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );\n\n\t\t// Try prefixed name followed by the unprefixed name\n\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n\n\t\t// If a hook was provided get the computed value from there\n\t\tif ( hooks && \"get\" in hooks ) {\n\t\t\tval = hooks.get( elem, true, extra );\n\t\t}\n\n\t\t// Otherwise, if a way to get the computed value exists, use that\n\t\tif ( val === undefined ) {\n\t\t\tval = curCSS( elem, name, styles );\n\t\t}\n\n\t\t// Convert \"normal\" to computed value\n\t\tif ( val === \"normal\" && name in cssNormalTransform ) {\n\t\t\tval = cssNormalTransform[ name ];\n\t\t}\n\n\t\t// Make numeric if forced or a qualifier was provided and val looks numeric\n\t\tif ( extra === \"\" || extra ) {\n\t\t\tnum = parseFloat( val );\n\t\t\treturn extra === true || isFinite( num ) ? num || 0 : val;\n\t\t}\n\t\treturn val;\n\t}\n} );\n\njQuery.each( [ \"height\", \"width\" ], function( i, name ) {\n\tjQuery.cssHooks[ name ] = {\n\t\tget: function( elem, computed, extra ) {\n\t\t\tif ( computed ) {\n\n\t\t\t\t// Certain elements can have dimension info if we invisibly show them\n\t\t\t\t// but it must have a current display style that would benefit\n\t\t\t\treturn rdisplayswap.test( jQuery.css( elem, \"display\" ) ) &&\n\n\t\t\t\t\t// Support: Safari 8+\n\t\t\t\t\t// Table columns in Safari have non-zero offsetWidth & zero\n\t\t\t\t\t// getBoundingClientRect().width unless display is changed.\n\t\t\t\t\t// Support: IE <=11 only\n\t\t\t\t\t// Running getBoundingClientRect on a disconnected node\n\t\t\t\t\t// in IE throws an error.\n\t\t\t\t\t( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?\n\t\t\t\t\t\tswap( elem, cssShow, function() {\n\t\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n\t\t\t\t\t\t} ) :\n\t\t\t\t\t\tgetWidthOrHeight( elem, name, extra );\n\t\t\t}\n\t\t},\n\n\t\tset: function( elem, value, extra ) {\n\t\t\tvar matches,\n\t\t\t\tstyles = extra && getStyles( elem ),\n\t\t\t\tsubtract = extra && augmentWidthOrHeight(\n\t\t\t\t\telem,\n\t\t\t\t\tname,\n\t\t\t\t\textra,\n\t\t\t\t\tjQuery.css( elem, \"boxSizing\", false, styles ) === \"border-box\",\n\t\t\t\t\tstyles\n\t\t\t\t);\n\n\t\t\t// Convert to pixels if value adjustment is needed\n\t\t\tif ( subtract && ( matches = rcssNum.exec( value ) ) &&\n\t\t\t\t( matches[ 3 ] || \"px\" ) !== \"px\" ) {\n\n\t\t\t\telem.style[ name ] = value;\n\t\t\t\tvalue = jQuery.css( elem, name );\n\t\t\t}\n\n\t\t\treturn setPositiveNumber( elem, value, subtract );\n\t\t}\n\t};\n} );\n\njQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,\n\tfunction( elem, computed ) {\n\t\tif ( computed ) {\n\t\t\treturn ( parseFloat( curCSS( elem, \"marginLeft\" ) ) ||\n\t\t\t\telem.getBoundingClientRect().left -\n\t\t\t\t\tswap( elem, { marginLeft: 0 }, function() {\n\t\t\t\t\t\treturn elem.getBoundingClientRect().left;\n\t\t\t\t\t} )\n\t\t\t\t) + \"px\";\n\t\t}\n\t}\n);\n\n// These hooks are used by animate to expand properties\njQuery.each( {\n\tmargin: \"\",\n\tpadding: \"\",\n\tborder: \"Width\"\n}, function( prefix, suffix ) {\n\tjQuery.cssHooks[ prefix + suffix ] = {\n\t\texpand: function( value ) {\n\t\t\tvar i = 0,\n\t\t\t\texpanded = {},\n\n\t\t\t\t// Assumes a single number if not a string\n\t\t\t\tparts = typeof value === \"string\" ? value.split( \" \" ) : [ value ];\n\n\t\t\tfor ( ; i < 4; i++ ) {\n\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n\t\t\t}\n\n\t\t\treturn expanded;\n\t\t}\n\t};\n\n\tif ( !rmargin.test( prefix ) ) {\n\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n\t}\n} );\n\njQuery.fn.extend( {\n\tcss: function( name, value ) {\n\t\treturn access( this, function( elem, name, value ) {\n\t\t\tvar styles, len,\n\t\t\t\tmap = {},\n\t\t\t\ti = 0;\n\n\t\t\tif ( jQuery.isArray( name ) ) {\n\t\t\t\tstyles = getStyles( elem );\n\t\t\t\tlen = name.length;\n\n\t\t\t\tfor ( ; i < len; i++ ) {\n\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n\t\t\t\t}\n\n\t\t\t\treturn map;\n\t\t\t}\n\n\t\t\treturn value !== undefined ?\n\t\t\t\tjQuery.style( elem, name, value ) :\n\t\t\t\tjQuery.css( elem, name );\n\t\t}, name, value, arguments.length > 1 );\n\t}\n} );\n\n\nfunction Tween( elem, options, prop, end, easing ) {\n\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n}\njQuery.Tween = Tween;\n\nTween.prototype = {\n\tconstructor: Tween,\n\tinit: function( elem, options, prop, end, easing, unit ) {\n\t\tthis.elem = elem;\n\t\tthis.prop = prop;\n\t\tthis.easing = easing || jQuery.easing._default;\n\t\tthis.options = options;\n\t\tthis.start = this.now = this.cur();\n\t\tthis.end = end;\n\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? \"\" : \"px\" );\n\t},\n\tcur: function() {\n\t\tvar hooks = Tween.propHooks[ this.prop ];\n\n\t\treturn hooks && hooks.get ?\n\t\t\thooks.get( this ) :\n\t\t\tTween.propHooks._default.get( this );\n\t},\n\trun: function( percent ) {\n\t\tvar eased,\n\t\t\thooks = Tween.propHooks[ this.prop ];\n\n\t\tif ( this.options.duration ) {\n\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n\t\t\t);\n\t\t} else {\n\t\t\tthis.pos = eased = percent;\n\t\t}\n\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n\n\t\tif ( this.options.step ) {\n\t\t\tthis.options.step.call( this.elem, this.now, this );\n\t\t}\n\n\t\tif ( hooks && hooks.set ) {\n\t\t\thooks.set( this );\n\t\t} else {\n\t\t\tTween.propHooks._default.set( this );\n\t\t}\n\t\treturn this;\n\t}\n};\n\nTween.prototype.init.prototype = Tween.prototype;\n\nTween.propHooks = {\n\t_default: {\n\t\tget: function( tween ) {\n\t\t\tvar result;\n\n\t\t\t// Use a property on the element directly when it is not a DOM element,\n\t\t\t// or when there is no matching style property that exists.\n\t\t\tif ( tween.elem.nodeType !== 1 ||\n\t\t\t\ttween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {\n\t\t\t\treturn tween.elem[ tween.prop ];\n\t\t\t}\n\n\t\t\t// Passing an empty string as a 3rd parameter to .css will automatically\n\t\t\t// attempt a parseFloat and fallback to a string if the parse fails.\n\t\t\t// Simple values such as \"10px\" are parsed to Float;\n\t\t\t// complex values such as \"rotate(1rad)\" are returned as-is.\n\t\t\tresult = jQuery.css( tween.elem, tween.prop, \"\" );\n\n\t\t\t// Empty strings, null, undefined and \"auto\" are converted to 0.\n\t\t\treturn !result || result === \"auto\" ? 0 : result;\n\t\t},\n\t\tset: function( tween ) {\n\n\t\t\t// Use step hook for back compat.\n\t\t\t// Use cssHook if its there.\n\t\t\t// Use .style if available and use plain properties where available.\n\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n\t\t\t} else if ( tween.elem.nodeType === 1 &&\n\t\t\t\t( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||\n\t\t\t\t\tjQuery.cssHooks[ tween.prop ] ) ) {\n\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n\t\t\t} else {\n\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t\t}\n\t\t}\n\t}\n};\n\n// Support: IE <=9 only\n// Panic based approach to setting things on disconnected nodes\nTween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n\tset: function( tween ) {\n\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n\t\t\ttween.elem[ tween.prop ] = tween.now;\n\t\t}\n\t}\n};\n\njQuery.easing = {\n\tlinear: function( p ) {\n\t\treturn p;\n\t},\n\tswing: function( p ) {\n\t\treturn 0.5 - Math.cos( p * Math.PI ) / 2;\n\t},\n\t_default: \"swing\"\n};\n\njQuery.fx = Tween.prototype.init;\n\n// Back compat <1.8 extension point\njQuery.fx.step = {};\n\n\n\n\nvar\n\tfxNow, timerId,\n\trfxtypes = /^(?:toggle|show|hide)$/,\n\trrun = /queueHooks$/;\n\nfunction raf() {\n\tif ( timerId ) {\n\t\twindow.requestAnimationFrame( raf );\n\t\tjQuery.fx.tick();\n\t}\n}\n\n// Animations created synchronously will run synchronously\nfunction createFxNow() {\n\twindow.setTimeout( function() {\n\t\tfxNow = undefined;\n\t} );\n\treturn ( fxNow = jQuery.now() );\n}\n\n// Generate parameters to create a standard animation\nfunction genFx( type, includeWidth ) {\n\tvar which,\n\t\ti = 0,\n\t\tattrs = { height: type };\n\n\t// If we include width, step value is 1 to do all cssExpand values,\n\t// otherwise step value is 2 to skip over Left and Right\n\tincludeWidth = includeWidth ? 1 : 0;\n\tfor ( ; i < 4; i += 2 - includeWidth ) {\n\t\twhich = cssExpand[ i ];\n\t\tattrs[ \"margin\" + which ] = attrs[ \"padding\" + which ] = type;\n\t}\n\n\tif ( includeWidth ) {\n\t\tattrs.opacity = attrs.width = type;\n\t}\n\n\treturn attrs;\n}\n\nfunction createTween( value, prop, animation ) {\n\tvar tween,\n\t\tcollection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ \"*\" ] ),\n\t\tindex = 0,\n\t\tlength = collection.length;\n\tfor ( ; index < length; index++ ) {\n\t\tif ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {\n\n\t\t\t// We're done with this property\n\t\t\treturn tween;\n\t\t}\n\t}\n}\n\nfunction defaultPrefilter( elem, props, opts ) {\n\tvar prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,\n\t\tisBox = \"width\" in props || \"height\" in props,\n\t\tanim = this,\n\t\torig = {},\n\t\tstyle = elem.style,\n\t\thidden = elem.nodeType && isHiddenWithinTree( elem ),\n\t\tdataShow = dataPriv.get( elem, \"fxshow\" );\n\n\t// Queue-skipping animations hijack the fx hooks\n\tif ( !opts.queue ) {\n\t\thooks = jQuery._queueHooks( elem, \"fx\" );\n\t\tif ( hooks.unqueued == null ) {\n\t\t\thooks.unqueued = 0;\n\t\t\toldfire = hooks.empty.fire;\n\t\t\thooks.empty.fire = function() {\n\t\t\t\tif ( !hooks.unqueued ) {\n\t\t\t\t\toldfire();\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\t\thooks.unqueued++;\n\n\t\tanim.always( function() {\n\n\t\t\t// Ensure the complete handler is called before this completes\n\t\t\tanim.always( function() {\n\t\t\t\thooks.unqueued--;\n\t\t\t\tif ( !jQuery.queue( elem, \"fx\" ).length ) {\n\t\t\t\t\thooks.empty.fire();\n\t\t\t\t}\n\t\t\t} );\n\t\t} );\n\t}\n\n\t// Detect show/hide animations\n\tfor ( prop in props ) {\n\t\tvalue = props[ prop ];\n\t\tif ( rfxtypes.test( value ) ) {\n\t\t\tdelete props[ prop ];\n\t\t\ttoggle = toggle || value === \"toggle\";\n\t\t\tif ( value === ( hidden ? \"hide\" : \"show\" ) ) {\n\n\t\t\t\t// Pretend to be hidden if this is a \"show\" and\n\t\t\t\t// there is still data from a stopped show/hide\n\t\t\t\tif ( value === \"show\" && dataShow && dataShow[ prop ] !== undefined ) {\n\t\t\t\t\thidden = true;\n\n\t\t\t\t// Ignore all other no-op show/hide data\n\t\t\t\t} else {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n\t\t}\n\t}\n\n\t// Bail out if this is a no-op like .hide().hide()\n\tpropTween = !jQuery.isEmptyObject( props );\n\tif ( !propTween && jQuery.isEmptyObject( orig ) ) {\n\t\treturn;\n\t}\n\n\t// Restrict \"overflow\" and \"display\" styles during box animations\n\tif ( isBox && elem.nodeType === 1 ) {\n\n\t\t// Support: IE <=9 - 11, Edge 12 - 13\n\t\t// Record all 3 overflow attributes because IE does not infer the shorthand\n\t\t// from identically-valued overflowX and overflowY\n\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n\n\t\t// Identify a display type, preferring old show/hide data over the CSS cascade\n\t\trestoreDisplay = dataShow && dataShow.display;\n\t\tif ( restoreDisplay == null ) {\n\t\t\trestoreDisplay = dataPriv.get( elem, \"display\" );\n\t\t}\n\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\tif ( display === \"none\" ) {\n\t\t\tif ( restoreDisplay ) {\n\t\t\t\tdisplay = restoreDisplay;\n\t\t\t} else {\n\n\t\t\t\t// Get nonempty value(s) by temporarily forcing visibility\n\t\t\t\tshowHide( [ elem ], true );\n\t\t\t\trestoreDisplay = elem.style.display || restoreDisplay;\n\t\t\t\tdisplay = jQuery.css( elem, \"display\" );\n\t\t\t\tshowHide( [ elem ] );\n\t\t\t}\n\t\t}\n\n\t\t// Animate inline elements as inline-block\n\t\tif ( display === \"inline\" || display === \"inline-block\" && restoreDisplay != null ) {\n\t\t\tif ( jQuery.css( elem, \"float\" ) === \"none\" ) {\n\n\t\t\t\t// Restore the original display value at the end of pure show/hide animations\n\t\t\t\tif ( !propTween ) {\n\t\t\t\t\tanim.done( function() {\n\t\t\t\t\t\tstyle.display = restoreDisplay;\n\t\t\t\t\t} );\n\t\t\t\t\tif ( restoreDisplay == null ) {\n\t\t\t\t\t\tdisplay = style.display;\n\t\t\t\t\t\trestoreDisplay = display === \"none\" ? \"\" : display;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tstyle.display = \"inline-block\";\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( opts.overflow ) {\n\t\tstyle.overflow = \"hidden\";\n\t\tanim.always( function() {\n\t\t\tstyle.overflow = opts.overflow[ 0 ];\n\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n\t\t} );\n\t}\n\n\t// Implement show/hide animations\n\tpropTween = false;\n\tfor ( prop in orig ) {\n\n\t\t// General show/hide setup for this element animation\n\t\tif ( !propTween ) {\n\t\t\tif ( dataShow ) {\n\t\t\t\tif ( \"hidden\" in dataShow ) {\n\t\t\t\t\thidden = dataShow.hidden;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tdataShow = dataPriv.access( elem, \"fxshow\", { display: restoreDisplay } );\n\t\t\t}\n\n\t\t\t// Store hidden/visible for toggle so `.stop().toggle()` \"reverses\"\n\t\t\tif ( toggle ) {\n\t\t\t\tdataShow.hidden = !hidden;\n\t\t\t}\n\n\t\t\t// Show elements before animating them\n\t\t\tif ( hidden ) {\n\t\t\t\tshowHide( [ elem ], true );\n\t\t\t}\n\n\t\t\t/* eslint-disable no-loop-func */\n\n\t\t\tanim.done( function() {\n\n\t\t\t/* eslint-enable no-loop-func */\n\n\t\t\t\t// The final step of a \"hide\" animation is actually hiding the element\n\t\t\t\tif ( !hidden ) {\n\t\t\t\t\tshowHide( [ elem ] );\n\t\t\t\t}\n\t\t\t\tdataPriv.remove( elem, \"fxshow\" );\n\t\t\t\tfor ( prop in orig ) {\n\t\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\n\t\t// Per-property setup\n\t\tpropTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n\t\tif ( !( prop in dataShow ) ) {\n\t\t\tdataShow[ prop ] = propTween.start;\n\t\t\tif ( hidden ) {\n\t\t\t\tpropTween.end = propTween.start;\n\t\t\t\tpropTween.start = 0;\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction propFilter( props, specialEasing ) {\n\tvar index, name, easing, value, hooks;\n\n\t// camelCase, specialEasing and expand cssHook pass\n\tfor ( index in props ) {\n\t\tname = jQuery.camelCase( index );\n\t\teasing = specialEasing[ name ];\n\t\tvalue = props[ index ];\n\t\tif ( jQuery.isArray( value ) ) {\n\t\t\teasing = value[ 1 ];\n\t\t\tvalue = props[ index ] = value[ 0 ];\n\t\t}\n\n\t\tif ( index !== name ) {\n\t\t\tprops[ name ] = value;\n\t\t\tdelete props[ index ];\n\t\t}\n\n\t\thooks = jQuery.cssHooks[ name ];\n\t\tif ( hooks && \"expand\" in hooks ) {\n\t\t\tvalue = hooks.expand( value );\n\t\t\tdelete props[ name ];\n\n\t\t\t// Not quite $.extend, this won't overwrite existing keys.\n\t\t\t// Reusing 'index' because we have the correct \"name\"\n\t\t\tfor ( index in value ) {\n\t\t\t\tif ( !( index in props ) ) {\n\t\t\t\t\tprops[ index ] = value[ index ];\n\t\t\t\t\tspecialEasing[ index ] = easing;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tspecialEasing[ name ] = easing;\n\t\t}\n\t}\n}\n\nfunction Animation( elem, properties, options ) {\n\tvar result,\n\t\tstopped,\n\t\tindex = 0,\n\t\tlength = Animation.prefilters.length,\n\t\tdeferred = jQuery.Deferred().always( function() {\n\n\t\t\t// Don't match elem in the :animated selector\n\t\t\tdelete tick.elem;\n\t\t} ),\n\t\ttick = function() {\n\t\t\tif ( stopped ) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tvar currentTime = fxNow || createFxNow(),\n\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n\n\t\t\t\t// Support: Android 2.3 only\n\t\t\t\t// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)\n\t\t\t\ttemp = remaining / animation.duration || 0,\n\t\t\t\tpercent = 1 - temp,\n\t\t\t\tindex = 0,\n\t\t\t\tlength = animation.tweens.length;\n\n\t\t\tfor ( ; index < length; index++ ) {\n\t\t\t\tanimation.tweens[ index ].run( percent );\n\t\t\t}\n\n\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ] );\n\n\t\t\tif ( percent < 1 && length ) {\n\t\t\t\treturn remaining;\n\t\t\t} else {\n\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n\t\t\t\treturn false;\n\t\t\t}\n\t\t},\n\t\tanimation = deferred.promise( {\n\t\t\telem: elem,\n\t\t\tprops: jQuery.extend( {}, properties ),\n\t\t\topts: jQuery.extend( true, {\n\t\t\t\tspecialEasing: {},\n\t\t\t\teasing: jQuery.easing._default\n\t\t\t}, options ),\n\t\t\toriginalProperties: properties,\n\t\t\toriginalOptions: options,\n\t\t\tstartTime: fxNow || createFxNow(),\n\t\t\tduration: options.duration,\n\t\t\ttweens: [],\n\t\t\tcreateTween: function( prop, end ) {\n\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n\t\t\t\tanimation.tweens.push( tween );\n\t\t\t\treturn tween;\n\t\t\t},\n\t\t\tstop: function( gotoEnd ) {\n\t\t\t\tvar index = 0,\n\n\t\t\t\t\t// If we are going to the end, we want to run all the tweens\n\t\t\t\t\t// otherwise we skip this part\n\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n\t\t\t\tif ( stopped ) {\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t\tstopped = true;\n\t\t\t\tfor ( ; index < length; index++ ) {\n\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n\t\t\t\t}\n\n\t\t\t\t// Resolve when we played the last frame; otherwise, reject\n\t\t\t\tif ( gotoEnd ) {\n\t\t\t\t\tdeferred.notifyWith( elem, [ animation, 1, 0 ] );\n\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n\t\t\t\t}\n\t\t\t\treturn this;\n\t\t\t}\n\t\t} ),\n\t\tprops = animation.props;\n\n\tpropFilter( props, animation.opts.specialEasing );\n\n\tfor ( ; index < length; index++ ) {\n\t\tresult = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );\n\t\tif ( result ) {\n\t\t\tif ( jQuery.isFunction( result.stop ) ) {\n\t\t\t\tjQuery._queueHooks( animation.elem, animation.opts.queue ).stop =\n\t\t\t\t\tjQuery.proxy( result.stop, result );\n\t\t\t}\n\t\t\treturn result;\n\t\t}\n\t}\n\n\tjQuery.map( props, createTween, animation );\n\n\tif ( jQuery.isFunction( animation.opts.start ) ) {\n\t\tanimation.opts.start.call( elem, animation );\n\t}\n\n\tjQuery.fx.timer(\n\t\tjQuery.extend( tick, {\n\t\t\telem: elem,\n\t\t\tanim: animation,\n\t\t\tqueue: animation.opts.queue\n\t\t} )\n\t);\n\n\t// attach callbacks from options\n\treturn animation.progress( animation.opts.progress )\n\t\t.done( animation.opts.done, animation.opts.complete )\n\t\t.fail( animation.opts.fail )\n\t\t.always( animation.opts.always );\n}\n\njQuery.Animation = jQuery.extend( Animation, {\n\n\ttweeners: {\n\t\t\"*\": [ function( prop, value ) {\n\t\t\tvar tween = this.createTween( prop, value );\n\t\t\tadjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );\n\t\t\treturn tween;\n\t\t} ]\n\t},\n\n\ttweener: function( props, callback ) {\n\t\tif ( jQuery.isFunction( props ) ) {\n\t\t\tcallback = props;\n\t\t\tprops = [ \"*\" ];\n\t\t} else {\n\t\t\tprops = props.match( rnothtmlwhite );\n\t\t}\n\n\t\tvar prop,\n\t\t\tindex = 0,\n\t\t\tlength = props.length;\n\n\t\tfor ( ; index < length; index++ ) {\n\t\t\tprop = props[ index ];\n\t\t\tAnimation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];\n\t\t\tAnimation.tweeners[ prop ].unshift( callback );\n\t\t}\n\t},\n\n\tprefilters: [ defaultPrefilter ],\n\n\tprefilter: function( callback, prepend ) {\n\t\tif ( prepend ) {\n\t\t\tAnimation.prefilters.unshift( callback );\n\t\t} else {\n\t\t\tAnimation.prefilters.push( callback );\n\t\t}\n\t}\n} );\n\njQuery.speed = function( speed, easing, fn ) {\n\tvar opt = speed && typeof speed === \"object\" ? jQuery.extend( {}, speed ) : {\n\t\tcomplete: fn || !fn && easing ||\n\t\t\tjQuery.isFunction( speed ) && speed,\n\t\tduration: speed,\n\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n\t};\n\n\t// Go to the end state if fx are off or if document is hidden\n\tif ( jQuery.fx.off || document.hidden ) {\n\t\topt.duration = 0;\n\n\t} else {\n\t\tif ( typeof opt.duration !== \"number\" ) {\n\t\t\tif ( opt.duration in jQuery.fx.speeds ) {\n\t\t\t\topt.duration = jQuery.fx.speeds[ opt.duration ];\n\n\t\t\t} else {\n\t\t\t\topt.duration = jQuery.fx.speeds._default;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Normalize opt.queue - true/undefined/null -> \"fx\"\n\tif ( opt.queue == null || opt.queue === true ) {\n\t\topt.queue = \"fx\";\n\t}\n\n\t// Queueing\n\topt.old = opt.complete;\n\n\topt.complete = function() {\n\t\tif ( jQuery.isFunction( opt.old ) ) {\n\t\t\topt.old.call( this );\n\t\t}\n\n\t\tif ( opt.queue ) {\n\t\t\tjQuery.dequeue( this, opt.queue );\n\t\t}\n\t};\n\n\treturn opt;\n};\n\njQuery.fn.extend( {\n\tfadeTo: function( speed, to, easing, callback ) {\n\n\t\t// Show any hidden elements after setting opacity to 0\n\t\treturn this.filter( isHiddenWithinTree ).css( \"opacity\", 0 ).show()\n\n\t\t\t// Animate to the value specified\n\t\t\t.end().animate( { opacity: to }, speed, easing, callback );\n\t},\n\tanimate: function( prop, speed, easing, callback ) {\n\t\tvar empty = jQuery.isEmptyObject( prop ),\n\t\t\toptall = jQuery.speed( speed, easing, callback ),\n\t\t\tdoAnimation = function() {\n\n\t\t\t\t// Operate on a copy of prop so per-property easing won't be lost\n\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n\n\t\t\t\t// Empty animations, or finishing resolves immediately\n\t\t\t\tif ( empty || dataPriv.get( this, \"finish\" ) ) {\n\t\t\t\t\tanim.stop( true );\n\t\t\t\t}\n\t\t\t};\n\t\t\tdoAnimation.finish = doAnimation;\n\n\t\treturn empty || optall.queue === false ?\n\t\t\tthis.each( doAnimation ) :\n\t\t\tthis.queue( optall.queue, doAnimation );\n\t},\n\tstop: function( type, clearQueue, gotoEnd ) {\n\t\tvar stopQueue = function( hooks ) {\n\t\t\tvar stop = hooks.stop;\n\t\t\tdelete hooks.stop;\n\t\t\tstop( gotoEnd );\n\t\t};\n\n\t\tif ( typeof type !== \"string\" ) {\n\t\t\tgotoEnd = clearQueue;\n\t\t\tclearQueue = type;\n\t\t\ttype = undefined;\n\t\t}\n\t\tif ( clearQueue && type !== false ) {\n\t\t\tthis.queue( type || \"fx\", [] );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar dequeue = true,\n\t\t\t\tindex = type != null && type + \"queueHooks\",\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tdata = dataPriv.get( this );\n\n\t\t\tif ( index ) {\n\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tfor ( index in data ) {\n\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n\t\t\t\t\t\tstopQueue( data[ index ] );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this &&\n\t\t\t\t\t( type == null || timers[ index ].queue === type ) ) {\n\n\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n\t\t\t\t\tdequeue = false;\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Start the next in the queue if the last step wasn't forced.\n\t\t\t// Timers currently will call their complete callbacks, which\n\t\t\t// will dequeue but only if they were gotoEnd.\n\t\t\tif ( dequeue || !gotoEnd ) {\n\t\t\t\tjQuery.dequeue( this, type );\n\t\t\t}\n\t\t} );\n\t},\n\tfinish: function( type ) {\n\t\tif ( type !== false ) {\n\t\t\ttype = type || \"fx\";\n\t\t}\n\t\treturn this.each( function() {\n\t\t\tvar index,\n\t\t\t\tdata = dataPriv.get( this ),\n\t\t\t\tqueue = data[ type + \"queue\" ],\n\t\t\t\thooks = data[ type + \"queueHooks\" ],\n\t\t\t\ttimers = jQuery.timers,\n\t\t\t\tlength = queue ? queue.length : 0;\n\n\t\t\t// Enable finishing flag on private data\n\t\t\tdata.finish = true;\n\n\t\t\t// Empty the queue first\n\t\t\tjQuery.queue( this, type, [] );\n\n\t\t\tif ( hooks && hooks.stop ) {\n\t\t\t\thooks.stop.call( this, true );\n\t\t\t}\n\n\t\t\t// Look for any active animations, and finish them\n\t\t\tfor ( index = timers.length; index--; ) {\n\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n\t\t\t\t\ttimers[ index ].anim.stop( true );\n\t\t\t\t\ttimers.splice( index, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Look for any animations in the old queue and finish them\n\t\t\tfor ( index = 0; index < length; index++ ) {\n\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n\t\t\t\t\tqueue[ index ].finish.call( this );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Turn off finishing flag\n\t\t\tdelete data.finish;\n\t\t} );\n\t}\n} );\n\njQuery.each( [ \"toggle\", \"show\", \"hide\" ], function( i, name ) {\n\tvar cssFn = jQuery.fn[ name ];\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn speed == null || typeof speed === \"boolean\" ?\n\t\t\tcssFn.apply( this, arguments ) :\n\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n\t};\n} );\n\n// Generate shortcuts for custom animations\njQuery.each( {\n\tslideDown: genFx( \"show\" ),\n\tslideUp: genFx( \"hide\" ),\n\tslideToggle: genFx( \"toggle\" ),\n\tfadeIn: { opacity: \"show\" },\n\tfadeOut: { opacity: \"hide\" },\n\tfadeToggle: { opacity: \"toggle\" }\n}, function( name, props ) {\n\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n\t\treturn this.animate( props, speed, easing, callback );\n\t};\n} );\n\njQuery.timers = [];\njQuery.fx.tick = function() {\n\tvar timer,\n\t\ti = 0,\n\t\ttimers = jQuery.timers;\n\n\tfxNow = jQuery.now();\n\n\tfor ( ; i < timers.length; i++ ) {\n\t\ttimer = timers[ i ];\n\n\t\t// Checks the timer has not already been removed\n\t\tif ( !timer() && timers[ i ] === timer ) {\n\t\t\ttimers.splice( i--, 1 );\n\t\t}\n\t}\n\n\tif ( !timers.length ) {\n\t\tjQuery.fx.stop();\n\t}\n\tfxNow = undefined;\n};\n\njQuery.fx.timer = function( timer ) {\n\tjQuery.timers.push( timer );\n\tif ( timer() ) {\n\t\tjQuery.fx.start();\n\t} else {\n\t\tjQuery.timers.pop();\n\t}\n};\n\njQuery.fx.interval = 13;\njQuery.fx.start = function() {\n\tif ( !timerId ) {\n\t\ttimerId = window.requestAnimationFrame ?\n\t\t\twindow.requestAnimationFrame( raf ) :\n\t\t\twindow.setInterval( jQuery.fx.tick, jQuery.fx.interval );\n\t}\n};\n\njQuery.fx.stop = function() {\n\tif ( window.cancelAnimationFrame ) {\n\t\twindow.cancelAnimationFrame( timerId );\n\t} else {\n\t\twindow.clearInterval( timerId );\n\t}\n\n\ttimerId = null;\n};\n\njQuery.fx.speeds = {\n\tslow: 600,\n\tfast: 200,\n\n\t// Default speed\n\t_default: 400\n};\n\n\n// Based off of the plugin by Clint Helfers, with permission.\n// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/\njQuery.fn.delay = function( time, type ) {\n\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n\ttype = type || \"fx\";\n\n\treturn this.queue( type, function( next, hooks ) {\n\t\tvar timeout = window.setTimeout( next, time );\n\t\thooks.stop = function() {\n\t\t\twindow.clearTimeout( timeout );\n\t\t};\n\t} );\n};\n\n\n( function() {\n\tvar input = document.createElement( \"input\" ),\n\t\tselect = document.createElement( \"select\" ),\n\t\topt = select.appendChild( document.createElement( \"option\" ) );\n\n\tinput.type = \"checkbox\";\n\n\t// Support: Android <=4.3 only\n\t// Default value for a checkbox should be \"on\"\n\tsupport.checkOn = input.value !== \"\";\n\n\t// Support: IE <=11 only\n\t// Must access selectedIndex to make default options select\n\tsupport.optSelected = opt.selected;\n\n\t// Support: IE <=11 only\n\t// An input loses its value after becoming a radio\n\tinput = document.createElement( \"input\" );\n\tinput.value = \"t\";\n\tinput.type = \"radio\";\n\tsupport.radioValue = input.value === \"t\";\n} )();\n\n\nvar boolHook,\n\tattrHandle = jQuery.expr.attrHandle;\n\njQuery.fn.extend( {\n\tattr: function( name, value ) {\n\t\treturn access( this, jQuery.attr, name, value, arguments.length > 1 );\n\t},\n\n\tremoveAttr: function( name ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.removeAttr( this, name );\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tattr: function( elem, name, value ) {\n\t\tvar ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set attributes on text, comment and attribute nodes\n\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Fallback to prop when attributes are not supported\n\t\tif ( typeof elem.getAttribute === \"undefined\" ) {\n\t\t\treturn jQuery.prop( elem, name, value );\n\t\t}\n\n\t\t// Attribute hooks are determined by the lowercase version\n\t\t// Grab necessary hook if one is defined\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\t\t\thooks = jQuery.attrHooks[ name.toLowerCase() ] ||\n\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( value === null ) {\n\t\t\t\tjQuery.removeAttr( elem, name );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\telem.setAttribute( name, value + \"\" );\n\t\t\treturn value;\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\tret = jQuery.find.attr( elem, name );\n\n\t\t// Non-existent attributes return null, we normalize to undefined\n\t\treturn ret == null ? undefined : ret;\n\t},\n\n\tattrHooks: {\n\t\ttype: {\n\t\t\tset: function( elem, value ) {\n\t\t\t\tif ( !support.radioValue && value === \"radio\" &&\n\t\t\t\t\tjQuery.nodeName( elem, \"input\" ) ) {\n\t\t\t\t\tvar val = elem.value;\n\t\t\t\t\telem.setAttribute( \"type\", value );\n\t\t\t\t\tif ( val ) {\n\t\t\t\t\t\telem.value = val;\n\t\t\t\t\t}\n\t\t\t\t\treturn value;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tremoveAttr: function( elem, value ) {\n\t\tvar name,\n\t\t\ti = 0,\n\n\t\t\t// Attribute names can contain non-HTML whitespace characters\n\t\t\t// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2\n\t\t\tattrNames = value && value.match( rnothtmlwhite );\n\n\t\tif ( attrNames && elem.nodeType === 1 ) {\n\t\t\twhile ( ( name = attrNames[ i++ ] ) ) {\n\t\t\t\telem.removeAttribute( name );\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Hooks for boolean attributes\nboolHook = {\n\tset: function( elem, value, name ) {\n\t\tif ( value === false ) {\n\n\t\t\t// Remove boolean attributes when set to false\n\t\t\tjQuery.removeAttr( elem, name );\n\t\t} else {\n\t\t\telem.setAttribute( name, name );\n\t\t}\n\t\treturn name;\n\t}\n};\n\njQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n\tvar getter = attrHandle[ name ] || jQuery.find.attr;\n\n\tattrHandle[ name ] = function( elem, name, isXML ) {\n\t\tvar ret, handle,\n\t\t\tlowercaseName = name.toLowerCase();\n\n\t\tif ( !isXML ) {\n\n\t\t\t// Avoid an infinite loop by temporarily removing this function from the getter\n\t\t\thandle = attrHandle[ lowercaseName ];\n\t\t\tattrHandle[ lowercaseName ] = ret;\n\t\t\tret = getter( elem, name, isXML ) != null ?\n\t\t\t\tlowercaseName :\n\t\t\t\tnull;\n\t\t\tattrHandle[ lowercaseName ] = handle;\n\t\t}\n\t\treturn ret;\n\t};\n} );\n\n\n\n\nvar rfocusable = /^(?:input|select|textarea|button)$/i,\n\trclickable = /^(?:a|area)$/i;\n\njQuery.fn.extend( {\n\tprop: function( name, value ) {\n\t\treturn access( this, jQuery.prop, name, value, arguments.length > 1 );\n\t},\n\n\tremoveProp: function( name ) {\n\t\treturn this.each( function() {\n\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tprop: function( elem, name, value ) {\n\t\tvar ret, hooks,\n\t\t\tnType = elem.nodeType;\n\n\t\t// Don't get/set properties on text, comment and attribute nodes\n\t\tif ( nType === 3 || nType === 8 || nType === 2 ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n\n\t\t\t// Fix name and attach hooks\n\t\t\tname = jQuery.propFix[ name ] || name;\n\t\t\thooks = jQuery.propHooks[ name ];\n\t\t}\n\n\t\tif ( value !== undefined ) {\n\t\t\tif ( hooks && \"set\" in hooks &&\n\t\t\t\t( ret = hooks.set( elem, value, name ) ) !== undefined ) {\n\t\t\t\treturn ret;\n\t\t\t}\n\n\t\t\treturn ( elem[ name ] = value );\n\t\t}\n\n\t\tif ( hooks && \"get\" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {\n\t\t\treturn ret;\n\t\t}\n\n\t\treturn elem[ name ];\n\t},\n\n\tpropHooks: {\n\t\ttabIndex: {\n\t\t\tget: function( elem ) {\n\n\t\t\t\t// Support: IE <=9 - 11 only\n\t\t\t\t// elem.tabIndex doesn't always return the\n\t\t\t\t// correct value when it hasn't been explicitly set\n\t\t\t\t// https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/\n\t\t\t\t// Use proper attribute retrieval(#12072)\n\t\t\t\tvar tabindex = jQuery.find.attr( elem, \"tabindex\" );\n\n\t\t\t\tif ( tabindex ) {\n\t\t\t\t\treturn parseInt( tabindex, 10 );\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\trfocusable.test( elem.nodeName ) ||\n\t\t\t\t\trclickable.test( elem.nodeName ) &&\n\t\t\t\t\telem.href\n\t\t\t\t) {\n\t\t\t\t\treturn 0;\n\t\t\t\t}\n\n\t\t\t\treturn -1;\n\t\t\t}\n\t\t}\n\t},\n\n\tpropFix: {\n\t\t\"for\": \"htmlFor\",\n\t\t\"class\": \"className\"\n\t}\n} );\n\n// Support: IE <=11 only\n// Accessing the selectedIndex property\n// forces the browser to respect setting selected\n// on the option\n// The getter ensures a default option is selected\n// when in an optgroup\n// eslint rule \"no-unused-expressions\" is disabled for this code\n// since it considers such accessions noop\nif ( !support.optSelected ) {\n\tjQuery.propHooks.selected = {\n\t\tget: function( elem ) {\n\n\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent && parent.parentNode ) {\n\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t}\n\t\t\treturn null;\n\t\t},\n\t\tset: function( elem ) {\n\n\t\t\t/* eslint no-unused-expressions: \"off\" */\n\n\t\t\tvar parent = elem.parentNode;\n\t\t\tif ( parent ) {\n\t\t\t\tparent.selectedIndex;\n\n\t\t\t\tif ( parent.parentNode ) {\n\t\t\t\t\tparent.parentNode.selectedIndex;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\njQuery.each( [\n\t\"tabIndex\",\n\t\"readOnly\",\n\t\"maxLength\",\n\t\"cellSpacing\",\n\t\"cellPadding\",\n\t\"rowSpan\",\n\t\"colSpan\",\n\t\"useMap\",\n\t\"frameBorder\",\n\t\"contentEditable\"\n], function() {\n\tjQuery.propFix[ this.toLowerCase() ] = this;\n} );\n\n\n\n\n\t// Strip and collapse whitespace according to HTML spec\n\t// https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace\n\tfunction stripAndCollapse( value ) {\n\t\tvar tokens = value.match( rnothtmlwhite ) || [];\n\t\treturn tokens.join( \" \" );\n\t}\n\n\nfunction getClass( elem ) {\n\treturn elem.getAttribute && elem.getAttribute( \"class\" ) || \"\";\n}\n\njQuery.fn.extend( {\n\taddClass: function( value ) {\n\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each( function( j ) {\n\t\t\t\tjQuery( this ).addClass( value.call( this, j, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tif ( typeof value === \"string\" && value ) {\n\t\t\tclasses = value.match( rnothtmlwhite ) || [];\n\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\t\t\t\t\t\tif ( cur.indexOf( \" \" + clazz + \" \" ) < 0 ) {\n\t\t\t\t\t\t\tcur += clazz + \" \";\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\tremoveClass: function( value ) {\n\t\tvar classes, elem, cur, curValue, clazz, j, finalValue,\n\t\t\ti = 0;\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each( function( j ) {\n\t\t\t\tjQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );\n\t\t\t} );\n\t\t}\n\n\t\tif ( !arguments.length ) {\n\t\t\treturn this.attr( \"class\", \"\" );\n\t\t}\n\n\t\tif ( typeof value === \"string\" && value ) {\n\t\t\tclasses = value.match( rnothtmlwhite ) || [];\n\n\t\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\t\tcurValue = getClass( elem );\n\n\t\t\t\t// This expression is here for better compressibility (see addClass)\n\t\t\t\tcur = elem.nodeType === 1 && ( \" \" + stripAndCollapse( curValue ) + \" \" );\n\n\t\t\t\tif ( cur ) {\n\t\t\t\t\tj = 0;\n\t\t\t\t\twhile ( ( clazz = classes[ j++ ] ) ) {\n\n\t\t\t\t\t\t// Remove *all* instances\n\t\t\t\t\t\twhile ( cur.indexOf( \" \" + clazz + \" \" ) > -1 ) {\n\t\t\t\t\t\t\tcur = cur.replace( \" \" + clazz + \" \", \" \" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Only assign if different to avoid unneeded rendering.\n\t\t\t\t\tfinalValue = stripAndCollapse( cur );\n\t\t\t\t\tif ( curValue !== finalValue ) {\n\t\t\t\t\t\telem.setAttribute( \"class\", finalValue );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn this;\n\t},\n\n\ttoggleClass: function( value, stateVal ) {\n\t\tvar type = typeof value;\n\n\t\tif ( typeof stateVal === \"boolean\" && type === \"string\" ) {\n\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n\t\t}\n\n\t\tif ( jQuery.isFunction( value ) ) {\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).toggleClass(\n\t\t\t\t\tvalue.call( this, i, getClass( this ), stateVal ),\n\t\t\t\t\tstateVal\n\t\t\t\t);\n\t\t\t} );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar className, i, self, classNames;\n\n\t\t\tif ( type === \"string\" ) {\n\n\t\t\t\t// Toggle individual class names\n\t\t\t\ti = 0;\n\t\t\t\tself = jQuery( this );\n\t\t\t\tclassNames = value.match( rnothtmlwhite ) || [];\n\n\t\t\t\twhile ( ( className = classNames[ i++ ] ) ) {\n\n\t\t\t\t\t// Check each className given, space separated list\n\t\t\t\t\tif ( self.hasClass( className ) ) {\n\t\t\t\t\t\tself.removeClass( className );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tself.addClass( className );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Toggle whole class name\n\t\t\t} else if ( value === undefined || type === \"boolean\" ) {\n\t\t\t\tclassName = getClass( this );\n\t\t\t\tif ( className ) {\n\n\t\t\t\t\t// Store className if set\n\t\t\t\t\tdataPriv.set( this, \"__className__\", className );\n\t\t\t\t}\n\n\t\t\t\t// If the element has a class name or if we're passed `false`,\n\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n\t\t\t\t// falling back to the empty string if nothing was stored.\n\t\t\t\tif ( this.setAttribute ) {\n\t\t\t\t\tthis.setAttribute( \"class\",\n\t\t\t\t\t\tclassName || value === false ?\n\t\t\t\t\t\t\"\" :\n\t\t\t\t\t\tdataPriv.get( this, \"__className__\" ) || \"\"\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t},\n\n\thasClass: function( selector ) {\n\t\tvar className, elem,\n\t\t\ti = 0;\n\n\t\tclassName = \" \" + selector + \" \";\n\t\twhile ( ( elem = this[ i++ ] ) ) {\n\t\t\tif ( elem.nodeType === 1 &&\n\t\t\t\t( \" \" + stripAndCollapse( getClass( elem ) ) + \" \" ).indexOf( className ) > -1 ) {\n\t\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t}\n} );\n\n\n\n\nvar rreturn = /\\r/g;\n\njQuery.fn.extend( {\n\tval: function( value ) {\n\t\tvar hooks, ret, isFunction,\n\t\t\telem = this[ 0 ];\n\n\t\tif ( !arguments.length ) {\n\t\t\tif ( elem ) {\n\t\t\t\thooks = jQuery.valHooks[ elem.type ] ||\n\t\t\t\t\tjQuery.valHooks[ elem.nodeName.toLowerCase() ];\n\n\t\t\t\tif ( hooks &&\n\t\t\t\t\t\"get\" in hooks &&\n\t\t\t\t\t( ret = hooks.get( elem, \"value\" ) ) !== undefined\n\t\t\t\t) {\n\t\t\t\t\treturn ret;\n\t\t\t\t}\n\n\t\t\t\tret = elem.value;\n\n\t\t\t\t// Handle most common string cases\n\t\t\t\tif ( typeof ret === \"string\" ) {\n\t\t\t\t\treturn ret.replace( rreturn, \"\" );\n\t\t\t\t}\n\n\t\t\t\t// Handle cases where value is null/undef or number\n\t\t\t\treturn ret == null ? \"\" : ret;\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tisFunction = jQuery.isFunction( value );\n\n\t\treturn this.each( function( i ) {\n\t\t\tvar val;\n\n\t\t\tif ( this.nodeType !== 1 ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( isFunction ) {\n\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n\t\t\t} else {\n\t\t\t\tval = value;\n\t\t\t}\n\n\t\t\t// Treat null/undefined as \"\"; convert numbers to string\n\t\t\tif ( val == null ) {\n\t\t\t\tval = \"\";\n\n\t\t\t} else if ( typeof val === \"number\" ) {\n\t\t\t\tval += \"\";\n\n\t\t\t} else if ( jQuery.isArray( val ) ) {\n\t\t\t\tval = jQuery.map( val, function( value ) {\n\t\t\t\t\treturn value == null ? \"\" : value + \"\";\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n\n\t\t\t// If set returns undefined, fall back to normal setting\n\t\t\tif ( !hooks || !( \"set\" in hooks ) || hooks.set( this, val, \"value\" ) === undefined ) {\n\t\t\t\tthis.value = val;\n\t\t\t}\n\t\t} );\n\t}\n} );\n\njQuery.extend( {\n\tvalHooks: {\n\t\toption: {\n\t\t\tget: function( elem ) {\n\n\t\t\t\tvar val = jQuery.find.attr( elem, \"value\" );\n\t\t\t\treturn val != null ?\n\t\t\t\t\tval :\n\n\t\t\t\t\t// Support: IE <=10 - 11 only\n\t\t\t\t\t// option.text throws exceptions (#14686, #14858)\n\t\t\t\t\t// Strip and collapse whitespace\n\t\t\t\t\t// https://html.spec.whatwg.org/#strip-and-collapse-whitespace\n\t\t\t\t\tstripAndCollapse( jQuery.text( elem ) );\n\t\t\t}\n\t\t},\n\t\tselect: {\n\t\t\tget: function( elem ) {\n\t\t\t\tvar value, option, i,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tindex = elem.selectedIndex,\n\t\t\t\t\tone = elem.type === \"select-one\",\n\t\t\t\t\tvalues = one ? null : [],\n\t\t\t\t\tmax = one ? index + 1 : options.length;\n\n\t\t\t\tif ( index < 0 ) {\n\t\t\t\t\ti = max;\n\n\t\t\t\t} else {\n\t\t\t\t\ti = one ? index : 0;\n\t\t\t\t}\n\n\t\t\t\t// Loop through all the selected options\n\t\t\t\tfor ( ; i < max; i++ ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t// IE8-9 doesn't update selected after form reset (#2551)\n\t\t\t\t\tif ( ( option.selected || i === index ) &&\n\n\t\t\t\t\t\t\t// Don't return options that are disabled or in a disabled optgroup\n\t\t\t\t\t\t\t!option.disabled &&\n\t\t\t\t\t\t\t( !option.parentNode.disabled ||\n\t\t\t\t\t\t\t\t!jQuery.nodeName( option.parentNode, \"optgroup\" ) ) ) {\n\n\t\t\t\t\t\t// Get the specific value for the option\n\t\t\t\t\t\tvalue = jQuery( option ).val();\n\n\t\t\t\t\t\t// We don't need an array for one selects\n\t\t\t\t\t\tif ( one ) {\n\t\t\t\t\t\t\treturn value;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Multi-Selects return an array\n\t\t\t\t\t\tvalues.push( value );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn values;\n\t\t\t},\n\n\t\t\tset: function( elem, value ) {\n\t\t\t\tvar optionSet, option,\n\t\t\t\t\toptions = elem.options,\n\t\t\t\t\tvalues = jQuery.makeArray( value ),\n\t\t\t\t\ti = options.length;\n\n\t\t\t\twhile ( i-- ) {\n\t\t\t\t\toption = options[ i ];\n\n\t\t\t\t\t/* eslint-disable no-cond-assign */\n\n\t\t\t\t\tif ( option.selected =\n\t\t\t\t\t\tjQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1\n\t\t\t\t\t) {\n\t\t\t\t\t\toptionSet = true;\n\t\t\t\t\t}\n\n\t\t\t\t\t/* eslint-enable no-cond-assign */\n\t\t\t\t}\n\n\t\t\t\t// Force browsers to behave consistently when non-matching value is set\n\t\t\t\tif ( !optionSet ) {\n\t\t\t\t\telem.selectedIndex = -1;\n\t\t\t\t}\n\t\t\t\treturn values;\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Radios and checkboxes getter/setter\njQuery.each( [ \"radio\", \"checkbox\" ], function() {\n\tjQuery.valHooks[ this ] = {\n\t\tset: function( elem, value ) {\n\t\t\tif ( jQuery.isArray( value ) ) {\n\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );\n\t\t\t}\n\t\t}\n\t};\n\tif ( !support.checkOn ) {\n\t\tjQuery.valHooks[ this ].get = function( elem ) {\n\t\t\treturn elem.getAttribute( \"value\" ) === null ? \"on\" : elem.value;\n\t\t};\n\t}\n} );\n\n\n\n\n// Return jQuery for attributes-only inclusion\n\n\nvar rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;\n\njQuery.extend( jQuery.event, {\n\n\ttrigger: function( event, data, elem, onlyHandlers ) {\n\n\t\tvar i, cur, tmp, bubbleType, ontype, handle, special,\n\t\t\teventPath = [ elem || document ],\n\t\t\ttype = hasOwn.call( event, \"type\" ) ? event.type : event,\n\t\t\tnamespaces = hasOwn.call( event, \"namespace\" ) ? event.namespace.split( \".\" ) : [];\n\n\t\tcur = tmp = elem = elem || document;\n\n\t\t// Don't do events on text and comment nodes\n\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// focus/blur morphs to focusin/out; ensure we're not firing them right now\n\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( type.indexOf( \".\" ) > -1 ) {\n\n\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n\t\t\tnamespaces = type.split( \".\" );\n\t\t\ttype = namespaces.shift();\n\t\t\tnamespaces.sort();\n\t\t}\n\t\tontype = type.indexOf( \":\" ) < 0 && \"on\" + type;\n\n\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n\t\tevent = event[ jQuery.expando ] ?\n\t\t\tevent :\n\t\t\tnew jQuery.Event( type, typeof event === \"object\" && event );\n\n\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n\t\tevent.namespace = namespaces.join( \".\" );\n\t\tevent.rnamespace = event.namespace ?\n\t\t\tnew RegExp( \"(^|\\\\.)\" + namespaces.join( \"\\\\.(?:.*\\\\.|)\" ) + \"(\\\\.|$)\" ) :\n\t\t\tnull;\n\n\t\t// Clean up the event in case it is being reused\n\t\tevent.result = undefined;\n\t\tif ( !event.target ) {\n\t\t\tevent.target = elem;\n\t\t}\n\n\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n\t\tdata = data == null ?\n\t\t\t[ event ] :\n\t\t\tjQuery.makeArray( data, [ event ] );\n\n\t\t// Allow special events to draw outside the lines\n\t\tspecial = jQuery.event.special[ type ] || {};\n\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n\n\t\t\tbubbleType = special.delegateType || type;\n\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n\t\t\t\tcur = cur.parentNode;\n\t\t\t}\n\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n\t\t\t\teventPath.push( cur );\n\t\t\t\ttmp = cur;\n\t\t\t}\n\n\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n\t\t\tif ( tmp === ( elem.ownerDocument || document ) ) {\n\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n\t\t\t}\n\t\t}\n\n\t\t// Fire handlers on the event path\n\t\ti = 0;\n\t\twhile ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {\n\n\t\t\tevent.type = i > 1 ?\n\t\t\t\tbubbleType :\n\t\t\t\tspecial.bindType || type;\n\n\t\t\t// jQuery handler\n\t\t\thandle = ( dataPriv.get( cur, \"events\" ) || {} )[ event.type ] &&\n\t\t\t\tdataPriv.get( cur, \"handle\" );\n\t\t\tif ( handle ) {\n\t\t\t\thandle.apply( cur, data );\n\t\t\t}\n\n\t\t\t// Native handler\n\t\t\thandle = ontype && cur[ ontype ];\n\t\t\tif ( handle && handle.apply && acceptData( cur ) ) {\n\t\t\t\tevent.result = handle.apply( cur, data );\n\t\t\t\tif ( event.result === false ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tevent.type = type;\n\n\t\t// If nobody prevented the default action, do it now\n\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n\n\t\t\tif ( ( !special._default ||\n\t\t\t\tspecial._default.apply( eventPath.pop(), data ) === false ) &&\n\t\t\t\tacceptData( elem ) ) {\n\n\t\t\t\t// Call a native DOM method on the target with the same name as the event.\n\t\t\t\t// Don't do default actions on window, that's where global variables be (#6170)\n\t\t\t\tif ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// Don't re-trigger an onFOO event when we call its FOO() method\n\t\t\t\t\ttmp = elem[ ontype ];\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = null;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n\t\t\t\t\tjQuery.event.triggered = type;\n\t\t\t\t\telem[ type ]();\n\t\t\t\t\tjQuery.event.triggered = undefined;\n\n\t\t\t\t\tif ( tmp ) {\n\t\t\t\t\t\telem[ ontype ] = tmp;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn event.result;\n\t},\n\n\t// Piggyback on a donor event to simulate a different one\n\t// Used only for `focus(in | out)` events\n\tsimulate: function( type, elem, event ) {\n\t\tvar e = jQuery.extend(\n\t\t\tnew jQuery.Event(),\n\t\t\tevent,\n\t\t\t{\n\t\t\t\ttype: type,\n\t\t\t\tisSimulated: true\n\t\t\t}\n\t\t);\n\n\t\tjQuery.event.trigger( e, null, elem );\n\t}\n\n} );\n\njQuery.fn.extend( {\n\n\ttrigger: function( type, data ) {\n\t\treturn this.each( function() {\n\t\t\tjQuery.event.trigger( type, data, this );\n\t\t} );\n\t},\n\ttriggerHandler: function( type, data ) {\n\t\tvar elem = this[ 0 ];\n\t\tif ( elem ) {\n\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n\t\t}\n\t}\n} );\n\n\njQuery.each( ( \"blur focus focusin focusout resize scroll click dblclick \" +\n\t\"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave \" +\n\t\"change select submit keydown keypress keyup contextmenu\" ).split( \" \" ),\n\tfunction( i, name ) {\n\n\t// Handle event binding\n\tjQuery.fn[ name ] = function( data, fn ) {\n\t\treturn arguments.length > 0 ?\n\t\t\tthis.on( name, null, data, fn ) :\n\t\t\tthis.trigger( name );\n\t};\n} );\n\njQuery.fn.extend( {\n\thover: function( fnOver, fnOut ) {\n\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n\t}\n} );\n\n\n\n\nsupport.focusin = \"onfocusin\" in window;\n\n\n// Support: Firefox <=44\n// Firefox doesn't have focus(in | out) events\n// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787\n//\n// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1\n// focus(in | out) events fire after focus & blur events,\n// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order\n// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857\nif ( !support.focusin ) {\n\tjQuery.each( { focus: \"focusin\", blur: \"focusout\" }, function( orig, fix ) {\n\n\t\t// Attach a single capturing handler on the document while someone wants focusin/focusout\n\t\tvar handler = function( event ) {\n\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );\n\t\t};\n\n\t\tjQuery.event.special[ fix ] = {\n\t\t\tsetup: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = dataPriv.access( doc, fix );\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.addEventListener( orig, handler, true );\n\t\t\t\t}\n\t\t\t\tdataPriv.access( doc, fix, ( attaches || 0 ) + 1 );\n\t\t\t},\n\t\t\tteardown: function() {\n\t\t\t\tvar doc = this.ownerDocument || this,\n\t\t\t\t\tattaches = dataPriv.access( doc, fix ) - 1;\n\n\t\t\t\tif ( !attaches ) {\n\t\t\t\t\tdoc.removeEventListener( orig, handler, true );\n\t\t\t\t\tdataPriv.remove( doc, fix );\n\n\t\t\t\t} else {\n\t\t\t\t\tdataPriv.access( doc, fix, attaches );\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t} );\n}\nvar location = window.location;\n\nvar nonce = jQuery.now();\n\nvar rquery = ( /\\?/ );\n\n\n\n// Cross-browser xml parsing\njQuery.parseXML = function( data ) {\n\tvar xml;\n\tif ( !data || typeof data !== \"string\" ) {\n\t\treturn null;\n\t}\n\n\t// Support: IE 9 - 11 only\n\t// IE throws on parseFromString with invalid input.\n\ttry {\n\t\txml = ( new window.DOMParser() ).parseFromString( data, \"text/xml\" );\n\t} catch ( e ) {\n\t\txml = undefined;\n\t}\n\n\tif ( !xml || xml.getElementsByTagName( \"parsererror\" ).length ) {\n\t\tjQuery.error( \"Invalid XML: \" + data );\n\t}\n\treturn xml;\n};\n\n\nvar\n\trbracket = /\\[\\]$/,\n\trCRLF = /\\r?\\n/g,\n\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n\nfunction buildParams( prefix, obj, traditional, add ) {\n\tvar name;\n\n\tif ( jQuery.isArray( obj ) ) {\n\n\t\t// Serialize array item.\n\t\tjQuery.each( obj, function( i, v ) {\n\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n\n\t\t\t\t// Treat each array item as a scalar.\n\t\t\t\tadd( prefix, v );\n\n\t\t\t} else {\n\n\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n\t\t\t\tbuildParams(\n\t\t\t\t\tprefix + \"[\" + ( typeof v === \"object\" && v != null ? i : \"\" ) + \"]\",\n\t\t\t\t\tv,\n\t\t\t\t\ttraditional,\n\t\t\t\t\tadd\n\t\t\t\t);\n\t\t\t}\n\t\t} );\n\n\t} else if ( !traditional && jQuery.type( obj ) === \"object\" ) {\n\n\t\t// Serialize object item.\n\t\tfor ( name in obj ) {\n\t\t\tbuildParams( prefix + \"[\" + name + \"]\", obj[ name ], traditional, add );\n\t\t}\n\n\t} else {\n\n\t\t// Serialize scalar item.\n\t\tadd( prefix, obj );\n\t}\n}\n\n// Serialize an array of form elements or a set of\n// key/values into a query string\njQuery.param = function( a, traditional ) {\n\tvar prefix,\n\t\ts = [],\n\t\tadd = function( key, valueOrFunction ) {\n\n\t\t\t// If value is a function, invoke it and use its return value\n\t\t\tvar value = jQuery.isFunction( valueOrFunction ) ?\n\t\t\t\tvalueOrFunction() :\n\t\t\t\tvalueOrFunction;\n\n\t\t\ts[ s.length ] = encodeURIComponent( key ) + \"=\" +\n\t\t\t\tencodeURIComponent( value == null ? \"\" : value );\n\t\t};\n\n\t// If an array was passed in, assume that it is an array of form elements.\n\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n\n\t\t// Serialize the form elements\n\t\tjQuery.each( a, function() {\n\t\t\tadd( this.name, this.value );\n\t\t} );\n\n\t} else {\n\n\t\t// If traditional, encode the \"old\" way (the way 1.3.2 or older\n\t\t// did it), otherwise encode params recursively.\n\t\tfor ( prefix in a ) {\n\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n\t\t}\n\t}\n\n\t// Return the resulting serialization\n\treturn s.join( \"&\" );\n};\n\njQuery.fn.extend( {\n\tserialize: function() {\n\t\treturn jQuery.param( this.serializeArray() );\n\t},\n\tserializeArray: function() {\n\t\treturn this.map( function() {\n\n\t\t\t// Can add propHook for \"elements\" to filter or add form elements\n\t\t\tvar elements = jQuery.prop( this, \"elements\" );\n\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n\t\t} )\n\t\t.filter( function() {\n\t\t\tvar type = this.type;\n\n\t\t\t// Use .is( \":disabled\" ) so that fieldset[disabled] works\n\t\t\treturn this.name && !jQuery( this ).is( \":disabled\" ) &&\n\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n\t\t\t\t( this.checked || !rcheckableType.test( type ) );\n\t\t} )\n\t\t.map( function( i, elem ) {\n\t\t\tvar val = jQuery( this ).val();\n\n\t\t\tif ( val == null ) {\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\tif ( jQuery.isArray( val ) ) {\n\t\t\t\treturn jQuery.map( val, function( val ) {\n\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn { name: elem.name, value: val.replace( rCRLF, \"\\r\\n\" ) };\n\t\t} ).get();\n\t}\n} );\n\n\nvar\n\tr20 = /%20/g,\n\trhash = /#.*$/,\n\trantiCache = /([?&])_=[^&]*/,\n\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)$/mg,\n\n\t// #7653, #8125, #8152: local protocol detection\n\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n\trnoContent = /^(?:GET|HEAD)$/,\n\trprotocol = /^\\/\\//,\n\n\t/* Prefilters\n\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n\t * 2) These are called:\n\t *    - BEFORE asking for a transport\n\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n\t * 3) key is the dataType\n\t * 4) the catchall symbol \"*\" can be used\n\t * 5) execution will start with transport dataType and THEN continue down to \"*\" if needed\n\t */\n\tprefilters = {},\n\n\t/* Transports bindings\n\t * 1) key is the dataType\n\t * 2) the catchall symbol \"*\" can be used\n\t * 3) selection will start with transport dataType and THEN go to \"*\" if needed\n\t */\n\ttransports = {},\n\n\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n\tallTypes = \"*/\".concat( \"*\" ),\n\n\t// Anchor tag for parsing the document origin\n\toriginAnchor = document.createElement( \"a\" );\n\toriginAnchor.href = location.href;\n\n// Base \"constructor\" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\nfunction addToPrefiltersOrTransports( structure ) {\n\n\t// dataTypeExpression is optional and defaults to \"*\"\n\treturn function( dataTypeExpression, func ) {\n\n\t\tif ( typeof dataTypeExpression !== \"string\" ) {\n\t\t\tfunc = dataTypeExpression;\n\t\t\tdataTypeExpression = \"*\";\n\t\t}\n\n\t\tvar dataType,\n\t\t\ti = 0,\n\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];\n\n\t\tif ( jQuery.isFunction( func ) ) {\n\n\t\t\t// For each dataType in the dataTypeExpression\n\t\t\twhile ( ( dataType = dataTypes[ i++ ] ) ) {\n\n\t\t\t\t// Prepend if requested\n\t\t\t\tif ( dataType[ 0 ] === \"+\" ) {\n\t\t\t\t\tdataType = dataType.slice( 1 ) || \"*\";\n\t\t\t\t\t( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );\n\n\t\t\t\t// Otherwise append\n\t\t\t\t} else {\n\t\t\t\t\t( structure[ dataType ] = structure[ dataType ] || [] ).push( func );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n}\n\n// Base inspection function for prefilters and transports\nfunction inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n\n\tvar inspected = {},\n\t\tseekingTransport = ( structure === transports );\n\n\tfunction inspect( dataType ) {\n\t\tvar selected;\n\t\tinspected[ dataType ] = true;\n\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n\t\t\tif ( typeof dataTypeOrTransport === \"string\" &&\n\t\t\t\t!seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n\n\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n\t\t\t\tinspect( dataTypeOrTransport );\n\t\t\t\treturn false;\n\t\t\t} else if ( seekingTransport ) {\n\t\t\t\treturn !( selected = dataTypeOrTransport );\n\t\t\t}\n\t\t} );\n\t\treturn selected;\n\t}\n\n\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ \"*\" ] && inspect( \"*\" );\n}\n\n// A special extend for ajax options\n// that takes \"flat\" options (not to be deep extended)\n// Fixes #9887\nfunction ajaxExtend( target, src ) {\n\tvar key, deep,\n\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n\n\tfor ( key in src ) {\n\t\tif ( src[ key ] !== undefined ) {\n\t\t\t( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];\n\t\t}\n\t}\n\tif ( deep ) {\n\t\tjQuery.extend( true, target, deep );\n\t}\n\n\treturn target;\n}\n\n/* Handles responses to an ajax request:\n * - finds the right dataType (mediates between content-type and expected dataType)\n * - returns the corresponding response\n */\nfunction ajaxHandleResponses( s, jqXHR, responses ) {\n\n\tvar ct, type, finalDataType, firstDataType,\n\t\tcontents = s.contents,\n\t\tdataTypes = s.dataTypes;\n\n\t// Remove auto dataType and get content-type in the process\n\twhile ( dataTypes[ 0 ] === \"*\" ) {\n\t\tdataTypes.shift();\n\t\tif ( ct === undefined ) {\n\t\t\tct = s.mimeType || jqXHR.getResponseHeader( \"Content-Type\" );\n\t\t}\n\t}\n\n\t// Check if we're dealing with a known content-type\n\tif ( ct ) {\n\t\tfor ( type in contents ) {\n\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n\t\t\t\tdataTypes.unshift( type );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\t// Check to see if we have a response for the expected dataType\n\tif ( dataTypes[ 0 ] in responses ) {\n\t\tfinalDataType = dataTypes[ 0 ];\n\t} else {\n\n\t\t// Try convertible dataTypes\n\t\tfor ( type in responses ) {\n\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + \" \" + dataTypes[ 0 ] ] ) {\n\t\t\t\tfinalDataType = type;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif ( !firstDataType ) {\n\t\t\t\tfirstDataType = type;\n\t\t\t}\n\t\t}\n\n\t\t// Or just use first one\n\t\tfinalDataType = finalDataType || firstDataType;\n\t}\n\n\t// If we found a dataType\n\t// We add the dataType to the list if needed\n\t// and return the corresponding response\n\tif ( finalDataType ) {\n\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n\t\t\tdataTypes.unshift( finalDataType );\n\t\t}\n\t\treturn responses[ finalDataType ];\n\t}\n}\n\n/* Chain conversions given the request and the original response\n * Also sets the responseXXX fields on the jqXHR instance\n */\nfunction ajaxConvert( s, response, jqXHR, isSuccess ) {\n\tvar conv2, current, conv, tmp, prev,\n\t\tconverters = {},\n\n\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n\t\tdataTypes = s.dataTypes.slice();\n\n\t// Create converters map with lowercased keys\n\tif ( dataTypes[ 1 ] ) {\n\t\tfor ( conv in s.converters ) {\n\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n\t\t}\n\t}\n\n\tcurrent = dataTypes.shift();\n\n\t// Convert to each sequential dataType\n\twhile ( current ) {\n\n\t\tif ( s.responseFields[ current ] ) {\n\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n\t\t}\n\n\t\t// Apply the dataFilter if provided\n\t\tif ( !prev && isSuccess && s.dataFilter ) {\n\t\t\tresponse = s.dataFilter( response, s.dataType );\n\t\t}\n\n\t\tprev = current;\n\t\tcurrent = dataTypes.shift();\n\n\t\tif ( current ) {\n\n\t\t\t// There's only work to do if current dataType is non-auto\n\t\t\tif ( current === \"*\" ) {\n\n\t\t\t\tcurrent = prev;\n\n\t\t\t// Convert response if prev dataType is non-auto and differs from current\n\t\t\t} else if ( prev !== \"*\" && prev !== current ) {\n\n\t\t\t\t// Seek a direct converter\n\t\t\t\tconv = converters[ prev + \" \" + current ] || converters[ \"* \" + current ];\n\n\t\t\t\t// If none found, seek a pair\n\t\t\t\tif ( !conv ) {\n\t\t\t\t\tfor ( conv2 in converters ) {\n\n\t\t\t\t\t\t// If conv2 outputs current\n\t\t\t\t\t\ttmp = conv2.split( \" \" );\n\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n\n\t\t\t\t\t\t\t// If prev can be converted to accepted input\n\t\t\t\t\t\t\tconv = converters[ prev + \" \" + tmp[ 0 ] ] ||\n\t\t\t\t\t\t\t\tconverters[ \"* \" + tmp[ 0 ] ];\n\t\t\t\t\t\t\tif ( conv ) {\n\n\t\t\t\t\t\t\t\t// Condense equivalence converters\n\t\t\t\t\t\t\t\tif ( conv === true ) {\n\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n\n\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Apply converter (if not an equivalence)\n\t\t\t\tif ( conv !== true ) {\n\n\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n\t\t\t\t\tif ( conv && s.throws ) {\n\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tresponse = conv( response );\n\t\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\tstate: \"parsererror\",\n\t\t\t\t\t\t\t\terror: conv ? e : \"No conversion from \" + prev + \" to \" + current\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn { state: \"success\", data: response };\n}\n\njQuery.extend( {\n\n\t// Counter for holding the number of active queries\n\tactive: 0,\n\n\t// Last-Modified header cache for next request\n\tlastModified: {},\n\tetag: {},\n\n\tajaxSettings: {\n\t\turl: location.href,\n\t\ttype: \"GET\",\n\t\tisLocal: rlocalProtocol.test( location.protocol ),\n\t\tglobal: true,\n\t\tprocessData: true,\n\t\tasync: true,\n\t\tcontentType: \"application/x-www-form-urlencoded; charset=UTF-8\",\n\n\t\t/*\n\t\ttimeout: 0,\n\t\tdata: null,\n\t\tdataType: null,\n\t\tusername: null,\n\t\tpassword: null,\n\t\tcache: null,\n\t\tthrows: false,\n\t\ttraditional: false,\n\t\theaders: {},\n\t\t*/\n\n\t\taccepts: {\n\t\t\t\"*\": allTypes,\n\t\t\ttext: \"text/plain\",\n\t\t\thtml: \"text/html\",\n\t\t\txml: \"application/xml, text/xml\",\n\t\t\tjson: \"application/json, text/javascript\"\n\t\t},\n\n\t\tcontents: {\n\t\t\txml: /\\bxml\\b/,\n\t\t\thtml: /\\bhtml/,\n\t\t\tjson: /\\bjson\\b/\n\t\t},\n\n\t\tresponseFields: {\n\t\t\txml: \"responseXML\",\n\t\t\ttext: \"responseText\",\n\t\t\tjson: \"responseJSON\"\n\t\t},\n\n\t\t// Data converters\n\t\t// Keys separate source (or catchall \"*\") and destination types with a single space\n\t\tconverters: {\n\n\t\t\t// Convert anything to text\n\t\t\t\"* text\": String,\n\n\t\t\t// Text to html (true = no transformation)\n\t\t\t\"text html\": true,\n\n\t\t\t// Evaluate text as a json expression\n\t\t\t\"text json\": JSON.parse,\n\n\t\t\t// Parse text as xml\n\t\t\t\"text xml\": jQuery.parseXML\n\t\t},\n\n\t\t// For options that shouldn't be deep extended:\n\t\t// you can add your own custom options here if\n\t\t// and when you create one that shouldn't be\n\t\t// deep extended (see ajaxExtend)\n\t\tflatOptions: {\n\t\t\turl: true,\n\t\t\tcontext: true\n\t\t}\n\t},\n\n\t// Creates a full fledged settings object into target\n\t// with both ajaxSettings and settings fields.\n\t// If target is omitted, writes into ajaxSettings.\n\tajaxSetup: function( target, settings ) {\n\t\treturn settings ?\n\n\t\t\t// Building a settings object\n\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n\n\t\t\t// Extending ajaxSettings\n\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n\t},\n\n\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n\tajaxTransport: addToPrefiltersOrTransports( transports ),\n\n\t// Main method\n\tajax: function( url, options ) {\n\n\t\t// If url is an object, simulate pre-1.5 signature\n\t\tif ( typeof url === \"object\" ) {\n\t\t\toptions = url;\n\t\t\turl = undefined;\n\t\t}\n\n\t\t// Force options to be an object\n\t\toptions = options || {};\n\n\t\tvar transport,\n\n\t\t\t// URL without anti-cache param\n\t\t\tcacheURL,\n\n\t\t\t// Response headers\n\t\t\tresponseHeadersString,\n\t\t\tresponseHeaders,\n\n\t\t\t// timeout handle\n\t\t\ttimeoutTimer,\n\n\t\t\t// Url cleanup var\n\t\t\turlAnchor,\n\n\t\t\t// Request state (becomes false upon send and true upon completion)\n\t\t\tcompleted,\n\n\t\t\t// To know if global events are to be dispatched\n\t\t\tfireGlobals,\n\n\t\t\t// Loop variable\n\t\t\ti,\n\n\t\t\t// uncached part of the url\n\t\t\tuncached,\n\n\t\t\t// Create the final options object\n\t\t\ts = jQuery.ajaxSetup( {}, options ),\n\n\t\t\t// Callbacks context\n\t\t\tcallbackContext = s.context || s,\n\n\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n\t\t\tglobalEventContext = s.context &&\n\t\t\t\t( callbackContext.nodeType || callbackContext.jquery ) ?\n\t\t\t\t\tjQuery( callbackContext ) :\n\t\t\t\t\tjQuery.event,\n\n\t\t\t// Deferreds\n\t\t\tdeferred = jQuery.Deferred(),\n\t\t\tcompleteDeferred = jQuery.Callbacks( \"once memory\" ),\n\n\t\t\t// Status-dependent callbacks\n\t\t\tstatusCode = s.statusCode || {},\n\n\t\t\t// Headers (they are sent all at once)\n\t\t\trequestHeaders = {},\n\t\t\trequestHeadersNames = {},\n\n\t\t\t// Default abort message\n\t\t\tstrAbort = \"canceled\",\n\n\t\t\t// Fake xhr\n\t\t\tjqXHR = {\n\t\t\t\treadyState: 0,\n\n\t\t\t\t// Builds headers hashtable if needed\n\t\t\t\tgetResponseHeader: function( key ) {\n\t\t\t\t\tvar match;\n\t\t\t\t\tif ( completed ) {\n\t\t\t\t\t\tif ( !responseHeaders ) {\n\t\t\t\t\t\t\tresponseHeaders = {};\n\t\t\t\t\t\t\twhile ( ( match = rheaders.exec( responseHeadersString ) ) ) {\n\t\t\t\t\t\t\t\tresponseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n\t\t\t\t\t}\n\t\t\t\t\treturn match == null ? null : match;\n\t\t\t\t},\n\n\t\t\t\t// Raw string\n\t\t\t\tgetAllResponseHeaders: function() {\n\t\t\t\t\treturn completed ? responseHeadersString : null;\n\t\t\t\t},\n\n\t\t\t\t// Caches the header\n\t\t\t\tsetRequestHeader: function( name, value ) {\n\t\t\t\t\tif ( completed == null ) {\n\t\t\t\t\t\tname = requestHeadersNames[ name.toLowerCase() ] =\n\t\t\t\t\t\t\trequestHeadersNames[ name.toLowerCase() ] || name;\n\t\t\t\t\t\trequestHeaders[ name ] = value;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Overrides response content-type header\n\t\t\t\toverrideMimeType: function( type ) {\n\t\t\t\t\tif ( completed == null ) {\n\t\t\t\t\t\ts.mimeType = type;\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Status-dependent callbacks\n\t\t\t\tstatusCode: function( map ) {\n\t\t\t\t\tvar code;\n\t\t\t\t\tif ( map ) {\n\t\t\t\t\t\tif ( completed ) {\n\n\t\t\t\t\t\t\t// Execute the appropriate callbacks\n\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t// Lazy-add the new callbacks in a way that preserves old ones\n\t\t\t\t\t\t\tfor ( code in map ) {\n\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn this;\n\t\t\t\t},\n\n\t\t\t\t// Cancel the request\n\t\t\t\tabort: function( statusText ) {\n\t\t\t\t\tvar finalText = statusText || strAbort;\n\t\t\t\t\tif ( transport ) {\n\t\t\t\t\t\ttransport.abort( finalText );\n\t\t\t\t\t}\n\t\t\t\t\tdone( 0, finalText );\n\t\t\t\t\treturn this;\n\t\t\t\t}\n\t\t\t};\n\n\t\t// Attach deferreds\n\t\tdeferred.promise( jqXHR );\n\n\t\t// Add protocol if not provided (prefilters might expect it)\n\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n\t\t// We also use the url parameter if available\n\t\ts.url = ( ( url || s.url || location.href ) + \"\" )\n\t\t\t.replace( rprotocol, location.protocol + \"//\" );\n\n\t\t// Alias method option to type as per ticket #12004\n\t\ts.type = options.method || options.type || s.method || s.type;\n\n\t\t// Extract dataTypes list\n\t\ts.dataTypes = ( s.dataType || \"*\" ).toLowerCase().match( rnothtmlwhite ) || [ \"\" ];\n\n\t\t// A cross-domain request is in order when the origin doesn't match the current origin.\n\t\tif ( s.crossDomain == null ) {\n\t\t\turlAnchor = document.createElement( \"a\" );\n\n\t\t\t// Support: IE <=8 - 11, Edge 12 - 13\n\t\t\t// IE throws exception on accessing the href property if url is malformed,\n\t\t\t// e.g. http://example.com:80x/\n\t\t\ttry {\n\t\t\t\turlAnchor.href = s.url;\n\n\t\t\t\t// Support: IE <=8 - 11 only\n\t\t\t\t// Anchor's host property isn't correctly set when s.url is relative\n\t\t\t\turlAnchor.href = urlAnchor.href;\n\t\t\t\ts.crossDomain = originAnchor.protocol + \"//\" + originAnchor.host !==\n\t\t\t\t\turlAnchor.protocol + \"//\" + urlAnchor.host;\n\t\t\t} catch ( e ) {\n\n\t\t\t\t// If there is an error parsing the URL, assume it is crossDomain,\n\t\t\t\t// it can be rejected by the transport if it is invalid\n\t\t\t\ts.crossDomain = true;\n\t\t\t}\n\t\t}\n\n\t\t// Convert data if not already a string\n\t\tif ( s.data && s.processData && typeof s.data !== \"string\" ) {\n\t\t\ts.data = jQuery.param( s.data, s.traditional );\n\t\t}\n\n\t\t// Apply prefilters\n\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n\n\t\t// If request was aborted inside a prefilter, stop there\n\t\tif ( completed ) {\n\t\t\treturn jqXHR;\n\t\t}\n\n\t\t// We can fire global events as of now if asked to\n\t\t// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)\n\t\tfireGlobals = jQuery.event && s.global;\n\n\t\t// Watch for a new set of requests\n\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n\t\t\tjQuery.event.trigger( \"ajaxStart\" );\n\t\t}\n\n\t\t// Uppercase the type\n\t\ts.type = s.type.toUpperCase();\n\n\t\t// Determine if request has content\n\t\ts.hasContent = !rnoContent.test( s.type );\n\n\t\t// Save the URL in case we're toying with the If-Modified-Since\n\t\t// and/or If-None-Match header later on\n\t\t// Remove hash to simplify url manipulation\n\t\tcacheURL = s.url.replace( rhash, \"\" );\n\n\t\t// More options handling for requests with no content\n\t\tif ( !s.hasContent ) {\n\n\t\t\t// Remember the hash so we can put it back\n\t\t\tuncached = s.url.slice( cacheURL.length );\n\n\t\t\t// If data is available, append data to url\n\t\t\tif ( s.data ) {\n\t\t\t\tcacheURL += ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + s.data;\n\n\t\t\t\t// #9682: remove data so that it's not used in an eventual retry\n\t\t\t\tdelete s.data;\n\t\t\t}\n\n\t\t\t// Add or update anti-cache param if needed\n\t\t\tif ( s.cache === false ) {\n\t\t\t\tcacheURL = cacheURL.replace( rantiCache, \"$1\" );\n\t\t\t\tuncached = ( rquery.test( cacheURL ) ? \"&\" : \"?\" ) + \"_=\" + ( nonce++ ) + uncached;\n\t\t\t}\n\n\t\t\t// Put hash and anti-cache on the URL that will be requested (gh-1732)\n\t\t\ts.url = cacheURL + uncached;\n\n\t\t// Change '%20' to '+' if this is encoded form body content (gh-2658)\n\t\t} else if ( s.data && s.processData &&\n\t\t\t( s.contentType || \"\" ).indexOf( \"application/x-www-form-urlencoded\" ) === 0 ) {\n\t\t\ts.data = s.data.replace( r20, \"+\" );\n\t\t}\n\n\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\tif ( s.ifModified ) {\n\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-Modified-Since\", jQuery.lastModified[ cacheURL ] );\n\t\t\t}\n\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n\t\t\t\tjqXHR.setRequestHeader( \"If-None-Match\", jQuery.etag[ cacheURL ] );\n\t\t\t}\n\t\t}\n\n\t\t// Set the correct header, if data is being sent\n\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n\t\t\tjqXHR.setRequestHeader( \"Content-Type\", s.contentType );\n\t\t}\n\n\t\t// Set the Accepts header for the server, depending on the dataType\n\t\tjqXHR.setRequestHeader(\n\t\t\t\"Accept\",\n\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?\n\t\t\t\ts.accepts[ s.dataTypes[ 0 ] ] +\n\t\t\t\t\t( s.dataTypes[ 0 ] !== \"*\" ? \", \" + allTypes + \"; q=0.01\" : \"\" ) :\n\t\t\t\ts.accepts[ \"*\" ]\n\t\t);\n\n\t\t// Check for headers option\n\t\tfor ( i in s.headers ) {\n\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n\t\t}\n\n\t\t// Allow custom headers/mimetypes and early abort\n\t\tif ( s.beforeSend &&\n\t\t\t( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {\n\n\t\t\t// Abort if not done already and return\n\t\t\treturn jqXHR.abort();\n\t\t}\n\n\t\t// Aborting is no longer a cancellation\n\t\tstrAbort = \"abort\";\n\n\t\t// Install callbacks on deferreds\n\t\tcompleteDeferred.add( s.complete );\n\t\tjqXHR.done( s.success );\n\t\tjqXHR.fail( s.error );\n\n\t\t// Get transport\n\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n\n\t\t// If no transport, we auto-abort\n\t\tif ( !transport ) {\n\t\t\tdone( -1, \"No Transport\" );\n\t\t} else {\n\t\t\tjqXHR.readyState = 1;\n\n\t\t\t// Send global event\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxSend\", [ jqXHR, s ] );\n\t\t\t}\n\n\t\t\t// If request was aborted inside ajaxSend, stop there\n\t\t\tif ( completed ) {\n\t\t\t\treturn jqXHR;\n\t\t\t}\n\n\t\t\t// Timeout\n\t\t\tif ( s.async && s.timeout > 0 ) {\n\t\t\t\ttimeoutTimer = window.setTimeout( function() {\n\t\t\t\t\tjqXHR.abort( \"timeout\" );\n\t\t\t\t}, s.timeout );\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tcompleted = false;\n\t\t\t\ttransport.send( requestHeaders, done );\n\t\t\t} catch ( e ) {\n\n\t\t\t\t// Rethrow post-completion exceptions\n\t\t\t\tif ( completed ) {\n\t\t\t\t\tthrow e;\n\t\t\t\t}\n\n\t\t\t\t// Propagate others as results\n\t\t\t\tdone( -1, e );\n\t\t\t}\n\t\t}\n\n\t\t// Callback for when everything is done\n\t\tfunction done( status, nativeStatusText, responses, headers ) {\n\t\t\tvar isSuccess, success, error, response, modified,\n\t\t\t\tstatusText = nativeStatusText;\n\n\t\t\t// Ignore repeat invocations\n\t\t\tif ( completed ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcompleted = true;\n\n\t\t\t// Clear timeout if it exists\n\t\t\tif ( timeoutTimer ) {\n\t\t\t\twindow.clearTimeout( timeoutTimer );\n\t\t\t}\n\n\t\t\t// Dereference transport for early garbage collection\n\t\t\t// (no matter how long the jqXHR object will be used)\n\t\t\ttransport = undefined;\n\n\t\t\t// Cache response headers\n\t\t\tresponseHeadersString = headers || \"\";\n\n\t\t\t// Set readyState\n\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n\n\t\t\t// Determine if successful\n\t\t\tisSuccess = status >= 200 && status < 300 || status === 304;\n\n\t\t\t// Get response data\n\t\t\tif ( responses ) {\n\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n\t\t\t}\n\n\t\t\t// Convert no matter what (that way responseXXX fields are always set)\n\t\t\tresponse = ajaxConvert( s, response, jqXHR, isSuccess );\n\n\t\t\t// If successful, handle type chaining\n\t\t\tif ( isSuccess ) {\n\n\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n\t\t\t\tif ( s.ifModified ) {\n\t\t\t\t\tmodified = jqXHR.getResponseHeader( \"Last-Modified\" );\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t\tmodified = jqXHR.getResponseHeader( \"etag\" );\n\t\t\t\t\tif ( modified ) {\n\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// if no content\n\t\t\t\tif ( status === 204 || s.type === \"HEAD\" ) {\n\t\t\t\t\tstatusText = \"nocontent\";\n\n\t\t\t\t// if not modified\n\t\t\t\t} else if ( status === 304 ) {\n\t\t\t\t\tstatusText = \"notmodified\";\n\n\t\t\t\t// If we have data, let's convert it\n\t\t\t\t} else {\n\t\t\t\t\tstatusText = response.state;\n\t\t\t\t\tsuccess = response.data;\n\t\t\t\t\terror = response.error;\n\t\t\t\t\tisSuccess = !error;\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// Extract error from statusText and normalize for non-aborts\n\t\t\t\terror = statusText;\n\t\t\t\tif ( status || !statusText ) {\n\t\t\t\t\tstatusText = \"error\";\n\t\t\t\t\tif ( status < 0 ) {\n\t\t\t\t\t\tstatus = 0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set data for the fake xhr object\n\t\t\tjqXHR.status = status;\n\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + \"\";\n\n\t\t\t// Success/Error\n\t\t\tif ( isSuccess ) {\n\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n\t\t\t} else {\n\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n\t\t\t}\n\n\t\t\t// Status-dependent callbacks\n\t\t\tjqXHR.statusCode( statusCode );\n\t\t\tstatusCode = undefined;\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( isSuccess ? \"ajaxSuccess\" : \"ajaxError\",\n\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n\t\t\t}\n\n\t\t\t// Complete\n\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n\n\t\t\tif ( fireGlobals ) {\n\t\t\t\tglobalEventContext.trigger( \"ajaxComplete\", [ jqXHR, s ] );\n\n\t\t\t\t// Handle the global AJAX counter\n\t\t\t\tif ( !( --jQuery.active ) ) {\n\t\t\t\t\tjQuery.event.trigger( \"ajaxStop\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jqXHR;\n\t},\n\n\tgetJSON: function( url, data, callback ) {\n\t\treturn jQuery.get( url, data, callback, \"json\" );\n\t},\n\n\tgetScript: function( url, callback ) {\n\t\treturn jQuery.get( url, undefined, callback, \"script\" );\n\t}\n} );\n\njQuery.each( [ \"get\", \"post\" ], function( i, method ) {\n\tjQuery[ method ] = function( url, data, callback, type ) {\n\n\t\t// Shift arguments if data argument was omitted\n\t\tif ( jQuery.isFunction( data ) ) {\n\t\t\ttype = type || callback;\n\t\t\tcallback = data;\n\t\t\tdata = undefined;\n\t\t}\n\n\t\t// The url can be an options object (which then must have .url)\n\t\treturn jQuery.ajax( jQuery.extend( {\n\t\t\turl: url,\n\t\t\ttype: method,\n\t\t\tdataType: type,\n\t\t\tdata: data,\n\t\t\tsuccess: callback\n\t\t}, jQuery.isPlainObject( url ) && url ) );\n\t};\n} );\n\n\njQuery._evalUrl = function( url ) {\n\treturn jQuery.ajax( {\n\t\turl: url,\n\n\t\t// Make this explicit, since user can override this through ajaxSetup (#11264)\n\t\ttype: \"GET\",\n\t\tdataType: \"script\",\n\t\tcache: true,\n\t\tasync: false,\n\t\tglobal: false,\n\t\t\"throws\": true\n\t} );\n};\n\n\njQuery.fn.extend( {\n\twrapAll: function( html ) {\n\t\tvar wrap;\n\n\t\tif ( this[ 0 ] ) {\n\t\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\t\thtml = html.call( this[ 0 ] );\n\t\t\t}\n\n\t\t\t// The elements to wrap the target around\n\t\t\twrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n\n\t\t\tif ( this[ 0 ].parentNode ) {\n\t\t\t\twrap.insertBefore( this[ 0 ] );\n\t\t\t}\n\n\t\t\twrap.map( function() {\n\t\t\t\tvar elem = this;\n\n\t\t\t\twhile ( elem.firstElementChild ) {\n\t\t\t\t\telem = elem.firstElementChild;\n\t\t\t\t}\n\n\t\t\t\treturn elem;\n\t\t\t} ).append( this );\n\t\t}\n\n\t\treturn this;\n\t},\n\n\twrapInner: function( html ) {\n\t\tif ( jQuery.isFunction( html ) ) {\n\t\t\treturn this.each( function( i ) {\n\t\t\t\tjQuery( this ).wrapInner( html.call( this, i ) );\n\t\t\t} );\n\t\t}\n\n\t\treturn this.each( function() {\n\t\t\tvar self = jQuery( this ),\n\t\t\t\tcontents = self.contents();\n\n\t\t\tif ( contents.length ) {\n\t\t\t\tcontents.wrapAll( html );\n\n\t\t\t} else {\n\t\t\t\tself.append( html );\n\t\t\t}\n\t\t} );\n\t},\n\n\twrap: function( html ) {\n\t\tvar isFunction = jQuery.isFunction( html );\n\n\t\treturn this.each( function( i ) {\n\t\t\tjQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );\n\t\t} );\n\t},\n\n\tunwrap: function( selector ) {\n\t\tthis.parent( selector ).not( \"body\" ).each( function() {\n\t\t\tjQuery( this ).replaceWith( this.childNodes );\n\t\t} );\n\t\treturn this;\n\t}\n} );\n\n\njQuery.expr.pseudos.hidden = function( elem ) {\n\treturn !jQuery.expr.pseudos.visible( elem );\n};\njQuery.expr.pseudos.visible = function( elem ) {\n\treturn !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );\n};\n\n\n\n\njQuery.ajaxSettings.xhr = function() {\n\ttry {\n\t\treturn new window.XMLHttpRequest();\n\t} catch ( e ) {}\n};\n\nvar xhrSuccessStatus = {\n\n\t\t// File protocol always yields status code 0, assume 200\n\t\t0: 200,\n\n\t\t// Support: IE <=9 only\n\t\t// #1450: sometimes IE returns 1223 when it should be 204\n\t\t1223: 204\n\t},\n\txhrSupported = jQuery.ajaxSettings.xhr();\n\nsupport.cors = !!xhrSupported && ( \"withCredentials\" in xhrSupported );\nsupport.ajax = xhrSupported = !!xhrSupported;\n\njQuery.ajaxTransport( function( options ) {\n\tvar callback, errorCallback;\n\n\t// Cross domain only allowed if supported through XMLHttpRequest\n\tif ( support.cors || xhrSupported && !options.crossDomain ) {\n\t\treturn {\n\t\t\tsend: function( headers, complete ) {\n\t\t\t\tvar i,\n\t\t\t\t\txhr = options.xhr();\n\n\t\t\t\txhr.open(\n\t\t\t\t\toptions.type,\n\t\t\t\t\toptions.url,\n\t\t\t\t\toptions.async,\n\t\t\t\t\toptions.username,\n\t\t\t\t\toptions.password\n\t\t\t\t);\n\n\t\t\t\t// Apply custom fields if provided\n\t\t\t\tif ( options.xhrFields ) {\n\t\t\t\t\tfor ( i in options.xhrFields ) {\n\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Override mime type if needed\n\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n\t\t\t\t}\n\n\t\t\t\t// X-Requested-With header\n\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n\t\t\t\t// For same-domain requests, won't change header if already provided.\n\t\t\t\tif ( !options.crossDomain && !headers[ \"X-Requested-With\" ] ) {\n\t\t\t\t\theaders[ \"X-Requested-With\" ] = \"XMLHttpRequest\";\n\t\t\t\t}\n\n\t\t\t\t// Set headers\n\t\t\t\tfor ( i in headers ) {\n\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n\t\t\t\t}\n\n\t\t\t\t// Callback\n\t\t\t\tcallback = function( type ) {\n\t\t\t\t\treturn function() {\n\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\tcallback = errorCallback = xhr.onload =\n\t\t\t\t\t\t\t\txhr.onerror = xhr.onabort = xhr.onreadystatechange = null;\n\n\t\t\t\t\t\t\tif ( type === \"abort\" ) {\n\t\t\t\t\t\t\t\txhr.abort();\n\t\t\t\t\t\t\t} else if ( type === \"error\" ) {\n\n\t\t\t\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t\t\t\t// On a manual native abort, IE9 throws\n\t\t\t\t\t\t\t\t// errors on any property access that is not readyState\n\t\t\t\t\t\t\t\tif ( typeof xhr.status !== \"number\" ) {\n\t\t\t\t\t\t\t\t\tcomplete( 0, \"error\" );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tcomplete(\n\n\t\t\t\t\t\t\t\t\t\t// File: protocol always yields status 0; see #8605, #14207\n\t\t\t\t\t\t\t\t\t\txhr.status,\n\t\t\t\t\t\t\t\t\t\txhr.statusText\n\t\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tcomplete(\n\t\t\t\t\t\t\t\t\txhrSuccessStatus[ xhr.status ] || xhr.status,\n\t\t\t\t\t\t\t\t\txhr.statusText,\n\n\t\t\t\t\t\t\t\t\t// Support: IE <=9 only\n\t\t\t\t\t\t\t\t\t// IE9 has no XHR2 but throws on binary (trac-11426)\n\t\t\t\t\t\t\t\t\t// For XHR2 non-text, let the caller handle it (gh-2498)\n\t\t\t\t\t\t\t\t\t( xhr.responseType || \"text\" ) !== \"text\"  ||\n\t\t\t\t\t\t\t\t\ttypeof xhr.responseText !== \"string\" ?\n\t\t\t\t\t\t\t\t\t\t{ binary: xhr.response } :\n\t\t\t\t\t\t\t\t\t\t{ text: xhr.responseText },\n\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders()\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t};\n\n\t\t\t\t// Listen to events\n\t\t\t\txhr.onload = callback();\n\t\t\t\terrorCallback = xhr.onerror = callback( \"error\" );\n\n\t\t\t\t// Support: IE 9 only\n\t\t\t\t// Use onreadystatechange to replace onabort\n\t\t\t\t// to handle uncaught aborts\n\t\t\t\tif ( xhr.onabort !== undefined ) {\n\t\t\t\t\txhr.onabort = errorCallback;\n\t\t\t\t} else {\n\t\t\t\t\txhr.onreadystatechange = function() {\n\n\t\t\t\t\t\t// Check readyState before timeout as it changes\n\t\t\t\t\t\tif ( xhr.readyState === 4 ) {\n\n\t\t\t\t\t\t\t// Allow onerror to be called first,\n\t\t\t\t\t\t\t// but that will not handle a native abort\n\t\t\t\t\t\t\t// Also, save errorCallback to a variable\n\t\t\t\t\t\t\t// as xhr.onerror cannot be accessed\n\t\t\t\t\t\t\twindow.setTimeout( function() {\n\t\t\t\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\t\t\t\terrorCallback();\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Create the abort callback\n\t\t\t\tcallback = callback( \"abort\" );\n\n\t\t\t\ttry {\n\n\t\t\t\t\t// Do send the request (this may raise an exception)\n\t\t\t\t\txhr.send( options.hasContent && options.data || null );\n\t\t\t\t} catch ( e ) {\n\n\t\t\t\t\t// #14683: Only rethrow if this hasn't been notified as an error yet\n\t\t\t\t\tif ( callback ) {\n\t\t\t\t\t\tthrow e;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n} );\n\n\n\n\n// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)\njQuery.ajaxPrefilter( function( s ) {\n\tif ( s.crossDomain ) {\n\t\ts.contents.script = false;\n\t}\n} );\n\n// Install script dataType\njQuery.ajaxSetup( {\n\taccepts: {\n\t\tscript: \"text/javascript, application/javascript, \" +\n\t\t\t\"application/ecmascript, application/x-ecmascript\"\n\t},\n\tcontents: {\n\t\tscript: /\\b(?:java|ecma)script\\b/\n\t},\n\tconverters: {\n\t\t\"text script\": function( text ) {\n\t\t\tjQuery.globalEval( text );\n\t\t\treturn text;\n\t\t}\n\t}\n} );\n\n// Handle cache's special case and crossDomain\njQuery.ajaxPrefilter( \"script\", function( s ) {\n\tif ( s.cache === undefined ) {\n\t\ts.cache = false;\n\t}\n\tif ( s.crossDomain ) {\n\t\ts.type = \"GET\";\n\t}\n} );\n\n// Bind script tag hack transport\njQuery.ajaxTransport( \"script\", function( s ) {\n\n\t// This transport only deals with cross domain requests\n\tif ( s.crossDomain ) {\n\t\tvar script, callback;\n\t\treturn {\n\t\t\tsend: function( _, complete ) {\n\t\t\t\tscript = jQuery( \"<script>\" ).prop( {\n\t\t\t\t\tcharset: s.scriptCharset,\n\t\t\t\t\tsrc: s.url\n\t\t\t\t} ).on(\n\t\t\t\t\t\"load error\",\n\t\t\t\t\tcallback = function( evt ) {\n\t\t\t\t\t\tscript.remove();\n\t\t\t\t\t\tcallback = null;\n\t\t\t\t\t\tif ( evt ) {\n\t\t\t\t\t\t\tcomplete( evt.type === \"error\" ? 404 : 200, evt.type );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\t// Use native DOM manipulation to avoid our domManip AJAX trickery\n\t\t\t\tdocument.head.appendChild( script[ 0 ] );\n\t\t\t},\n\t\t\tabort: function() {\n\t\t\t\tif ( callback ) {\n\t\t\t\t\tcallback();\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t}\n} );\n\n\n\n\nvar oldCallbacks = [],\n\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n\n// Default jsonp settings\njQuery.ajaxSetup( {\n\tjsonp: \"callback\",\n\tjsonpCallback: function() {\n\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + \"_\" + ( nonce++ ) );\n\t\tthis[ callback ] = true;\n\t\treturn callback;\n\t}\n} );\n\n// Detect, normalize options and install callbacks for jsonp requests\njQuery.ajaxPrefilter( \"json jsonp\", function( s, originalSettings, jqXHR ) {\n\n\tvar callbackName, overwritten, responseContainer,\n\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n\t\t\t\"url\" :\n\t\t\ttypeof s.data === \"string\" &&\n\t\t\t\t( s.contentType || \"\" )\n\t\t\t\t\t.indexOf( \"application/x-www-form-urlencoded\" ) === 0 &&\n\t\t\t\trjsonp.test( s.data ) && \"data\"\n\t\t);\n\n\t// Handle iff the expected data type is \"jsonp\" or we have a parameter to set\n\tif ( jsonProp || s.dataTypes[ 0 ] === \"jsonp\" ) {\n\n\t\t// Get callback name, remembering preexisting value associated with it\n\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n\t\t\ts.jsonpCallback() :\n\t\t\ts.jsonpCallback;\n\n\t\t// Insert callback into url or form data\n\t\tif ( jsonProp ) {\n\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, \"$1\" + callbackName );\n\t\t} else if ( s.jsonp !== false ) {\n\t\t\ts.url += ( rquery.test( s.url ) ? \"&\" : \"?\" ) + s.jsonp + \"=\" + callbackName;\n\t\t}\n\n\t\t// Use data converter to retrieve json after script execution\n\t\ts.converters[ \"script json\" ] = function() {\n\t\t\tif ( !responseContainer ) {\n\t\t\t\tjQuery.error( callbackName + \" was not called\" );\n\t\t\t}\n\t\t\treturn responseContainer[ 0 ];\n\t\t};\n\n\t\t// Force json dataType\n\t\ts.dataTypes[ 0 ] = \"json\";\n\n\t\t// Install callback\n\t\toverwritten = window[ callbackName ];\n\t\twindow[ callbackName ] = function() {\n\t\t\tresponseContainer = arguments;\n\t\t};\n\n\t\t// Clean-up function (fires after converters)\n\t\tjqXHR.always( function() {\n\n\t\t\t// If previous value didn't exist - remove it\n\t\t\tif ( overwritten === undefined ) {\n\t\t\t\tjQuery( window ).removeProp( callbackName );\n\n\t\t\t// Otherwise restore preexisting value\n\t\t\t} else {\n\t\t\t\twindow[ callbackName ] = overwritten;\n\t\t\t}\n\n\t\t\t// Save back as free\n\t\t\tif ( s[ callbackName ] ) {\n\n\t\t\t\t// Make sure that re-using the options doesn't screw things around\n\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n\n\t\t\t\t// Save the callback name for future use\n\t\t\t\toldCallbacks.push( callbackName );\n\t\t\t}\n\n\t\t\t// Call if it was a function and we have a response\n\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n\t\t\t\toverwritten( responseContainer[ 0 ] );\n\t\t\t}\n\n\t\t\tresponseContainer = overwritten = undefined;\n\t\t} );\n\n\t\t// Delegate to script\n\t\treturn \"script\";\n\t}\n} );\n\n\n\n\n// Support: Safari 8 only\n// In Safari 8 documents created via document.implementation.createHTMLDocument\n// collapse sibling forms: the second one becomes a child of the first one.\n// Because of that, this security measure has to be disabled in Safari 8.\n// https://bugs.webkit.org/show_bug.cgi?id=137337\nsupport.createHTMLDocument = ( function() {\n\tvar body = document.implementation.createHTMLDocument( \"\" ).body;\n\tbody.innerHTML = \"<form></form><form></form>\";\n\treturn body.childNodes.length === 2;\n} )();\n\n\n// Argument \"data\" should be string of html\n// context (optional): If specified, the fragment will be created in this context,\n// defaults to document\n// keepScripts (optional): If true, will include scripts passed in the html string\njQuery.parseHTML = function( data, context, keepScripts ) {\n\tif ( typeof data !== \"string\" ) {\n\t\treturn [];\n\t}\n\tif ( typeof context === \"boolean\" ) {\n\t\tkeepScripts = context;\n\t\tcontext = false;\n\t}\n\n\tvar base, parsed, scripts;\n\n\tif ( !context ) {\n\n\t\t// Stop scripts or inline event handlers from being executed immediately\n\t\t// by using document.implementation\n\t\tif ( support.createHTMLDocument ) {\n\t\t\tcontext = document.implementation.createHTMLDocument( \"\" );\n\n\t\t\t// Set the base href for the created document\n\t\t\t// so any parsed elements with URLs\n\t\t\t// are based on the document's URL (gh-2965)\n\t\t\tbase = context.createElement( \"base\" );\n\t\t\tbase.href = document.location.href;\n\t\t\tcontext.head.appendChild( base );\n\t\t} else {\n\t\t\tcontext = document;\n\t\t}\n\t}\n\n\tparsed = rsingleTag.exec( data );\n\tscripts = !keepScripts && [];\n\n\t// Single tag\n\tif ( parsed ) {\n\t\treturn [ context.createElement( parsed[ 1 ] ) ];\n\t}\n\n\tparsed = buildFragment( [ data ], context, scripts );\n\n\tif ( scripts && scripts.length ) {\n\t\tjQuery( scripts ).remove();\n\t}\n\n\treturn jQuery.merge( [], parsed.childNodes );\n};\n\n\n/**\n * Load a url into a page\n */\njQuery.fn.load = function( url, params, callback ) {\n\tvar selector, type, response,\n\t\tself = this,\n\t\toff = url.indexOf( \" \" );\n\n\tif ( off > -1 ) {\n\t\tselector = stripAndCollapse( url.slice( off ) );\n\t\turl = url.slice( 0, off );\n\t}\n\n\t// If it's a function\n\tif ( jQuery.isFunction( params ) ) {\n\n\t\t// We assume that it's the callback\n\t\tcallback = params;\n\t\tparams = undefined;\n\n\t// Otherwise, build a param string\n\t} else if ( params && typeof params === \"object\" ) {\n\t\ttype = \"POST\";\n\t}\n\n\t// If we have elements to modify, make the request\n\tif ( self.length > 0 ) {\n\t\tjQuery.ajax( {\n\t\t\turl: url,\n\n\t\t\t// If \"type\" variable is undefined, then \"GET\" method will be used.\n\t\t\t// Make value of this field explicit since\n\t\t\t// user can override it through ajaxSetup method\n\t\t\ttype: type || \"GET\",\n\t\t\tdataType: \"html\",\n\t\t\tdata: params\n\t\t} ).done( function( responseText ) {\n\n\t\t\t// Save response for use in complete callback\n\t\t\tresponse = arguments;\n\n\t\t\tself.html( selector ?\n\n\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n\t\t\t\t// Exclude scripts to avoid IE 'Permission Denied' errors\n\t\t\t\tjQuery( \"<div>\" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :\n\n\t\t\t\t// Otherwise use the full result\n\t\t\t\tresponseText );\n\n\t\t// If the request succeeds, this function gets \"data\", \"status\", \"jqXHR\"\n\t\t// but they are ignored because response was set above.\n\t\t// If it fails, this function gets \"jqXHR\", \"status\", \"error\"\n\t\t} ).always( callback && function( jqXHR, status ) {\n\t\t\tself.each( function() {\n\t\t\t\tcallback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );\n\t\t\t} );\n\t\t} );\n\t}\n\n\treturn this;\n};\n\n\n\n\n// Attach a bunch of functions for handling common AJAX events\njQuery.each( [\n\t\"ajaxStart\",\n\t\"ajaxStop\",\n\t\"ajaxComplete\",\n\t\"ajaxError\",\n\t\"ajaxSuccess\",\n\t\"ajaxSend\"\n], function( i, type ) {\n\tjQuery.fn[ type ] = function( fn ) {\n\t\treturn this.on( type, fn );\n\t};\n} );\n\n\n\n\njQuery.expr.pseudos.animated = function( elem ) {\n\treturn jQuery.grep( jQuery.timers, function( fn ) {\n\t\treturn elem === fn.elem;\n\t} ).length;\n};\n\n\n\n\n/**\n * Gets a window from an element\n */\nfunction getWindow( elem ) {\n\treturn jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;\n}\n\njQuery.offset = {\n\tsetOffset: function( elem, options, i ) {\n\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n\t\t\tposition = jQuery.css( elem, \"position\" ),\n\t\t\tcurElem = jQuery( elem ),\n\t\t\tprops = {};\n\n\t\t// Set position first, in-case top/left are set even on static elem\n\t\tif ( position === \"static\" ) {\n\t\t\telem.style.position = \"relative\";\n\t\t}\n\n\t\tcurOffset = curElem.offset();\n\t\tcurCSSTop = jQuery.css( elem, \"top\" );\n\t\tcurCSSLeft = jQuery.css( elem, \"left\" );\n\t\tcalculatePosition = ( position === \"absolute\" || position === \"fixed\" ) &&\n\t\t\t( curCSSTop + curCSSLeft ).indexOf( \"auto\" ) > -1;\n\n\t\t// Need to be able to calculate position if either\n\t\t// top or left is auto and position is either absolute or fixed\n\t\tif ( calculatePosition ) {\n\t\t\tcurPosition = curElem.position();\n\t\t\tcurTop = curPosition.top;\n\t\t\tcurLeft = curPosition.left;\n\n\t\t} else {\n\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n\t\t}\n\n\t\tif ( jQuery.isFunction( options ) ) {\n\n\t\t\t// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)\n\t\t\toptions = options.call( elem, i, jQuery.extend( {}, curOffset ) );\n\t\t}\n\n\t\tif ( options.top != null ) {\n\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n\t\t}\n\t\tif ( options.left != null ) {\n\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n\t\t}\n\n\t\tif ( \"using\" in options ) {\n\t\t\toptions.using.call( elem, props );\n\n\t\t} else {\n\t\t\tcurElem.css( props );\n\t\t}\n\t}\n};\n\njQuery.fn.extend( {\n\toffset: function( options ) {\n\n\t\t// Preserve chaining for setter\n\t\tif ( arguments.length ) {\n\t\t\treturn options === undefined ?\n\t\t\t\tthis :\n\t\t\t\tthis.each( function( i ) {\n\t\t\t\t\tjQuery.offset.setOffset( this, options, i );\n\t\t\t\t} );\n\t\t}\n\n\t\tvar docElem, win, rect, doc,\n\t\t\telem = this[ 0 ];\n\n\t\tif ( !elem ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Support: IE <=11 only\n\t\t// Running getBoundingClientRect on a\n\t\t// disconnected node in IE throws an error\n\t\tif ( !elem.getClientRects().length ) {\n\t\t\treturn { top: 0, left: 0 };\n\t\t}\n\n\t\trect = elem.getBoundingClientRect();\n\n\t\t// Make sure element is not hidden (display: none)\n\t\tif ( rect.width || rect.height ) {\n\t\t\tdoc = elem.ownerDocument;\n\t\t\twin = getWindow( doc );\n\t\t\tdocElem = doc.documentElement;\n\n\t\t\treturn {\n\t\t\t\ttop: rect.top + win.pageYOffset - docElem.clientTop,\n\t\t\t\tleft: rect.left + win.pageXOffset - docElem.clientLeft\n\t\t\t};\n\t\t}\n\n\t\t// Return zeros for disconnected and hidden elements (gh-2310)\n\t\treturn rect;\n\t},\n\n\tposition: function() {\n\t\tif ( !this[ 0 ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar offsetParent, offset,\n\t\t\telem = this[ 0 ],\n\t\t\tparentOffset = { top: 0, left: 0 };\n\n\t\t// Fixed elements are offset from window (parentOffset = {top:0, left: 0},\n\t\t// because it is its only offset parent\n\t\tif ( jQuery.css( elem, \"position\" ) === \"fixed\" ) {\n\n\t\t\t// Assume getBoundingClientRect is there when computed position is fixed\n\t\t\toffset = elem.getBoundingClientRect();\n\n\t\t} else {\n\n\t\t\t// Get *real* offsetParent\n\t\t\toffsetParent = this.offsetParent();\n\n\t\t\t// Get correct offsets\n\t\t\toffset = this.offset();\n\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], \"html\" ) ) {\n\t\t\t\tparentOffset = offsetParent.offset();\n\t\t\t}\n\n\t\t\t// Add offsetParent borders\n\t\t\tparentOffset = {\n\t\t\t\ttop: parentOffset.top + jQuery.css( offsetParent[ 0 ], \"borderTopWidth\", true ),\n\t\t\t\tleft: parentOffset.left + jQuery.css( offsetParent[ 0 ], \"borderLeftWidth\", true )\n\t\t\t};\n\t\t}\n\n\t\t// Subtract parent offsets and element margins\n\t\treturn {\n\t\t\ttop: offset.top - parentOffset.top - jQuery.css( elem, \"marginTop\", true ),\n\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, \"marginLeft\", true )\n\t\t};\n\t},\n\n\t// This method will return documentElement in the following cases:\n\t// 1) For the element inside the iframe without offsetParent, this method will return\n\t//    documentElement of the parent window\n\t// 2) For the hidden or detached element\n\t// 3) For body or html element, i.e. in case of the html node - it will return itself\n\t//\n\t// but those exceptions were never presented as a real life use-cases\n\t// and might be considered as more preferable results.\n\t//\n\t// This logic, however, is not guaranteed and can change at any point in the future\n\toffsetParent: function() {\n\t\treturn this.map( function() {\n\t\t\tvar offsetParent = this.offsetParent;\n\n\t\t\twhile ( offsetParent && jQuery.css( offsetParent, \"position\" ) === \"static\" ) {\n\t\t\t\toffsetParent = offsetParent.offsetParent;\n\t\t\t}\n\n\t\t\treturn offsetParent || documentElement;\n\t\t} );\n\t}\n} );\n\n// Create scrollLeft and scrollTop methods\njQuery.each( { scrollLeft: \"pageXOffset\", scrollTop: \"pageYOffset\" }, function( method, prop ) {\n\tvar top = \"pageYOffset\" === prop;\n\n\tjQuery.fn[ method ] = function( val ) {\n\t\treturn access( this, function( elem, method, val ) {\n\t\t\tvar win = getWindow( elem );\n\n\t\t\tif ( val === undefined ) {\n\t\t\t\treturn win ? win[ prop ] : elem[ method ];\n\t\t\t}\n\n\t\t\tif ( win ) {\n\t\t\t\twin.scrollTo(\n\t\t\t\t\t!top ? val : win.pageXOffset,\n\t\t\t\t\ttop ? val : win.pageYOffset\n\t\t\t\t);\n\n\t\t\t} else {\n\t\t\t\telem[ method ] = val;\n\t\t\t}\n\t\t}, method, val, arguments.length );\n\t};\n} );\n\n// Support: Safari <=7 - 9.1, Chrome <=37 - 49\n// Add the top/left cssHooks using jQuery.fn.position\n// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347\n// getComputedStyle returns percent when specified for top/left/bottom/right;\n// rather than make the css module depend on the offset module, just check for it here\njQuery.each( [ \"top\", \"left\" ], function( i, prop ) {\n\tjQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,\n\t\tfunction( elem, computed ) {\n\t\t\tif ( computed ) {\n\t\t\t\tcomputed = curCSS( elem, prop );\n\n\t\t\t\t// If curCSS returns percentage, fallback to offset\n\t\t\t\treturn rnumnonpx.test( computed ) ?\n\t\t\t\t\tjQuery( elem ).position()[ prop ] + \"px\" :\n\t\t\t\t\tcomputed;\n\t\t\t}\n\t\t}\n\t);\n} );\n\n\n// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\njQuery.each( { Height: \"height\", Width: \"width\" }, function( name, type ) {\n\tjQuery.each( { padding: \"inner\" + name, content: type, \"\": \"outer\" + name },\n\t\tfunction( defaultExtra, funcName ) {\n\n\t\t// Margin is only for outerHeight, outerWidth\n\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== \"boolean\" ),\n\t\t\t\textra = defaultExtra || ( margin === true || value === true ? \"margin\" : \"border\" );\n\n\t\t\treturn access( this, function( elem, type, value ) {\n\t\t\t\tvar doc;\n\n\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n\n\t\t\t\t\t// $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)\n\t\t\t\t\treturn funcName.indexOf( \"outer\" ) === 0 ?\n\t\t\t\t\t\telem[ \"inner\" + name ] :\n\t\t\t\t\t\telem.document.documentElement[ \"client\" + name ];\n\t\t\t\t}\n\n\t\t\t\t// Get document width or height\n\t\t\t\tif ( elem.nodeType === 9 ) {\n\t\t\t\t\tdoc = elem.documentElement;\n\n\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n\t\t\t\t\t// whichever is greatest\n\t\t\t\t\treturn Math.max(\n\t\t\t\t\t\telem.body[ \"scroll\" + name ], doc[ \"scroll\" + name ],\n\t\t\t\t\t\telem.body[ \"offset\" + name ], doc[ \"offset\" + name ],\n\t\t\t\t\t\tdoc[ \"client\" + name ]\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn value === undefined ?\n\n\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n\t\t\t\t\tjQuery.css( elem, type, extra ) :\n\n\t\t\t\t\t// Set width or height on the element\n\t\t\t\t\tjQuery.style( elem, type, value, extra );\n\t\t\t}, type, chainable ? margin : undefined, chainable );\n\t\t};\n\t} );\n} );\n\n\njQuery.fn.extend( {\n\n\tbind: function( types, data, fn ) {\n\t\treturn this.on( types, null, data, fn );\n\t},\n\tunbind: function( types, fn ) {\n\t\treturn this.off( types, null, fn );\n\t},\n\n\tdelegate: function( selector, types, data, fn ) {\n\t\treturn this.on( types, selector, data, fn );\n\t},\n\tundelegate: function( selector, types, fn ) {\n\n\t\t// ( namespace ) or ( selector, types [, fn] )\n\t\treturn arguments.length === 1 ?\n\t\t\tthis.off( selector, \"**\" ) :\n\t\t\tthis.off( types, selector || \"**\", fn );\n\t}\n} );\n\njQuery.parseJSON = JSON.parse;\n\n\n\n\n// Register as a named AMD module, since jQuery can be concatenated with other\n// files that may use define, but not via a proper concatenation script that\n// understands anonymous AMD modules. A named AMD is safest and most robust\n// way to register. Lowercase jquery is used because AMD module names are\n// derived from file names, and jQuery is normally delivered in a lowercase\n// file name. Do this after creating the global so that if an AMD module wants\n// to call noConflict to hide this version of jQuery, it will work.\n\n// Note that for maximum portability, libraries that are not jQuery should\n// declare themselves as anonymous modules, and avoid setting a global if an\n// AMD loader is present. jQuery is a special case. For more information, see\n// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon\n\nif ( typeof define === \"function\" && define.amd ) {\n\tdefine( \"jquery\", [], function() {\n\t\treturn jQuery;\n\t} );\n}\n\n\n\n\nvar\n\n\t// Map over jQuery in case of overwrite\n\t_jQuery = window.jQuery,\n\n\t// Map over the $ in case of overwrite\n\t_$ = window.$;\n\njQuery.noConflict = function( deep ) {\n\tif ( window.$ === jQuery ) {\n\t\twindow.$ = _$;\n\t}\n\n\tif ( deep && window.jQuery === jQuery ) {\n\t\twindow.jQuery = _jQuery;\n\t}\n\n\treturn jQuery;\n};\n\n// Expose jQuery and $ identifiers, even in AMD\n// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)\n// and CommonJS for browser emulators (#13566)\nif ( !noGlobal ) {\n\twindow.jQuery = window.$ = jQuery;\n}\n\n\n\n\n\nreturn jQuery;\n} );\n"
  },
  {
    "path": "assets/vendor/string_score.coffee",
    "content": "---\n---\n###!\n * string_score.js: Quicksilver-like string scoring algorithm.\n *\n * Copyright (C) 2009-2011 Joshaven Potter <yourtech@gmail.com>\n * Copyright (C) 2010-2011 Yesudeep Mangalapilly <yesudeep@gmail.com>\n * MIT license: http://www.opensource.org/licenses/mit-license.php\n ###\n\n# Special thanks to Lachie Cox and Quicksilver for inspiration.\n#\n# Compilation notes:\n#\n# 1. Compile with the `-b -c` flags to the coffee-script compiler\n\n# `String.prototype.score`\n# ------------------------\nString::score = (abbreviation) ->\n    # **Size optimization notes**:\n    # Declaring `string` before checking for an exact match\n    # does not affect the speed and reduces size because `this`\n    # occurs only once in the code as a result.\n    string = this\n    \n    # Perfect match if the string equals the abbreviation.\n    return 1.0 if string == abbreviation\n\n    # Initializing variables.\n    string_length = string.length\n    total_character_score = 0\n\n    # Awarded only if the string and the abbreviation have a common prefix.\n    should_award_common_prefix_bonus = 0 #no\n    \n    #### Sum character scores\n    \n    # Add up scores for each character in the abbreviation.\n    for c, i in abbreviation\n        # Find the index of current character (case-insensitive) in remaining part of string.\n        index_c_lowercase = string.indexOf c.toLowerCase()\n        index_c_uppercase = string.indexOf c.toUpperCase()\n        min_index = Math.min index_c_lowercase, index_c_uppercase\n        index_in_string = if min_index > -1 then min_index else Math.max index_c_lowercase, index_c_uppercase        \n\n        #### Identical strings\n        # Bail out if current character is not found (case-insensitive) in remaining part of string.\n        #\n        # **Possible size optimization**:\n        # Replace `index_in_string == -1` with `index_in_string < 0`\n        # which has fewer characters and should have identical performance.\n        return 0 if index_in_string == -1\n        \n        # Set base score for current character.\n        character_score = 0.1\n        \n\n        #### Case-match bonus\n        # If the current abbreviation character has the same case \n        # as that of the character in the string, we add a bonus.\n        #\n        # **Optimization notes**:\n        # `charAt` was replaced with an index lookup here because \n        # the latter results in smaller and faster code without\n        # breaking any tests.\n        if string[index_in_string] == c\n            character_score += 0.1\n        \n        #### Consecutive character match and common prefix bonuses\n        # Increase the score when each consecutive character of\n        # the abbreviation matches the first character of the \n        # remaining string.\n        #\n        # **Size optimization disabled (truthiness shortened)**:\n        # It produces smaller code but is slower.\n        #\n        #     if !index_in_string\n        if index_in_string == 0\n            character_score += 0.8\n            # String and abbreviation have common prefix, so award bonus. \n            #\n            # **Size optimization disabled (truthiness shortened)**:\n            # It produces smaller code but is slower.\n            #\n            #     if !i\n            if i == 0\n                should_award_common_prefix_bonus = 1 #yes\n        \n        #### Acronym bonus\n        # Typing the first character of an acronym is as\n        # though you preceded it with two perfect character\n        # matches.\n        #\n        # **Size optimization disabled**:\n        # `string.charAt(index)` wasn't replaced with `string[index]`\n        # in this case even though the latter results in smaller\n        # code (when minified) because the former is faster, and \n        # the gain out of replacing it is negligible.\n        if string.charAt(index_in_string - 1) == ' '\n            character_score += 0.8 # * Math.min(index_in_string, 5) # Cap bonus at 0.4 * 5\n        \n        # Left trim the matched part of the string\n        # (forces sequential matching).\n        string = string.substring(index_in_string + 1, string_length)\n \n        # Add to total character score.\n        total_character_score += character_score\n    \n    # **Feature disabled**:\n    # Uncomment the following to weigh smaller words higher.\n    #\n    #     return total_character_score / string_length\n    \n    abbreviation_length = abbreviation.length\n    abbreviation_score = total_character_score / abbreviation_length\n    \n    #### Reduce penalty for longer strings\n    \n    # **Optimization notes (code inlined)**:\n    #\n    #     percentage_of_matched_string = abbreviation_length / string_length\n    #     word_score = abbreviation_score * percentage_of_matched_string\n    #     final_score = (word_score + abbreviation_score) / 2\n    final_score = ((abbreviation_score * (abbreviation_length / string_length)) + abbreviation_score) / 2\n    \n    #### Award common prefix bonus\n    if should_award_common_prefix_bonus and (final_score + 0.1 < 1)\n        final_score += 0.1\n    \n    return final_score\n"
  },
  {
    "path": "blog/authors.html",
    "content": "---\nindex: false\n---\n\n{% assign posts_by_author = site.posts | group_by: \"author\" %}\n\n<section class=\"grid-2_sm-1\">\n  {% for author_posts in posts_by_author %}\n    {% if author_posts.name != \"\" %}\n      {% assign author_info = site.data.authors[author_posts.name] %}\n      <div class=\"col\" id=\"{{ author_posts.name }}\">\n        <h2>{{ author_info.name | default: author_posts.name }}</h2>\n\n        <div class=\"description\">\n          {{ author_info.description | markdownify }}\n        </div>\n\n        <ul class=\"social\">\n          {% if author_info.twitter %}\n            <li class=\"twitter\"><span class=\"label\">Twitter:</span> <a href=\"https://twitter.com/{{ author_info.twitter }}\">@{{ author_info.twitter }}</a></li>\n          {% endif %}\n\n          {% if author_info.googleplus %}\n            <li class=\"googleplus\"><span class=\"label\">Google Plus:</span> <a href=\"https://googleplus.com/{{ author_info.googleplus }}\">{{ author_info.googleplus }}</a></li>\n          {% endif %}\n\n          {% if author_info.facebook %}\n            <li class=\"facebook\"><span class=\"label\">Facebook:</span> <a href=\"https://facebook.com/{{ author_info.facebook }}\">{{ author_info.facebook }}</a></li>\n          {% endif %}\n        </ul>\n\n        {% assign article_number = author_posts.items | size %}\n        <h3>\n          {{ article_number}} article{% if article_number != 1 %}s{% endif %}\n        </h3>\n        <ul>\n          {% for _post in author_posts.items %}\n            <li>\n              <a href=\"{{ site.baseurl }}{{ _post.url }}\">{{ _post.title }}</a>\n            </li>\n          {% endfor %}\n        </ul>\n      </div>\n    {% endif %}\n  {% endfor %}\n</section>\n"
  },
  {
    "path": "blog/category/index.md",
    "content": "---\ntitle: Blog categories\nindex: false\n---\n\n{% for category in site.categories %}\n  {% capture filename %}{{\n    page.path | replace: 'index', category[0]\n    }}{% endcapture %}\n\n  {% assign cat_page = site.pages | where: 'path', filename | first %}\n\n{% if cat_page.path %}\n* [{{ category[0] | capitalize }}]({{ cat_page.url }})\n{% endif %}\n{% endfor %}\n"
  },
  {
    "path": "blog/category/linux.md",
    "content": "---\ntitle: Blog posts\nindex: false\n---\n\n{% include posts_category.html %}\n"
  },
  {
    "path": "blog/category/release.md",
    "content": "---\ntitle: Blog posts\nindex: false\n---\n\n{% include posts_category.html %}\n"
  },
  {
    "path": "blog/category/tutorial.md",
    "content": "---\ntitle: Blog posts\nindex: false\n---\n\n{% include posts_category.html %}\n"
  },
  {
    "path": "blog/feeds/all.atom.xml",
    "content": "---\nlayout: null\n---\n{% include feed.html %}\n"
  },
  {
    "path": "blog/feeds/index.md",
    "content": "---\ntitle: Atom Feeds\n---\n\nFollow [the blog]({{ site.baseurl }}/blog/) in an feed reader! Subscribe to our Atom (similar to RSS) feed:\n\n- [All blog posts](all.atom.xml)\n\n### Category-filtered Atom feeds\n\n- [Release blog posts](release.atom.xml)\n- [Tutorial blog posts](tutorial.atom.xml)\n"
  },
  {
    "path": "blog/feeds/linux.atom.xml",
    "content": "---\nlayout: null\n---\n{% include feed_category.html %}\n"
  },
  {
    "path": "blog/feeds/release.atom.xml",
    "content": "---\nlayout: null\n---\n{% include feed_category.html %}\n"
  },
  {
    "path": "blog/feeds/tutorial.atom.xml",
    "content": "---\nlayout: null\n---\n{% include feed_category.html %}\n"
  },
  {
    "path": "blog/index.html",
    "content": "---\ntitle: Blog posts\nindex: false\n---\n\n{% capture md %}\nYou can also [Subscribe to Atom feeds]({{ site.baseurl }}/blog/feeds/) in a feed reader.\n{% endcapture %}\n\n{{ md | markdownify }}\n\n{% include posts.html posts=paginator.posts %}\n{% include pagination.html %}\n"
  },
  {
    "path": "blog/tags.html",
    "content": "---\nindex: false\n---\n\n{% capture tag_downcase %}{% for tag in site.tags %}{{ tag[0] | downcase }}:::{{ tag[0] }}|||{% endfor %}{% endcapture %}\n{% assign tag_downcase = tag_downcase | split: \"|||\" | sort %}\n\n<section class=\"tag-cloud\">\n  <h2>All Tags</h2>\n\n  {% assign max_height = 1 %}\n  {% for tag in site.tags %}\n    {% if tag[1].size > max_height %}\n      {% assign max_height = tag[1].size | plus: 0.0 %}\n    {% endif %}\n  {% endfor %}\n\n  {% for tagline in tag_downcase %}\n    {% assign tag_info = tagline | split: \":::\" %}\n    {% assign tag_label = tag_info[0] %}\n    {% assign tag_title = tag_info[1] %}\n    {% assign tag_id = tag_label | replace: \" \", \"-\" | urlencode | remove: \".\" %}\n    {% assign size = site.tags[tag_title].size | divided_by: max_height | add: 1 | times: 100 | plus: 100 %}\n\n    {% unless tag_label == previous_tag %}\n      <span class=\"tag\" style=\"font-size:{{ size }}%\">\n        <a href=\"#{{ tag_id }}\">{{ tag_title }}</a>\n      </span>\n    {% endunless %}\n\n    {% assign previous_tag = tag_label %}\n  {% endfor %}\n</section>\n\n{% assign taglist = \"\" | split: \",\" %}\n\n{% for tagline in tag_downcase %}\n  {% assign tag_info = tagline | split: \":::\" %}\n  {% assign tag_label = tag_info[0] %}\n  {% assign tag_title = tag_info[1] %}\n  {% assign tag_id = tag_label | replace: \" \", \"-\" | urlencode %}\n\n  {% unless tag_label == previous_tag %}\n    {% assign title = tag_title | prepend: \"## \" %}\n    {% assign taglist = taglist | push: \"\" %}\n    {% assign taglist = taglist | push: title %}\n  {% endunless %}\n\n  {% for post in site.tags[tag_title] %}\n    {% assign FOOli = '* <time class=\"published\" datetime=\"{{ post.date | date_to_xmlschema }}\">{{ post.date | date_to_string }}</time> ({{ post.title }})[{{ site.baseurl }}{{ post.url }}\">{{ post.title }}' %}\n    {% assign datestring = post.date | date_to_string | prepend: '<span class=\"published\">' | append: '</span>' %}\n    {% assign li = \"* \" | append: datestring | append: \" [\" | append: post.title | append: \"](\" | append: site.baseurl | append: post.url | append: \")\" %}\n    {% assign taglist = taglist | push: li %}\n  {% endfor %}\n\n  {% assign previous_tag = tag_label %}\n{% endfor %}\n\n<section class=\"tag-list\">{{ taglist | join: \"\n\" | markdownify | replace: \"<span\", \"<time\" | replace: \"span>\", \"time>\" }}</section>\n"
  },
  {
    "path": "code-of-conduct.md",
    "content": "---\ntitle: Contributor Covenant 3.0 Code of Conduct\n---\n\n## Our Pledge\n\nWe pledge to make our community welcoming, safe, and equitable for all.\n\nWe are committed to fostering an environment that respects and promotes the dignity, rights, and contributions of all individuals, regardless of characteristics including race, ethnicity, caste, color, age, physical characteristics, neurodiversity, disability, sex or gender, gender identity or expression, sexual orientation, language, philosophy or religion, national or social origin, socio-economic position, level of education, or other status. The same privileges of participation are extended to everyone who participates in good faith and in accordance with this Covenant.\n\n## Encouraged Behaviors\n\nWhile acknowledging differences in social norms, we all strive to meet our community's expectations for positive behavior. We also understand that our words and actions may be interpreted differently than we intend based on culture, background, or native language.\n\nWith these considerations in mind, we agree to behave mindfully toward each other and act in ways that center our shared values, including:\n\n1. Respecting the **purpose of our community**, our activities, and our ways of gathering.\n2. Engaging **kindly and honestly** with others.\n3. Respecting **different viewpoints** and experiences.\n4. **Taking responsibility** for our actions and contributions.\n5. Gracefully giving and accepting **constructive feedback**.\n6. Committing to **repairing harm** when it occurs.\n7. Behaving in other ways that promote and sustain the **well-being of our community**.\n\n\n## Restricted Behaviors\n\nWe agree to restrict the following behaviors in our community. Instances, threats, and promotion of these behaviors are violations of this Code of Conduct.\n\n1. **Harassment.** Violating explicitly expressed boundaries or engaging in unnecessary personal attention after any clear request to stop.\n2. **Character attacks.** Making insulting, demeaning, or pejorative comments directed at a community member or group of people.\n3. **Stereotyping or discrimination.** Characterizing anyone’s personality or behavior on the basis of immutable identities or traits.\n4. **Sexualization.** Behaving in a way that would generally be considered inappropriately intimate in the context or purpose of the community.\n5. **Violating confidentiality**. Sharing or acting on someone's personal or private information without their permission.\n6. **Endangerment.** Causing, encouraging, or threatening violence or other harm toward any person or group.\n7. Behaving in other ways that **threaten the well-being** of our community.\n\n### Other Restrictions\n\n1. **Misleading identity.** Impersonating someone else for any reason, or pretending to be someone else to evade enforcement actions.\n2. **Failing to credit sources.** Not properly crediting the sources of content you contribute.\n3. **Promotional materials**. Sharing marketing or other commercial content in a way that is outside the norms of the community.\n4. **Irresponsible communication.** Failing to responsibly present content which includes, links or describes any other restricted behaviors.\n\n\n## Reporting an Issue\n\nTensions can occur between community members even when they are trying their best to collaborate. Not every conflict represents a code of conduct violation, and this Code of Conduct reinforces encouraged behaviors and norms that can help avoid conflicts and minimize harm.\n\nWhen an incident does occur, it is important to report it promptly. To report a possible violation, **reported by contacting one or more team members, including:**\n{%\n  include email.html\n    name=\"Freya\"\n    username=\"freya\"\n    domain=\"venefilyn.se\"\n    after=\", and \"\n  %}{%\n  include email.html\n    name=\"Martin\"\n    username=\"martin\"\n    domain=\"piware.de\"\n    after=\".\"\n  %}{%\n  include email.html\n    script=true\n%}\n\nCommunity Moderators take reports of violations seriously and will make every effort to respond in a timely manner. They will investigate all reports of code of conduct violations, reviewing messages, logs, and recordings, or interviewing witnesses and other participants. Community Moderators will keep investigation and enforcement actions as transparent as possible while prioritizing safety and confidentiality. In order to honor these values, enforcement actions are carried out in private with the involved parties, but communicating to the whole community may be part of a mutually agreed upon resolution.\n\n\n## Addressing and Repairing Harm\n\n****\n\nIf an investigation by the Community Moderators finds that this Code of Conduct has been violated, the following enforcement ladder may be used to determine how best to repair harm, based on the incident's impact on the individuals involved and the community as a whole. Depending on the severity of a violation, lower rungs on the ladder may be skipped.\n\n1. Warning\n   1. Event: A violation involving a single incident or series of incidents.\n   2. Consequence: A private, written warning from the Community Moderators.\n   3. Repair: Examples of repair include a private written apology, acknowledgement of responsibility, and seeking clarification on expectations.\n2. Temporarily Limited Activities\n   1. Event: A repeated incidence of a violation that previously resulted in a warning, or the first incidence of a more serious violation.\n   2. Consequence: A private, written warning with a time-limited cooldown period designed to underscore the seriousness of the situation and give the community members involved time to process the incident. The cooldown period may be limited to particular communication channels or interactions with particular community members.\n   3. Repair: Examples of repair may include making an apology, using the cooldown period to reflect on actions and impact, and being thoughtful about re-entering community spaces after the period is over.\n3. Temporary Suspension\n   1. Event: A pattern of repeated violation which the Community Moderators have tried to address with warnings, or a single serious violation.\n   2. Consequence: A private written warning with conditions for return from suspension. In general, temporary suspensions give the person being suspended time to reflect upon their behavior and possible corrective actions.\n   3. Repair: Examples of repair include respecting the spirit of the suspension, meeting the specified conditions for return, and being thoughtful about how to reintegrate with the community when the suspension is lifted.\n4. Permanent Ban\n   1. Event: A pattern of repeated code of conduct violations that other steps on the ladder have failed to resolve, or a violation so serious that the Community Moderators determine there is no way to keep the community safe with this person as a member.\n   2. Consequence: Access to all community spaces, tools, and communication channels is removed. In general, permanent bans should be rarely used, should have strong reasoning behind them, and should only be resorted to if working through other remedies has failed to change the behavior.\n   3. Repair: There is no possible repair in cases of this severity.\n\nThis enforcement ladder is intended as a guideline. It does not limit the ability of Community Managers to use their discretion and judgment, in keeping with the best interests of our community.\n\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public or other spaces. Examples of representing our community include using an official email address, posting via an official social media account, or acting as an appointed representative at an online or offline event.\n\n\n## Attribution\n\nThis Code of Conduct is adapted from the Contributor Covenant, version 3.0, permanently available at [https://www.contributor-covenant.org/version/3/0/](https://www.contributor-covenant.org/version/3/0/).\n\nContributor Covenant is stewarded by the Organization for Ethical Source and licensed under CC BY-SA 4.0. To view a copy of this license, visit [https://creativecommons.org/licenses/by-sa/4.0/](https://creativecommons.org/licenses/by-sa/4.0/)\n\nFor answers to common questions about Contributor Covenant, see the FAQ at [https://www.contributor-covenant.org/faq](https://www.contributor-covenant.org/faq). Translations are provided at [https://www.contributor-covenant.org/translations](https://www.contributor-covenant.org/translations). Additional enforcement and community guideline resources can be found at [https://www.contributor-covenant.org/resources](https://www.contributor-covenant.org/resources). The enforcement ladder was inspired by the work of [Mozilla’s code of conduct team](https://github.com/mozilla/inclusion).\n"
  },
  {
    "path": "documentation.md",
    "content": "---\ntitle: Cockpit documentation\n---\n\n## Installation\n\nTo get Cockpit installed and running on your system, follow the instructions on the [installation and running page](/running.html).\n\nAfter Cockpit is running, visit **ip-address-of-machine:9090** in your web browser. If your browser is on the same machine where Cockpit is running, then visit [localhost:9090](http://localhost:9090/) (for example).\n\n## Usage\n\n[The Red Hat Customer Portal product documentation pages](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/managing_systems_using_the_rhel_9_web_console/index) document how to use the \"web console\" (another name for Cockpit). While this is specifically for the version of Cockpit that ships in Red Hat Enterprise Linux, the interface and its usage is similar on other distributions where the Cockpit web console exists.\n\n### Red Hat Enterprise Linux 9 documentation\n\nThe documentation for Red Hat Enterprise Linux 9 is the most up-to-date.\n\n- [Managing systems using the RHEL 9 web console](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/9/html/managing_systems_using_the_rhel_9_web_console/index)\n\n### Red Hat Enterprise Linux 8 documentation\n\nWhile this documentation is for an older version of Cockpit, most is still current enough and there may be more detailed information:\n\n- [Getting started using the RHEL web console](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/getting-started-with-the-rhel-8-web-console_system-management-using-the-rhel-8-web-console)\n- [Managing user accounts in the web console](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/managing-user-accounts-in-the-web-console_system-management-using-the-rhel-8-web-console)\n- [Managing systems using the RHEL 8 web console](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/8/html/managing_systems_using_the_rhel_8_web_console/)\n\n### SUSE Linux Enterprise Micro documentation\n- [Administering SUSE Linux Enterprise Micro using Cockpit](https://documentation.suse.com/cockpit)\n\n## Cockpit Guide\n\nThe [Cockpit guide](guide/latest/) contains:\n\n1. [Deployment guide](guide/latest/guide.html) with everything you need to know about deployment beyond what's covered on the installation page.\n2. [Feature internals](guide/latest/features.html) cover the parts of the system Cockpit communicates with.\n3. [Developer guide](guide/latest/development.html) contains topics such as embedding and integrating Cockpit, packages, and the Cockpit API.\n\nMore [developer-focused resources are on the contribute page](external/wiki/Contributing.html).\n\n## Additional help\n\n- [Frequently Asked Questions (FAQ)](faq.html)\n- [Cockpit's forum @ GitHub Discussions](https://github.com/cockpit-project/cockpit/discussions/)\n"
  },
  {
    "path": "external/bots/README.md",
    "content": "---\ntitle: Cockpit Bots\nsource: https://github.com/cockpit-project/bots/blob/master/README.md\n---\n\nThese are automated bots and tools that work on Cockpit. This includes updating\noperating system images, updating translations or NPM modules, testing PRs, and\nmore.\n\n## Images\n\nIn order to test Cockpit-related projects, they are staged into an operating\nsystem image. These images are tracked in the `images/` directory. For example,\nyou might want to test a scenario where Cockpit on one machine talks to FreeIPA\non another, and you want those two machines to use different images.\n\nThis is handled by passing a specific image to image-create\nand other scripts that work with test machine images. Available images include:\n\n - `fedora-*`, `rhel-*`, `debian-*`, etc: Various operating systems for testing Cockpit related projects\n - `services`: Auxiliary network services for tests which are independent from\n   the OS where Cockpit runs: FreeIPA, Samba AD, candlepin, Grafana\n\nThese well known image names are expected to contain no `.`\ncharacters and have no file name extension.\n\nIndividual projects are expected to locally build their code into packages, and\ninstall them as overlay on top of these pristine images, with `image-customize`\nor using the [machine Python API](./machine/machine_core/).\n\nFor managing these images:\n\n - `image-download`: Download selected or all test images\n - `image-create`: Create test machine images from scratch (usually through\n   downloading a cloud image), with common build and test dependencies for\n   Cockpit projects preinstalled\n - `image-upload`: Upload a locally built test image to the official image servers\n\nFor running and debugging the images:\n\n - `image-customize`: Install packages, upload files, or run commands in a test\n   machine image; this keeps the original image intact, and puts the changes\n   into an image overlay into test/images/.\n - `vm-run`: Run a test machine image; by default this happens in an ephemeral\n   overlay. You can use the `--maintain` option to write into the persistent\n   overlay in test/images/ instead.\n - `vm-reset`: Remove all overlays from test/images/\n\n## Image location\n\nDownloaded images are stored into ~/.cache/cockpit-images/ by default. If you\nwant to change that, you can set `$COCKPIT_IMAGES_DATA_DIR` or the\n`cockpit.bots.images-data-dir` variable with `git config` to a directory where\nto store the pristine virtual machine images.  For example:\n\n    git config cockpit.bots.images-data-dir /srv/cockpit/images\n\n## Tests\n\nThe bots automatically run the tests as needed on pull requests\nand branches. To check when and where tests will be run, use the\ntests-scan tool:\n\n    ./tests-scan -vd\n\n#### Note on eslintrc interaction\n\nAs eslint looks for additional configurations, eslintrc.(json|yaml) files, in\nparent directories, it is recommended to have `\"root\": true` in the eslint\nconfiguration of any project which is using eslint and is tested through\ncockpit-bots.\n\n## Integration with GitHub\n\nA number of machines are watching our GitHub repositories and are\nexecuting tests for pull requests as well as making new images.\n\nMost of this happens automatically, but you can influence their\nactions with the tests-trigger utility in this directory.\n\n### Setup\n\nYou need a GitHub token in ~/.config/cockpit-dev/github-token or from\nthe [GitHub CLI](https://cli.github.com/) configuration in\n~/.config/gh/config.yml.  You can create one for your account at\n[Developer Settings → Personal access tokens](https://github.com/settings/tokens).\n\nWhen generating a new personal access token, the scopes should contain\n`repo:status` and `read:org`. Note in particular, that `repo` and\n`public_repo` scopes each grant full push access, and should not be used.\n\nYou need at least \"Write\" access to the project for triggering statuses, either\nindividually per repo (e.g. [cockpit](https://github.com/cockpit-project/cockpit/settings/access)\nor for [all cockpit-project repos](https://github.com/orgs/cockpit-project/teams/committers).\n\nIf you'd like to download Red Hat-only internal images from S3, you'll\nneed to create a key file in `~/.config/cockpit-dev/s3-keys/[domain]`.\nThe `[domain]` can be any non-toplevel domain which contains the S3 URL\nin question.  The contents of this file should be a single line\ncontaining the \"access key\" and the \"secret key\" separated by\nwhitespace.\n\nFor the currently configured mirrors this means that you'd likely have the\nfollowing file:\n\n- `~/.config/cockpit-dev/s3-keys/linodeobjects.com`\n\nFor more control, you could also use the following:\n\n- `~/.config/cockpit-dev/s3-keys/cockpit-images.eu-central-1.linodeobjects.com`\n- `~/.config/cockpit-dev/s3-keys/eu-central-1.linodeobjects.com`\n- either of the above, with `us-east` instead of `eu-central`\n\neach file would be a single line which looks like\n\n```\nEEVIDIDFSOQ0ABJ2LGTT    009rKOypIoqO44Q3VQGRyYPfugi84zANHF0pOW9f\n```\n\nThe \"access key\" and \"secret key\" is unique per-developer and can be\nobtained by talking to Allison.\n\n### Test contexts\n\nFor describing tests which we want to run we use __contexts__. A context has the form:\n\n    image[/scenario][@bots#bots_pr][@owner/project/ref]\n\nwhere items have the following meaning:\n- image: Name of the image on which tests should run (e.g. 'fedora-coreos').\n- scenario: Name of a specific test. This is specific for each separate project and\n  is passed verbatim to 'test/run' in `$TEST_SCENARIO`.\n- bots_pr: Number of pull request that exists in bots repository. When specified,\n  bots from this PR would be used instead of main.\n- owner/project: Name of github project (e.g. 'cockpit-project/cockpit'). This part can\n  be omitted when testing in the same project and no 'ref' is needed.\n- ref: Reference in the project (usually branch) (e.g. 'rhel-8.2'). Default is\n  the project's primary branch.\n\nFor example, context for scenario 'firefox' on 'fedora-coreos' is:\n\n    fedora-coreos/firefox\n\nIf we want to trigger it on 'cockpit-project/cockpit':\n\n    fedora-coreos/firefox@cockpit-project/cockpit\n\nIf we want to also not run it on the primary branch, but on 'rhel-8-0' branch:\n\n    fedora-coreos/firefox@cockpit-project/cockpit/rhel-8-0\n\nIf we want to run tests on 'fedora-coreos' but with bots from pull request '169':\n\n    fedora-coreos@bots#169\n\n### Retrying a failed test\n\nIf you want to run the \"fedora-coreos\" testsuite again for pull\nrequest #1234 of cockpit-project/cockpit, run tests-trigger like so:\n\n    ./tests-trigger --repo cockpit-project/cockpit 1234 fedora-coreos\n\nYou can also invoke bots/tests/trigger from any project checkout, in which case\nyou don't need the explicit `--repo` -- it will default to the GitHub origin of\nthe current directory's project.\n\n### Testing a pull request by a non-allowed user\n\nIf you want to run all tests on pull request #1234 that has been opened by\nsomeone who does not have push access to the repository nor isn't in the\n[allowlist](https://github.com/cockpit-project/bots/blob/main/lib/allowlist.py)\nrun tests-trigger with `--allow`:\n\n    ./tests-trigger --allow [...]\n\nOf course, you should make sure that the pull request is proper and\ndoesn't execute evil code during tests.\n\n### tests-trigger with a different origin\n\nIf you need to specify --repo in tests-trigger as your remote is different from\ncockpit-project/cockpit, you can set a git configuration option from which\ntests-trigger reads the repo. This has to be set per cockpit project.\n\n    git config cockpit.bots.github-repo cockpit-project/cockpit\n\n### Refreshing a test image\n\nTest images are refreshed automatically once per week, and even if the\nlast refresh has failed, the machines wait one week before trying again.\n\nIf you want the machines to refresh the fedora-coreos image immediately,\nrun image-trigger like so:\n\n    ./image-trigger fedora-coreos\n\n### Creating new images for a pull request\n\nIf as part of some new feature you need to change the content of some\nor all images, you can ask the machines to create those images.\n\nIf you want to have a new fedora-coreos image for pull request #1234, add\na bullet point to that pull request's description like so, and add the\n\"bot\" label to the pull request.\n\n    * [ ] image-refresh fedora-coreos\n\nThe machines will post comments to the pull request about their\nprogress and at the end there will be links to commits with the new\nimages.  You can then include these commits into the pull request in\nany way you like.\n\n### Creating a new image\n\nCreating a new image from scratch requires some\n[images/scripts/](./images/scripts) files. For a new image called `tux` we need:\n\n- `tux.bootstrap`: Download or create an initial qcow2 image which boots and has SSH\n  acccess. If available, this should be the latest available cloud image,\n  but it may also invoke some other VM build tool or build service.\n  This script runs in the [cockpit/tasks](https://github.com/cockpit-project/cockpituous/tree/main/tasks/container)\n  container, and thus can only use the tools installed there. If necessary, add\n  them first.\n- `tux.setup`: The setup script runs inside the downloaded test image,\n  install all required build and test dependencies, and sets up an `admin`\n  user.\n\nFor a new image it is recommended to follow the existing setup/bootstrap scripts,\nfor example the `fedora` one.\n\nRun `./image-create -v tux` to build the image. If that succeeds, a new image\nis saved in `images` as `images/tux` (a symlink to the real qcow2 file).\nTest-boot it with `./vm-run tux`, and ensure you can:\n\n - Log in with SSH as the `admin` and `root` user with our usual test SSH key\n - Become root with `sudo` as admin works (password \"foobar\")\n\nTo add that image to our CI, create a PR and follow the \"Creating new\nimages for a pull request\" section. External contributors will need to ask a\nCockpit team member to create a copy of the PR and follow this workflow.\n\nFor the initial PR it is recommended to add the new image to the `_manual`\ntestmap of `starter-kit` or other project to prove that the created image is\nfunctional.\n\n### Updating CI to a new Fedora release\n\n`TEST_OS_DEFAULT` is usually set to the latest (stable) Fedora released,\nused as default OS for test VMs.\n\n1. If this is a new image, add `_manual` test contexts for the new image to `lib/testmap.py`, and land that into `main`.\n2. Create a PR that updates `TEST_OS_DEFAULT` in `lib/constants.py`, and trigger all tests for that image there.\n\n#### Fedora CoreOS\n\nThe Fedora CoreOS image is updated to a new Fedora release out of our\ncontrol, when this occurs:\n\n1. Update the naughty symlink `naughty/fedora-coreos` to the release\n   CoreOS uses.\n2. Update `OSTREE_BUILD_IMAGE` to point to the Fedora release CoreOS\n   uses.\n\n#### Debian Testing\n\nSometimes packages are dropped out of the Debian testing repositories, when\nthis happens apply a temporary hack to fetch the package from `unstable` using\nthis 954f12fae1d2854e14c543e333338482a012c50d as example.\n\n####  Pixel tests\n\nThe pixel tests used in Cockpit projects use `test/reference-image` to\ndetermine what image to run the pixel tests on.\n\n1. Create a PR which updates `test/reference-image`.\n2. Update the pixel tests if required."
  },
  {
    "path": "external/source/HACKING.md",
    "content": "---\ntitle: Hacking on Cockpit\nsource: https://github.com/cockpit-project/cockpit/blob/master/HACKING.md\n---\n\nStart by getting the code:\n\n    git clone https://github.com/cockpit-project/cockpit\n    cd cockpit/\n\nThe remainder of the commands assume you're in the top level of the\nCockpit git repository checkout.\n\n**Do not clone a fork!** This will not work for various reasons (missing tags,\ndetermining version, integration with bots commands). Please keep `origin` as\nthe read-only actual upstream project, and add your fork as a separate writable\nremote, for example with\n\n    git remote add my git@github.com:yourgithubid/cockpit.git\n\n## Setting up development container\n\nThe cockpit team maintains a [cockpit/tasks container](https://ghcr.io/cockpit-project/tasks)\nfor both local development and CI. If you can install [toolbx](https://containertoolbx.org/) or\n[distrobox](https://distrobox.privatedns.org/) on your system, it is highly\nrecommended to do that:\n\n - It is *the* official environment for CI, known to work, and gives you reproducible results.\n - It avoids having to install development packages on your main machine.\n - It avoids having to map the build and test dependencies to package names of various distributions.\n\n1. Install `toolbox`\n\n   - Fedora/CentOS/RHEL based distributions:\n\n         sudo dnf install toolbox\n\n   - Debian/Ubuntu based distributions:\n\n         sudo apt install podman-toolbox\n\n2. Create a development toolbox for Cockpit\n\n       toolbox create --image ghcr.io/cockpit-project/tasks -c cockpit\n\n3. Enter the toolbox:\n\n       toolbox enter cockpit\n\nYour home directory, user D-Bus, etc. are shared with the host, so you can\nedit files as you normally would. Building and running tests happens inside the\ntoolbox container. If desired, you can install additional packages with\n`sudo dnf install`.\n\nThe Cockpit team occasionally refreshes the `tasks` container image.\nTo re-create your development container from the latest image, run:\n\n    podman pull ghcr.io/cockpit-project/tasks\n    toolbox rm cockpit\n\n...and then repeat steps 2 and 3 from above.\n\n## Working on Cockpit's session pages\n\nMost contributors want to work on the web (HTML, JavaScript, CSS) parts of Cockpit.\n\n### Install Cockpit\n\nFirst, install Cockpit on your local machine as described in:\n\n<https://cockpit-project.org/running.html>\n\n### Build session pages\n\nNext, run this command from your top level Cockpit checkout directory, and make\nsure to run it as the same user that you'll use to log into Cockpit below.\n\n    mkdir -p ~/.local/share/\n    ln -s $(pwd)/dist ~/.local/share/cockpit\n\nThis will cause Cockpit to read JavaScript, HTML, and CSS files directly from the\nlocally built package output directory instead of using the system-installed Cockpit\nfiles.\n\nThe recommended way to build bundles is to use the \"watch\" mode\n(`-w` or`--watch`) on the page you are working on. For example, if you want to\nwork on anything in [pkg/systemd](https://github.com/cockpit-project/cockpit/tree/main/pkg/systemd/), run:\n\n    ./build.js -w systemd\n\nSee [pkg/](https://github.com/cockpit-project/cockpit/tree/main/pkg) for a list of all pages.\n\nIf you work on a change that affects multiple pages (such as a file in\npkg/lib/), you can also build all pages:\n\n    ./build.js -w\n\nNow you can log into Cockpit on your local Linux machine at the following\naddress, using the same username and password as your desktop login:\n\n<http://localhost:9090>\n\nWatch mode automatically rebuilds when source files are modified. Once it\nfinishes building, refresh your browser to see the changes in Cockpit.\nPress `Ctrl-C` to stop watch mode when you are done changing the code.\n\n### Testing\n\nYou often need to test code changes in a VM. You can set the `$RSYNC` env\nvariable to copy the built page into the given SSH target's\n/usr/local/share/cockpit/ directory. If you use Cockpit's own test VMs and set up the\nSSH `c` alias as described in [test/README.md](./test/README.md), you can use\none of these commands:\n\n    RSYNC=c ./build.js -w kdump\n    RSYNC=c ./build.js -w\n\n### Returning to system packages\n\nTo make Cockpit use system packages again, instead of your checkout directory,\nremove the symlink with the following command and log back into Cockpit:\n\n    rm ~/.local/share/cockpit\n\n## Building and unit tests\n\nCockpit uses autotools, so there are familiar `./configure` script and\nMakefile targets.\n\nAfter a fresh clone of the Cockpit sources, you need to prepare them by running\n`autogen.sh` like this:\n\n    ./autogen.sh --prefix=/usr --enable-debug\n\nAs shown, `autogen.sh` runs 'configure' with the given options, and it also\nprepares the build tree by downloading various nodejs dependencies.\n\nWhen working with a Git clone, it is best to always run `./autogen.sh`\ninstead of `./configure`.\n\nThen run\n\n    make\n\nto build everything. Cockpit has a single non-recursive Makefile. You can only\nrun `make` from the top-level and it will always rebuild the whole project.\n\nYou can run unit tests of the current checkout:\n\n    make check\n\nThese should finish very quickly. It is a good practice to do this often.\n\nFor debugging individual tests, there are compiled binaries in the build\ndirectory. For QUnit tests (JavaScript), you can run\n\n    ./test-server\n\nwhich will output a URL to connect to with a browser, such as\n<http://localhost:8765/qunit/base1/test-dbus.html>. Adjust the path for different\ntests and inspect the results there.\n\nQUnit tests are run as part of a pytest test called `test_browser`.  You can\nrun individual tests via `pytest -k`, like so:\n\n    pytest -k test-fsinfo.html\n\nYou can see JavaScript code coverage information for QUnit tests.  For a\nsummary table:\n\n    pytest -k test_browser --js-cov\n\nAnd for detailed output on uncovered sections in a specific file, something\nlike:\n\n    pytest -k test-fsinfo.html --js-cov-files='*/fsinfo.ts'\n\nCoverage information is gathered into the pytest tmpdir, regardless of which\ncoverage-related commandline flags are given, so it's also possible to drill\ndown after the fact — without re-running tests — using something like:\n\n    test/common/js_coverage.py -m '*/fsinfo.ts' /tmp/pytest-of-*/pytest-current/js-coverage/*\n\nThere are also static code and syntax checks which you should run often:\n\n    test/common/static-code\n\nIt is highly recommended to set up a git pre-push hook, to avoid pushing PRs\nthat will fail on trivial errors:\n\n    ln -s ../../tools/git-hook-pre-push .git/hooks/pre-push\n\nThis calls `test/common/static-code` for each commit you're trying to push.\n\nYou can also set up a post-commit hook to do the same, after each commit:\n\n    ln -s ../../tools/git-hook-post-commit .git/hooks/post-commit\n\nWe also have a hook to ameliorate one of the more annoying drawbacks of using\ngit submodules:\n\n    ln -s ../../tools/git-hook-pre-rebase .git/hooks/pre-rebase\n\n## Running the integration test suite\n\nRefer to the [testing README](test/README.md) for details on running the Cockpit\nintegration tests locally.\n\n## Bridge\n\nThe Cockpit bridge is the initial program launched in a Cockpit Linux session:\nIts stdin/out is connected to the web socket (and thus to JavaScript in the\n[pages](pkg/)), where it speaks a [JSON protocol](doc/protocol.md) that\nmultiplexes \"channels\" -- abstractions of operating system APIs that the pages\nuse to implement their functionality. This protocol is translated into\noperating system calls such as opening or writing files, D-Bus calls, or HTTP\nqueries. Think of the bridge as the moral equivalent of \"bash\" in a human SSH\nsession.\n\nThe bridge resides in `src/cockpit` with most of its rules in `src/Makefile.am`.\nThis directory was chosen because it matches the standard so-called \"src\nlayout\" convention for Python packages, where each package (`cockpit`) is a\nsubdirectory of the `src` directory.\n\n### Running the bridge\n\nThe bridge can be used interactively on a local machine out of the source tree:\n\n    PYTHONPATH=src python3 -m cockpit.bridge\n\nTo make it easy to test out channels without having to write out messages\nmanually, `cockpit.misc.print` can be used:\n\n    PYTHONPATH=src python3 -m cockpit.misc.print open fsinfo path=/etc 'attrs=[\"type\", \"entries\"]' | PYTHONPATH=src python3 -m cockpit.bridge\n\nThese shell aliases might be useful when experimenting with the protocol:\n\n    alias cpy='PYTHONPATH=src python3 -m cockpit.bridge'\n    alias cpf='PYTHONPATH=src python3 -m cockpit.misc.print'\n\nYou can then for example run a metrics channel:\n\n    cpf open metrics1 source=internal interval=1000 metrics='[{\"name\": \"cpu.basic.user\", \"derive\": \"rate\"}]' : wait | cpy\n\nTo enable debug logging in journal on a test image, you can pass `--debug` to\n`image-prepare`. This will set `COCKPIT_DEBUG=all` to `/etc/environment`, if\nyou are only interested channel debug messages change `all` to\n`cockpit.channel`.\n\n### Iterating on the bridge with the ws container\n\nOur fedora-coreos and -bootc images use the [cockpit/ws container](https://quay.io/repository/cockpit/ws)\ninstead of `cockpit-bridge.rpm`. You can do fast \"edit bridge\" → \"run\nintegration test\" iterations by modifying `MachineCase.login_and_go()` to\nupload the local dev tree bridge code to the VM, then onwards into the running\ncontainer, and bind-mount it into the correct path:\n\n```diff\n--- test/common/testlib.py\n+++ test/common/testlib.py\n@@ -1933,6 +1933,14 @@ class MachineCase(unittest.TestCase):\n         if enable_root_login:\n             self.enable_root_login()\n         self.machine.start_cockpit(tls=tls)\n+\n+        m = self.machine\n+        m.execute(\"umount /usr/lib/python3.14/site-packages/cockpit || true\")\n+        m.upload([\"../src/cockpit\"], \"/tmp/\")\n+        m.execute(\"podman cp /tmp/cockpit ws:/tmp/\")\n+        m.execute(\"podman exec ws mount -o bind /tmp/cockpit /usr/lib/python3.14/site-packages/cockpit\")\n+\n         # first load after starting cockpit tends to take longer, due to on-demand service start\n         with self.browser.wait_timeout(30):\n             self.browser.login_and_go(path, user=user, password=password, host=host, superuser=superuser,\n```\n\nReplace `3.14` with the Python version du jour.\n\n### Testing the bridge\n\nThere are a growing number of [pytest](https://docs.pytest.org) tests being written to test\nthe bridge code.  You can run these with `make pytest` or\n`make pytest-cov`.  Those are both just rules to make sure that the\n`systemd_ctypes` submodule is checked out before running `pytest` from the\nsource directory.\n\nThe tests require at least `pytest` 7.0.0 or higher to run.\n\n## Running eslint\n\nCockpit uses [ESLint](https://eslint.org/) to automatically check JavaScript\ncode style in `.js` and `.jsx` files.\n\nThe linter is executed as part of `test/common/static-code`.\n\nFor developer convenience, the ESLint can be started explicitly by:\n\n    npm run eslint\n\nMost rule violations can be automatically fixed by running:\n\n    npm run eslint:fix\n\nRules configuration can be found in the `.eslintrc.json` file.\n\nDuring fast iterative development, you can also choose to not run eslint, by\nrunning `./build.js` with the `-e`/`--no-eslint` option. This\nspeeds up the build and avoid build failures due to ill-formatted comments,\nunused identifiers, and other JavaScript-related issues.\n\n## Running stylelint\n\nCockpit uses [Stylelint](https://stylelint.io/) to automatically check CSS code\nstyle in `.css` and `.scss` files.\n\nThe linter is executed as part of `test/common/static-code`.\n\nFor developer convenience, the Stylelint can be started explicitly by:\n\n    npm run stylelint\n\nBut note that this only covers files in `pkg/`. `test/common/static-code` covers\n*all* (S)CSS files tracked in git.\n\nSome rule violations can be automatically fixed by running:\n\n    npm run stylelint:fix\n\nRules configuration can be found in the `.stylelintrc.json` file.\n\nDuring fast iterative development, you can also choose to not run stylelint, by\nrunning `./build.js` with the `-s`/`--no-stylelint` option. This speeds up the\nbuild and avoids build failures due to ill-formatted CSS or other issues.\n\n## Working on your local machine: systemd-sysext\n\nIf you want to safely test your local changes directly on it, Cockpit supports\ninstallation as a [systemd-sysext](https://www.freedesktop.org/software/systemd/man/latest/systemd-sysext.html).\nThis covers all parts of Cockpit (ws, tls, session, bridge, login page, systemd\nunits, PAM configuration, and the session pages) except for the SELinux policy.\nIt gets installed into `/run/extensions/`, so nothing ever hits the disk and\nthis also works on read-only installations (CoreOS, OSTree, bootc).\n\nJust run:\n\n    tools/make-sysext\n\nThis runs `./autogen.sh` if necessary, and then just re-`make`s your tree,\nre-installs it into `/run/extensions`, and reloads the sysext in systemd.\nAfterwards you can connect to http://localhost:9090 as usual.\n\nTo remove this, reboot or run\n\n    tools/make-sysext stop\n\n**Attention**: This is not currently compatible with SELinux in enforcing mode.\nIf you have that, you need to disable it:\n\n    sudo setenforce 0\n\n## Working on your local machine: Web server\n\nIf the above systemd-sysext approach does not work for you, you can also test\nchanges with some bind mounts.\n\nTo test changes to the login page, you can bind-mount the build tree's\n`dist/` directory over the system one:\n\n    sudo mount -o bind dist /usr/share/cockpit\n\nLikewise, to test changes to the branding, use:\n\n    sudo mount -o bind src/branding/ /usr/share/cockpit/branding/\n\nDo `mkdir dist/branding` if you run both of these commands at the same time.\n\nAfter that, run `systemctl stop cockpit.service` to ensure that the web server\nrestarts on the next browser request.\n\nTo make Cockpit use system-installed code again, umount the paths:\n\n    sudo umount /usr/share/cockpit /usr/share/cockpit/branding/\n    systemctl stop cockpit.service\n\nSimilarly, if you change `cockpit-ws` itself, you can make the system (systemd\nunits, cockpit-tls, etc.) use this:\n\n    sudo mount -o bind cockpit-ws /usr/libexec/cockpit-ws\n\nOn Debian-based OSes (including Ubuntu), the path will be\n`/usr/lib/cockpit/cockpit-ws` instead.\n\nOn Fedora, CentOS, Red Hat Enterprise Linux, and related distributions, you also\nneed to disable SELinux with:\n\n    sudo setenforce 0\n\nfor this to work, as your local build tree does not otherwise have the expected\nSELinux type.\n\nSome cockpit binaries rely on specific paths in /usr/share or libexecdir to be\nset correctly. By default they are set to `/usr/local`.\n\nOn RPM based systems, this can be set using an autogen.sh argument;\nafterwards you need to rebuild:\n\n    ./autogen.sh rpm\n\n## Installation from upstream sources\n\n    make\n    sudo make install\n\nThis will install Cockpit and all support files. If you have a\nFedora/RHEL/CentOS based distribution, install a PAM configuration with\n\n    sudo cp tools/cockpit.pam /etc/pam.d/cockpit\n\nIf you have a Debian/Ubuntu based distribution, install this PAM config instead:\n\n    sudo cp tools/cockpit.debian.pam /etc/pam.d/cockpit\n\nFor other distributions you need to create a PAM config yourself.\n\nIf you prefer to install to a different `--prefix` and would prefer\nthat `make install` not write outside that prefix, then specify the\n`--enable-prefix-only` option to `autogen.sh`. This will result in an\ninstallation of Cockpit that does not work without further tweaking.\nFor advanced users only.\n\n## Build distribution packages\n\nInstead of a direct `make install` as above, you can also build distribution\npackages and install them. This is generally more robust, as they upgrade and\nremove cleanly, and don't interfere with distribution packages in `/usr`.\n\nIn a Fedora/RHEL build environment you can build binary RPMs with\n\n    tools/make-rpms --quick\n\nIn a Debian/Ubuntu build environment you can build debs with\n\n    tools/make-debs --quick\n\n## Updating `node_modules`\n\nDuring a normal build from a git checkout, the `node_modules` will be\nautomatically unpacked from a cache kept in a separate git repository.  You can\nforce the unpack to occur using the `tools/node-modules checkout` command, but\nthis shouldn't be necessary.  In the event that you need to modify\n`package.json` (to install a new module, for example) then you'll need to run\n`tools/node-modules install` to create a new cache from the result of running\n`npm install` on your new `package.json`.\n\nYour locally rebuilt changes to `node_modules` won't be used by others.  A new\nversion will be created by a GitHub workflow when you open your pull request.\n\nThe `tools/node-modules` script inspects the `GITHUB_BASE` environment variable\nto determine the correct repository to use when fetching and pushing.  It will\nstrip the repository name (leaving the project- or username) and use the\n`node-cache.git` repository in that namespace.  If `GITHUB_BASE` is unset, it\nwill default to `cockpit-project/node-cache.git`.\n\nA local cache is maintained in `~/.cache/cockpit-dev`.\n\n## Contributing a change\n\nMake a pull request on github.com with your change. All changes get reviewed,\ntested, and iterated on before getting into Cockpit. The general workflow is\ndescribed in the [wiki](https://github.com/cockpit-project/cockpit/wiki/Workflow).\n\nYou need to be familiar with git to contribute a change. Do your changes\non a branch. Your change should be one or more git commits that each contain one\nsingle logical simple reviewable change, without modifications that are\nunrelated to the commit message.\n\nDon't feel bad if there's multiple steps back and forth asking for changes or\ntweaks before your change gets in. If you fix your commits after getting a\nreview, just force-push to your branch -- this will update the pull request\nautomatically. Do *not* close it and open a new one; that would destroy the\nconversation and reviews.\n\nCockpit is a designed project. Anything that the user will see should have\ndesign done first. This is done on the wiki and mailing list.\n\nBigger changes need to be discussed on the\n[#cockpit:fedoraproject.org](https://matrix.to/#/#cockpit:fedoraproject.org)\nMatrix channel or our mailing list\n[cockpit-devel@lists.fedoraproject.org](https://lists.fedorahosted.org/admin/lists/cockpit-devel.lists.fedorahosted.org/)\nbefore you invest too much time and energy.\n\nFeature changes should have a video and/or screenshots that show the change.\nThis video should be uploaded directly to GitHub on the pull request or issue\nor uploaded to YouTube or another service that allows video embedding.\n\nUse a command like this to record a video including the browser\nframe:\n\n```\nrecordmydesktop -x 1 -y 200 --width 1024 --height 576 \\\n   --fps 24 --freq 44100 --v_bitrate 2000000\n```\n\n(This command only works on X11 and requires the `recordmydesktop` program to\nbe installed.)\n\nYou can also resize your browser window and move it to the right location with\na script. In Firefox you can open the Scratchpad (`Shift+F4`) and enter the\nfollowing commands:\n\n    window.resizeTo(1024, 576);\n    window.moveTo(1, 200);\n\nThen run it with `Ctrl+R` when the browser is showing an empty tab, e.g.\n`about:newtab`. You may need to adjust the positions for your environment.\n\n## Adding a release note in PR\n\nOptional but highly quality of life feature we have relates to automatic\nrelease blog post generation.\n\nThere is an automated release note process for PRs where any PRs that include\na label `release-note` and contains a release note segment in the description\nwill be used when generating the release blog post for https://cockpit-project.org.\n\nTo create a release note you need a h2-header at the end of your PR description\nwhere everything underneath will be taken by the automation for the blog\ngeneration. It will also take any images and videos uploaded and add them to\nthe blog post PR as well. For example:\n\n```md\n[...truncated PR description...]\n\n## Release note title\n\nRelease note text that will be picked up by automation\n\n<img for release note>\n```\n\nYou can see this in action in [this cockpit-machines\nPR](https://github.com/cockpit-project/cockpit-machines/pull/2268) where we\nhave an h2-header together with text which in turn was taken by the\nautomation and shown inside [the blog\npost]({{ site.baseurl }}/blog/cockpit-347.html) for the release\nthat included it.\n\n## Debug logging\n\nAll messages from the various cockpit processes go to the journal and can be\nseen with commands like:\n\n    sudo journalctl -f\n\nCockpit's web server has verbose internal debug logging that can be enabled when\ntrying to track down a problem. To turn it on add a file to your system like\nthis:\n\n    sudo mkdir -p /etc/systemd/system/cockpit-wsinstance-http.service.d\n    sudo sh -c 'printf \"[Service]\\nEnvironment=G_MESSAGES_DEBUG=all\\n\" > /etc/systemd/system/cockpit-wsinstance-http.service.d/debug.conf'\n    sudo systemctl daemon-reload\n    sudo systemctl stop cockpit\n\nInstead of `all`, you can also specify a log domain:\n\n * cockpit-protocol: Very verbose low level traffic logging\n * cockpit-ws: Cockpit Web Service detailed debug messages\n * WebSocket: Verbose low level WebSocket logging\n\nTo revert the above logging changes:\n\n    sudo rm /etc/systemd/system/cockpit-wsinstance-http.service.d/debug.conf\n    sudo systemctl daemon-reload\n    sudo systemctl stop cockpit\n\nTo debug HTTPS connections, replace `http` with `https@` in the above commands.\n\nThe bridge runs in the user session, not in a systemd service. See \"Running the\nbridge\" section for how to enable debug logging.\n\n## Debug logging in Javascript console\n\nVarious javascript methods in Cockpit can show debug messages. You can turn them\non by setting a `window.debugging` global, or setting up a `debugging` property\nin the browser storage. To do this run the following in your javascript console:\n\n    >> sessionStorage.debugging = \"all\"\n\nYou'll notice that there's a ton of messages that get shown. If you\nwant to be more specific, instead of \"all\" use one or more of the following\nspecific types:\n\n    \"all\"      // All available debug messages\n    \"channel\"  // All channel messages sent to server\n    \"dbus\"     // DBus related debug messages\n    \"http\"     // HTTP (via the server) related debug messages\n    \"spawn\"    // Debug messages related to executing processes\n\nThere are other strings related to the code you may be working on. For example,\nthe metrics page shows debug information with the value `metrics`. Do\n`git grep window.debugging pkg` to find out all available ones.\n\nIn addition, if you want your debug setting to survive a browser refresh or\nCockpit log out, use something like:\n\n    >> localStorage.debugging = \"spawn\"\n\n## Using React Developer Tools\n\nCockpit uses React for the JavaScript frontend, [React Developer\nTools](https://react.dev/learn/react-developer-tools) is a browser extension to\ninspect React components, edit props and state. Out of the box the developer\ntools do not work with Cockpit due to the pages being loaded in a separate\niframe. A workaround is to load the page directly by embedding, for example for\nthe system overview page:\n\n<http://localhost:9090/cockpit/@localhost/system/index.html>\n\nThis loads the system overview as a standalone page allowing React Developer\ntools to inspect its state.\n\n## Running Cockpit processes under a debugger\n\nYou may want to run cockpit-ws under a debugger such as valgrind or gdb. You can\nrun these processes as your own user, although you won't be able to debug all\nthe authentication logic in those cases.\n\nFirst of all, make sure Cockpit is correctly installed. Even though we will be\nrunning `cockpit-ws` from the built sources, this still relies on some of the right\nsoftware being installed in order for Cockpit to work. (Such as: PAM stack,\nUI files, cockpit-bridge, etc.)\n\nThis is how you would run cockpit-ws under gdb:\n\n    export G_DEBUG=fatal-criticals\n    export G_MESSAGES_DEBUG=cockpit-ws,cockpit-wrapper,cockpit-bridge\n    gdb --args ./cockpit-ws --port 10000 --no-tls\n\nAnd you can run cockpit-ws and cockpit-bridge under valgrind like this:\n\n    export G_DEBUG=fatal-criticals\n    export G_MESSAGES_DEBUG=cockpit-ws,cockpit-wrapper,cockpit-bridge\n    valgrind --trace-children=yes --trace-children-skip='*unix_chkpwd*' \\\n          ./cockpit-ws --port 10000 --no-tls\n\nNote that cockpit-session and cockpit-bridge will run from the installed\nprefix, rather than your build tree.\n\n## Debug hard-to-grab elements\n\nIn most cases, you can use the browser debugger to directly attach breakpoints\nto interesting elements. But that's not directly possible with e.g. popup menus\nor other elements which react to `mouseenter`/`mouseleave`. For these, run this\nin the developer console:\n\n```js\nsetTimeout(() => { debugger }, 5000)\n```\n\nthen do the mouse action (like hovering over an element) and wait until the\ntimeout.\n\n## Start login session and web socket with curl\n\nFor iterating on the login / web socket ←→ bridge integration, this command\nlogs into our standard test VM (https://127.0.0.2:9091) and establishes the web\nsocket connection and user session:\n\n```sh\ncurl -ksS -D- -u admin:foobar --cookie-jar /tmp/cookie https://127.0.0.2:9091/cockpit/login --no-buffer -H\"Connection: Upgrade\" -H\"Upgrade: websocket\" -H\"Host: 127.0.0.2:9091\" -H\"Origin: https://127.0.0.2:9091\" -H\"Sec-Websocket-Key: 3sc2c9IzwRUc3BlSIYwtSA==\" -H\"Sec-WebSocket-Version: 13\" https://127.0.0.2:9091/cockpit/socket\n```\n\nIt replies with a message like\n```\n{\"csrf-token\":\"e3074fc5e06cb3804ad8c3463fc6727c67ac245dd3c39590e486644759a42818\"}HTTP/1.1 101 Switching Protocols\n```\n\nwhich contains the session token. You can use the `--cookie-jar` to issue\nfurther authenticated HTTP requests. Note that as there is no browser attached,\nthe session times out after some 10 seconds of inactivity.\n\n## Manually installing the development dependencies\n\n_If at all possible, use the cockpit/tasks container with toolbox/distrobox as\ndocumented above. Installing all necessary development packages manually on\nyour machine is intrusive, error prone, difficult, and hard to debug._\n\nYou will need at least node.js and NPM.\n\nOn Fedora or CentOS (>= 9):\n\n    sudo dnf install npm\n\nOn Debian/Ubuntu:\n\n    sudo apt install npm\n\nFor running tests, the following dependencies are required:\n\n    sudo dnf install curl expect xz rpm-build chromium-headless dbus-daemon \\\n        libvirt-daemon-driver-storage-core libvirt-daemon-driver-qemu libvirt-client python3-libvirt \\\n        python3-pyyaml\n\nFor compiling the C parts, you will need the package build dependencies:\n\n    sudo dnf install dnf-utils python-srpm-macros\n    sudo dnf builddep --spec tools/cockpit.spec"
  },
  {
    "path": "external/source/test/README.md",
    "content": "---\ntitle: Integration Tests of Cockpit\nsource: https://github.com/cockpit-project/cockpit/blob/master/test/README.md\n---\n\nThis directory contains automated integration tests for Cockpit, and the\nsupport files for them. The architecture of the automated integration tests is\ndescribed in [ARCHITECTURE](./ARCHITECTURE.md)\n\nTo run the tests on Fedora, refer to the [HACKING](../HACKING.md) guide for\ninstallation of all of the necessary build and test dependencies. There's\nno need to trigger a build manually - the test suite preparation step below\nwill handle that.\n\nIf test failures are encountered that look like they may be related to problems\nwith nested virtualization, refer to\n[this Fedora guide](https://docs.fedoraproject.org/en-US/quick-docs/using-nested-virtualization-in-kvm/index.html)\nfor more details and recommendations on ensuring it is enabled correctly.\n\n## Preparation and general invocation\n\n*Warning*: Never run the build, test, or any other command here as root!\n\nYou first need to build cockpit, and install it into a VM:\n\n    test/image-prepare\n\nThis uses the default OS image. See `$TEST_OS` below how to select a different one.\n\nSee `test/image-prepare --help` for some special modes, like skipping unit\ntests, building overlays, or preparing an image with the\n[cockpit/ws container](https://quay.io/repository/cockpit/ws) instead of RPMs.\nSee our scenarios in [test/run](./run) for how they are being used.\n\nIn most cases you want to run an individual test in a suite, for example:\n\n    test/verify/check-metrics TestCurrentMetrics.testCPU\n\nYou can get a list of tests by inspecting the `def test*` in the source, or by\nrunning the suite with `-l`/`--list`:\n\n    test/verify/check-metrics -l\n\nSometimes you may also want to run all tests in a test file suite:\n\n    test/verify/check-session\n\nTo see more verbose output from the test, use the `-v`/`--verbose` and/or `-t`/`--trace` flags:\n\n    test/verify/check-session --verbose --trace\n\nIf you specify `-s`/`--sit` in addition, then the test will wait on failure and\nallow you to log into cockpit and/or the test instance and diagnose the issue.\nThe cockpit and SSH addresses of the test instance will be printed:\n\n    test/verify/check-session -st\n\nYou can also run *all* the tests, with automatic parallelism:\n\n    test/common/run-tests --test-dir test/verify\n\nHowever, this will take *really* long. You can specify a subset of tests (see\n`--help`); but usually it's better to run individual tests locally, and let the\nCI machinery run all of them in a draft pull request.\n\nThe tests will automatically download the VM images they need, so expect\nthat the initial run may take a few minutes.\n\n## Interactive browser\n\nNormally each test starts its own chromium headless browser process on a\nseparate random port. To interactively follow what a test is doing:\n\n    TEST_SHOW_BROWSER=1 test/verify/check-session --trace\n\nYou can also run a test against Firefox instead of Chromium:\n\n    TEST_BROWSER=firefox test/verify/check-session --trace\n\nSee below for details.\n\n## Manual testing\n\nYou can conduct manual interactive testing against a test image by starting the\nimage like so:\n\n     bots/vm-run -s cockpit.socket arch\n\nOnce the machine is booted and the cockpit socket has been activated, a\nmessage will be printed describing how to access the virtual machine, via\nssh and web.  See the \"Helpful tips\" section below.\n\nTo login using the web client you have to use the username and password listed below. If you wish to enable `root` login using the web you can remove `root` from `/etc/cockpit/disallowed-users`.\n\n- Username: `admin`\n- Password: `foobar`\n\nBy default, it's only possible to contact the virtual machine from the host\nmachine on which it's running.   If you want to conduct manual testing from\nother devices on your network, set `TEST_BIND_GLOBAL=1`, for example:\n\n     TEST_BIND_GLOBAL=1 bots/vm-run -s cockpit.socket arch\n\nThis will bind the Cockpit and SSH ports to all interfaces, making it possible\nto access a URL like http://yourhost.local:9091/ to test Cockpit from another\nmachine on your LAN.\n\n## Pixel tests\n\nPixel tests in Cockpit ensure that updates of our dependencies or code changes\ndon't break the UI: for example slight changes of layout, padding, color and\neverything which isn't easily spotted by a human. They also give us confidence\nthat an update of our UI Framework doesn't introduce changes in how Cockpit\nlooks.\n\nPixel tests make a screenshot of a selector and compare it to a known good\nreference image. if there is a difference, the test fails and a pixel\ndifference is shown.\n\nThis works as our tests run in the [cockpit/tasks container](https://ghcr.io/cockpit-project/tasks)\nwhich pins the browser and font rendering so repeated runs provide the same\npixels. To generate new pixels, this tasks container must be used; your own\nbrowser and font rendering software might generate different results. For more\ninformation read the [\"introduction blog post\"]({{ site.baseurl }}/blog/pixel-testing.html).\n\nThe test images are stored in a git submodule in the `test/reference` directory\nand be fetched with:\n\n```sh\n./test/common/pixel-tests update\n```\n\nAs Cockpit tests under multiple distributions and it is not worth the effort to\nrun pixel tests on every supported distribution we only run them for the\nimage configured in `test/reference-image`.\n\nOur tests call `Browser.assert_pixels` at interesting and strategic places.\nThis assertion method requires at least a CSS selector and an image title.\nPixel tests are generated in five layouts by default: desktop, medium, mobile,\ndark and rtl.\n\nTake a screenshot of the content in `#detail-content`:\n```python\nbrowser.assert_pixels(\"#detail-content\", \"filesystem\")\n```\n\nTake a screenshot of the content in `#detail-content` and ignore all elements\nwith a class `disk-stats` as they change per test run:\n```python\nbrowser.assert_pixels(\"#detail-content\", \"filesystem\", ignore=[\".disks-stats\"])\n```\n\nTake a screenshot of the content in `#detail-content` and skip it for a\nspecific layout as it generates unstable pixels:\n```python\nbrowser.assert_pixels(\"#detail-content\", \"filesystem\", skip_layouts=[\"rtl\"])\n```\n\nTo update pixel tests, locally run the test in the current tasks container, or\ncreate a draft PR and let the tests run for `test/reference-image` and\nafterwards fetch the new pixels:\n\n```\n./test/common/pixel-tests fetch \"https://cockpit-logs.us-east-1.linodeobjects.com/<snip>/log.html\"\n```\n\nFinally, upload the new pixel tests and commit the newly generated submodule commit:\n```\n./test/common/pixel-tests push\n```\n\n**Note** that you have to a part of the [Contributors group](https://github.com/orgs/cockpit-project/teams/contributors)\nto push pixel tests.\n\n## Test Configuration\n\nYou can set these environment variables to configure the test suite:\n\n * `TEST_OS`: The OS to run the tests in, like \"fedora-coreos\" or\n    \"debian-testing\". See the \"cockpit-project/cockpit\" section in the\n    [test map](https://github.com/cockpit-project/bots/blob/main/lib/testmap.py)\n    for all supported values. \"fedora-44\" is the default (`TEST_OS_DEFAULT` in\n    bots' [constants.py](https://github.com/cockpit-project/bots/blob/main/lib/constants.py)).\n\n * `TEST_BROWSER`: What browser should be used for testing. Currently supported\n   values are \"chromium\" and \"firefox\". \"chromium\" is the default.\n\n * `TEST_SHOW_BROWSER`: Set to run browser interactively. When not specified,\n   browser is run in headless mode. When set to \"pixels\", the browser will be\n   resized to the exact dimensions that are used for pixel tests.\n\n * `TEST_TIMEOUT_FACTOR`: Scale normal timeouts by given float value. Useful for\n   slow/busy testbeds or architectures.\n\nSee the [bots documentation]({{ site.baseurl }}/external/bots/README.html)\nfor details about the tools and configuration for these.\n\n## Convenient test VM SSH access\n\nIt is recommended to add a snippet like this to your `~/.ssh/config`. Then\nyou can log in to test machines without authentication:\n\n    Match final host 127.0.0.2\n        User root\n        StrictHostKeyChecking no\n        UserKnownHostsFile /dev/null\n        CheckHostIp no\n        IdentityFile CHECKOUT_DIR/bots/machine/identity\n        IdentitiesOnly yes\n\nYou need to replace `CHECKOUT_DIR` with the actual directory where you cloned\n`cockpit.git`, or `bots.git` if you have a separate clone for that.\n\nMany cockpit developers take it a step further, and add an alias to\nallow typing `ssh c`:\n\n    Host c\n        Hostname 127.0.0.2\n        Port 2201\n\nThe `final` keyword in the first rule will cause it to be checked (and matched)\nafter the `Hostname` substitution in the `c` rule.\n\n## Fast develop/test iteration\n\nEach `image-prepare` invocation will always start from the pristine image and\nignore the current overlay in `test/images`. It is thorough, but also rather\nslow. If you want to iterate on changing only JavaScript/HTML code, as opposed\nto the bridge or webserver, the whole build and test cycle can be done much\nfaster.\n\nYou always need to do at least one initial `test/image-prepare $TEST_OS` run.\nAfterwards it depends on the kind of test you want to run.\n\n### Nondestructive tests\n\nMany test methods or classes are marked as `@nondestructive`, meaning that\nthey restore the state of the test VM enough that other tests can run\nafterwards. This is the fastest and most convenient situation for both\niterating on the code and debugging failing tests.\n\nStart the prepared VM with `bots/vm-run $TEST_OS`. Note the SSH and cockpit\nports. If this is the only running VM, it will have the ports in the\nexamples below, otherwise the port will be different.\n\nThen start building the page you are working on\n[in watch and rsync mode](../HACKING.md#working-on-cockpits-session-pages), e.g.\n\n    RSYNC=c ./build.js -w users\n\n(Assuming the `c` SSH alias from the previous section and first running VM).\n\nThen you can run a corresponding test against the running VM, with additional\ndebug output:\n\n    TEST_OS=... test/verify/check-users -t --machine 127.0.0.2:2201 --browser 127.0.0.2:9091 TestAccounts.testBasic\n\n### Destructive tests\n\nOther tests need one or more fresh VMs. Instead of a full `test/image-prepare`\nrun (which is slow), you can update the existing VM overlay with updated\nbundles. Start the build in watch mode, but without rsyncing, e.g.\n\n    ./build.js -w storaged\n\nand after each iteration, copy the new bundles into the VM overlay:\n\n    bots/image-customize -u dist:/usr/share/cockpit/ $TEST_OS\n\nThen run the test as you would normally do, e.g.\n\n    TEST_OS=... test/verify/check-storage-stratis -t TestStorageStratis.testBasic\n\nUse `bots/vm-reset` to clean up all prepared overlays in `test/images`.\n\n## Debugging tests\n\nIf you pass the `-s` (\"sit on failure\") option to a test program, it\nwill pause when a failure occurs so that you can log into the test\nmachine and investigate the problem.\n\nA test will print out the commands to access it when it fails in this\nway. You can log into a running test-machine using ssh.  See the\n\"Helpful tips\" section below.\n\nYou can also put calls to `sit()` into the tests themselves to stop them\nat strategic places.\n\nThat way, you can run a test cleanly while still being able to make\nquick changes, such as adding debugging output to JavaScript.\n\n## Guidelines for writing tests\n\nIf a test is not decorated with `@nondestructive`, it is OK for a test to\ndestroy the test machine OS installation, or otherwise modify it without\ncleaning up.  For example, it is OK to remove all of `/etc` just to see what\nhappens.  The next test will get a pristine test machine.\n\nTests decorated with `@nondestructive` will all run against the same test\nmachine. The nondestructive test should clean up after itself and restore the\nstate of the machine, such that the next nondestructive test is not impacted.\n\nA fast running test suite is more important than independent,\nsmall test cases.\n\nThus, it is OK for tests to be long.  Starting the test machine is so slow that\nwe should run as many checks within a single session as make sense. Note that\nnondestructive tests do not suffer from this, and are much quicker.\n\nStill, within a long test, try to have independent sections, where\neach section returns the machine to more or less the state that it was\nin before the section.  This makes it easier to run these sections\nad-hoc when doing incremental development.\n\n## Coverage\n\nEvery pull request will trigger a `$DEFAULT_OS/devel` scenario which creates a\ncoverage report of the JavaScript code executed and writes comments about\nuncovered code in the pull request. The overall coverage percentage is recorded\nin prometheus for a subset of our projects and [visualized in Grafana](https://grafana-cockpit.apps.ocp.cloud.ci.centos.org/d/ci/cockpit-ci?orgId=1).\n\nTo generate coverage locally for `TestApps`:\n\n```\nexport NODE_ENV=devel\n./build.js\n./test/image-prepare -q\n./test/common/run-tests --test-dir test/verify --coverage TestApps\n```\n\nCode which is impossible or very hard to test in our tests can be excluded from\nappearing in a pull request as comment by adding a `not-covered` comment with a\nshort justification:\n\n```javascript\nreturn cockpit.script(data, { superuser: \"try\", err: \"message\" })\n              .catch(console.error); // not-covered: OS error\n```\n\n## Helpful tips\n\nFor web access, if you'd like to avoid Chromium (or Chrome) prompting\nabout certificate errors while connecting to localhost, you can change\nthe following setting:\n\n    chrome://flags/#allow-insecure-localhost"
  },
  {
    "path": "external/wiki/Cockpit-Coding-Guidelines.md",
    "content": "---\ntitle: Cockpit Coding Guidelines\nsource: https://github.com/cockpit-project/cockpit/wiki/Cockpit-Coding-Guidelines\n---\n\n## General\n* No trailing whitespace, no tab characters, except in Makefile.am files\n* Generally line length should be limited to 120 chars\n* Indentation: 4 spaces per level, no tabs\n\n## Languages\n* [C](#cstyle)\n* [JavaScript](#jsstyle)\n* [CSS/HTML](#cssstyle)\n* [Python](#pythonstyle)\n\n<a name=\"cstyle\"/>\n\n## C style\n\n* [Gtk+ coding standards](https://github.com/GNOME/gtk/blob/main/docs/CODING-STYLE.md)\n* GNU C with C11 features is allowed and the default.\n* When in doubt, check the surrounding code and try to imitate it.\n\n* Exception: We don't require tabular alignment of function arguments like GTK and Glib do. Function definitions look like this:\n\n```c\nstatic JsonArray *\ninterframe_compress_samples (int count,\n                             JsonArray *samples)\n{\n  /* code */\n}\n```\n\n[Sample code](https://github.com/cockpit-project/cockpit/blob/30270ca580159cc4a0e0238b17f75bc7e03cbe2f/src/websocket/websocketconnection.c#L658-L671)\n```c\n/* Store the code/data payload */\nif (len >= 2)\n  {\n    pv->peer_close_code = (guint16)data[0] << 8 | data[1];\n  }\nif (len > 2)\n  {\n    data += 2;\n    len -= 2;\n    if (g_utf8_validate ((gchar *)data, len, NULL))\n      pv->peer_close_data = g_strndup ((gchar *)data, len);\n    else\n      g_message (\"received non-UTF8 close data: %d '%.*s' %d\", (int)len, (int)len, (gchar *)data, (int)data[0]);\n  }\n```\n\n<a name=\"jsstyle\"/>\n\n## JavaScript style\n\n* Private scopes are only necessary in code that is not bundled with webpack.\n* ```\"use strict\"``` should be set on code that is not bundled with webpack.\n* [Crockford](http://javascript.crockford.com/code.html) with lots of exceptions\n* Chained calls may be placed on separate lines for readability (see example below)\n\nDon't indent top level code, even if using a top level private scope (see above).\n\n```javascript\n(function() {\n\"use strict\";\n\nconsole.log(\"not indented\");\n\n}());\n```\n\nVariables should be declared outside of loops or condition braces.\n\n```javascript\n{\n  var demo = 1; /* here */\n  while(false) {\n     /* not here */\n  }\n}\n```\n\nFunction declarations and invocations should have no space after function name. Function starting brace goes on same line as ```function``` keyword.\n\n```javascript\nfunction name(arg) {\n   /* body */\n}\n```\n\nAnonymous functions do not need a space between the ```function``` keyword and arguments.\n\n```javascript\ndiv.onclick = function(e) {\n   /* body */\n}\n```\n\nControl flow keywords such as ```if``` ```for``` and ```while``` should have a space after them. If there is only one statement in a conditional or loop, you may leave out the braces.\n\n```javascript\nwhile (false)\n   console.log(\"never reached\");\n```\n\nAll binary operators except . (period) and ( (left parenthesis) and [ (left bracket) should be separated from their operands by a space.\n\n[More Sample code](https://github.com/cockpit-project/cockpit/blob/30270ca580159cc4a0e0238b17f75bc7e03cbe2f/pkg/shell/cockpit-docker.js#L588-L597)\n```javascript\n/* if an image is older than two days, don't show the time */\nvar threshold_date = new Date(image.Created * 1000);\nthreshold_date.setDate(threshold_date.getDate() + 2);\n\nif (threshold_date > (new Date())) {\n    $(row[1]).text(new Date(image.Created * 1000).toLocaleString());\n} else {\n    var creation_date = new Date(image.Created * 1000);\n\n    /* we hide the time, so put full timestamp in the hover text */\n    $(row[1])\n        .text(creation_date.toLocaleDateString())\n        .attr(\"title\", creation_date.toLocaleString());\n}\n```\n\nNew javascript files should be in the [Asynchronous Module Definition](http://dojotoolkit.org/documentation/tutorials/1.10/modules/index.html) form. For example:\n\n```javascript\ndefine([\n    \"jquery\",\n    \"base1/cockpit\"\n], function($, cockpit) {\n    /* ... */\n\n    var module = {\n        api1: function api1() { /* ... */ },\n        api2: function api2() { /* ... */ }\n    };\n\n    return module;\n});\n```\n\nAs a general rule: Modules that return API (as above) should avoid global side-effects. And modules that have global side-effects should not return or define API.\n\nReact/JSX conventions:\n* Wrap multiline jsx in parentheses\n* Inside JSX code, simple variables or expressions don't require spaces in curly braces, complex ones do, `{key.val}` and `{key}` but `{ this.props.fun_stuff.map(myMapFunction) }`\n\n```jsx\nvar panel = (\n    <tr className=\"listing-panel\">\n        <td colSpan={ header_entries.length + (expand_toggle?1:0) }>\n            <div className=\"listing-head\">\n                <div className=\"listing-actions\">\n                    {this.props.listingActions}\n                </div>\n                <ul className=\"nav nav-tabs nav-tabs-pf\">\n                    {links}\n                </ul>\n            </div>\n            {tabs}\n        </td>\n    </tr>\n);\n```\n\n\n\n<a name=\"cssstyle\"/>\n\n## CSS/HTML style\n* Use dashes instead of underscores in ids\n* Use namespaces for ids if writing code that is consumed as part of a larger whole.\n\n[Sample code](https://github.com/cockpit-project/cockpit/blob/97e0a7d7a11bc64da7f6a48ae27039f061977f6e/pkg/lib/page.scss#L99)\n```css\n/* Panels don't draw borders between them */\n.panel > .table > tbody:first-child td {\n    border-top: 1px solid rgb(221, 221, 221);\n}\n\n/* Table headers should not generate a double border */\n.panel .table thead tr th {\n    border-bottom: none;\n}\n```\n\n<a name=\"pythonstyle\"/>\n\n## Python style\n* [PEP 8](https://www.python.org/dev/peps/pep-0008/)\n\n[Sample code](https://github.com/cockpit-project/cockpit/blob/badd626498dd469dae10ff13f8ad03717835ccb7/tools/tap-gtester#L97-L112)\n```python\ndef run(self, proc, output=\"\"):\n    # Complete retrieval of the list of tests\n    output += proc.stdout.read()\n    proc.wait()\n    if proc.returncode:\n        sys.stderr.write(\"tap-gtester: listing GTest tests failed: %d\\n\" % proc.returncode)\n        return proc.returncode\n    self.test_remaining = []\n    for line in output.split(\"\\n\"):\n        if line.startswith(\"/\"):\n            self.test_remaining.append(line.strip())\n    if not self.test_remaining:\n        print \"Bail out! No tests found in GTest: %s\" % self.command[0]\n        return 0\n\n    print \"1..%d\" % len(self.test_remaining)\n```\n\n<a name=\"emacs\"/>\n\n## Emacs setup\n```emacs\n(setq indent-tabs-mode nil)\n(add-hook 'before-save-hook 'delete-trailing-whitespace)\n(setq whitespace-style '(face trailing lines-tail empty))\n(setq whitespace-line-column 120)\n(global-whitespace-mode)\n```"
  },
  {
    "path": "external/wiki/Contributing.md",
    "content": "---\ntitle: Contributing\nsource: https://github.com/cockpit-project/cockpit/wiki/Contributing\n---\n\n### Prerequisite\n\nSince you're considering contributing, you are likely already using Cockpit. If not, first install Cockpit on your local machine as described in:\n\n[https://cockpit-project.org/running.html]({{ site.baseurl }}/running.html)\n\n### Getting Started\n * Check out the [git repo](https://github.com/cockpit-project/cockpit), learn how to build it and run it. Change a string in the code somewhere and make sure you can see the change in the browser. See [HACKING.md]({{ site.baseurl }}/external/source/HACKING.html) for details.\n * Keep in mind the [project ideals]({{ site.baseurl }}/ideals.html)\n * If you are looking for someplace to start developing, issues are marked [with a good-first-issue label](https://github.com/cockpit-project/cockpit/issues?q=is%3Aopen+is%3Aissue+label%3Agood-first-issue) when they are a good introduction to Cockpit and of limited scope.\n * [Documentation]({{ site.baseurl }}/guide/latest/) (be aware: possible version differences)\n * [Set up integration tests](https://github.com/cockpit-project/cockpit/blob/master/test/README.md). Automated tests are an important part of Cockpit and every new feature should be accompanied by its tests.\n * Join the project's [GitHub Discussions page](https://github.com/cockpit-project/cockpit/discussions) to connect with the community, ask questions, and participate in discussions about the project's development and features.\n\n### Issue tracker\n\nIn-progress work and bugs are in the [issue tracker](https://github.com/cockpit-project/cockpit/issues). Use this for reporting bugs, filing feature requests, and proposing changes.\n\n### Pull request\n\nModify the project in your own fork and issue a pull request once you want other developers to take a look at what you have done and discuss the proposed changes.\n\n### Source code\nCockpit encompasses different languages and is developed by multiple developers. When contributing, please adhere to the [coding style guidelines](Cockpit-Coding-Guidelines).\n\nHere is a detailed description of the [commit workflow](Workflow) (including [review criteria](/external/wiki/Workflow#review-criteria)) and as an example, [how @mvollmer merges pull requests](https://github.com/cockpit-project/cockpit/wiki/How-@mvollmer-merges-pull-requests).\n\n### Contact the developers\n\n * Chat with us on Matrix in [#cockpit:fedoraproject.org](https://matrix.to/#/#cockpit:fedoraproject.org)\n * Join the [cockpit-devel mailing list](https://lists.fedorahosted.org/mailman/listinfo/cockpit-devel)\n * Join a [GitHub discussion](https://github.com/cockpit-project/cockpit/discussions) or create a new one.\n\n### User interface & design\nCockpit's user interface is based on [PatternFly](https://patternfly.org/). Please be aware of this, especially of the design patterns (listed on the design tab of each component) when proposing changes to the user interface. Be sure to also read the general guidelines on the PatternFly website as well.\n\nWe work on designs inline in issues, pull requests, and on the discussions area. Additionally, there is the [Cockpit Design repository](https://github.com/cockpit-project/cockpit-design) as an archive for most design work.\n\nDesigns are made with open source software, including [Inkscape](https://inkscape.org/), [Penpot](https://penpot.app/), and [Excalidraw](https://excalidraw.com/). Please post the resulting mockups as PNGs in the issue tracker. Ideally, also share the source too (SVG, penpot file, embedded info in the Excalidraw PNG, etc.).\n\n### Further reading\n * [Create plugins for the user interface]({{ site.baseurl }}/blog/creating-plugins-for-the-cockpit-user-interface.html)\n * [Starter Kit - the turn-key template for your own pages]({{ site.baseurl }}/blog/cockpit-starter-kit.html)\n * [Make your Cockpit page easily installable]({{ site.baseurl }}/blog/making-a-cockpit-application.html)\n * [Use DBUS from javascript in Cockpit]({{ site.baseurl }}/blog/using-dbus-from-javascript-in-cockpit.html)\n * [Protocol for web access to system APIs]({{ site.baseurl }}/blog/protocol-for-web-access-to-system-apis.html)"
  },
  {
    "path": "external/wiki/Demos-and-Talks.md",
    "content": "---\ntitle: Demos and Talks\nsource: https://github.com/cockpit-project/cockpit/wiki/Demos-and-Talks\n---\n\n### 2025\n * [Browser automation/testing with BiDi and minimal dependencies](https://pretalx.devconf.info/devconf-cz-2025/talk/B98ZPE/) (Martin Pitt), devconf.cz; [intro and demo code](https://github.com/martinpitt/bidi-test/), [video](https://www.youtube.com/watch?v=YUfqPE6Uh5c&t=7449s)\n\n### 2024\n * [Upstream cross-project testing: Never break your API consumers](https://pretalx.com/devconf-cz-2024/talk/KDZZES/) (Martin Pitt), devconf.cz; [video](https://www.youtube.com/watch?v=LyXOdDV98LM), [slides and notes](https://github.com/cockpit-project/presentations/tree/main/2024-upstream-cross-project-testing)\n * [How we integrated Btrfs in Cockpit](https://pretalx.com/devconf-cz-2024/talk/JEPNDF/) (Jelle van der Waa), devconf.cz; [video](https://youtu.be/ipb-_rgFNa4?t=4594), [slides](https://pretalx.com/media/devconf-cz-2024/submissions/JEPNDF/resources/Cockpit_Btrfs_vS8beTQ.pdf)\n\n### 2023\n * [Monty Python's Flying Cockpit](https://devconfcz2023.sched.com/event/3e54fcb5b2f905fedc4810af54ce29c8) (Allison Karlitskaya and Martin Pitt), devconf.cz; [video](https://www.youtube.com/watch?v=ZAVUG6E0Xd4), [slides and notes](https://github.com/cockpit-project/presentations/tree/main/2023-devconf-beipack-pybridge)\n\n### 2022\n * [Tame your CI with Error Budgets](https://www.youtube.com/watch?v=yFbNCkB4SuM) (Stef Walter and Martin Pitt); [DevConf.cz](https://devconfcz2022.sched.com/event/c4b8ec3b2553b64f514a4b022c9ca949) page with slides and notes links\n * [(Mostly) Self-testing infrastructure updates](https://github.com/cockpit-project/presentations/tree/main/cyborg-infra-seminar-2022-02) (Martin Pitt, Cyborg Infrastructure Seminar)\n\n### 2021\n* [Cockpit CI infrastructure overview](https://github.com/cockpit-project/presentations/tree/main/cyborg-infra-seminar-2021-02) (Sanne Raymaekers and Martin Pitt, Cyborg Infrastructure Seminar)\n* [Using the new metrics page to debug performance issues](https://www.youtube.com/watch?v=8_NLoJBjay4&t=1s) (Matej Marusak)\n\n### 2020\n* [Authenticate to Cockpit from anywhere](https://www.youtube.com/watch?v=m92Vl-FZdA8) ([slides](https://piware.de/docs/cockpit-auth-anywhere.pdf), [notes](https://piware.de/docs/cockpit-auth-anywhere-notes.pdf)) (Martin Pitt, DevConf.cz)\n\n### 2019\n* [Your-turn key Cockpit UI in a CICD ecosystem](https://www.youtube.com/watch?v=f19UAkxmuIg) ([slides with notes](https://piware.de/docs/cockpit-ecosystem-with-notes.pdf), [slide sources](https://piware.de/gitweb/?p=talk-cockpit-ecosystem.git;a=tree)) (Martin Pitt, DevConf.cz)\n* [Set up Smart Card authentication with Cockpit 209](https://www.youtube.com/watch?v=v07cHZQsRyo) (Martin Pitt)\n\n### 2018\n* [Cockpit - Moving towards more advanced use-cases](https://www.youtube.com/watch?v=-FV4TgaelJg&t=11s) (Lars Karlitski, Andreas Nilsson, DevConf.cz)\n* [Cockpit: A Linux Sysadmin Session in your Browser](https://www.youtube.com/watch?v=Oq6Vbwl-HqM&t=348s) (Stef Walter, FOSDEM)\n* [Is Cockpit Secure?](https://media.ccc.de/v/ASG2018-231-is_cockpit_secure) ([blog post]({{ site.baseurl }}/blog/is-cockpit-secure.html)) (Stef Walter, All Systems Go)\n\n### 2016\n* [Cockpit: A Linux Session In Your Browser](https://www.youtube.com/watch?v=KJ3JkEdi14c) (Peter Volpe, FOSDEM)\n* [What's new and what's next](https://www.youtube.com/watch?v=zdm4rsnVobw) (Peter Volpe, Dominik Perpeet, DevConf.cz)\n\n"
  },
  {
    "path": "external/wiki/Proxying-Cockpit-over-Apache-with-LetsEncrypt.md",
    "content": "---\ntitle: Proxying Cockpit over Apache with LetsEncrypt\nsource: https://github.com/cockpit-project/cockpit/wiki/Proxying-Cockpit-over-Apache-with-LetsEncrypt\n---\n\nCockpit works on a **web socket combined with http/https** interface, Web Socket is used to deliver active content back and forth between client and server. But when a proxy sits in between, it needs to be configured likely.\n\nWe will need to create a virtual host, give the virtual host a domain name, install TLS/SSL certificate and set up a reverse proxy. (instructions adapted from [here](https://www.linuxbabe.com/cloud-storage/integrate-collabora-online-server-nextcloud-ubuntu-16-04) and [here](https://stackoverflow.com/questions/27526281/websockets-and-apache-proxy-how-to-configure-mod-proxy-wstunnel))\n\n## Set up Apache X-Frame-Options\n\nEdit Apache X-Frame-Options policy by running:\n\n`sudo nano /etc/apache2/conf-available/ssl-params.conf`\n\nFind a line that says `Header always set X-Frame-Options DENY`\nand change it to `Header always set X-Frame-Options SAMEORIGIN`\n\n## Set up Apache Virtual Host\n\nInstall Apache web server with the following command:\n\n`sudo apt install apache2`\n\nRun the following command to create an Apache virtual host file. Replace the domain name with your actual domain name for Cockpit. Don’t forget to create an A record for this domain name.\n\n`sudo nano /etc/apache2/sites-available/cockpit.your-domain.com.conf`\n\nPut the following text into the file.\n\n```apacheconf\n<VirtualHost *:80>\n ServerName cockpit.your-domain.com\n</VirtualHost>\n```\n\nSave and close the file. Enable this virtual host with the following command:\n\n`sudo a2ensite cockpit.your-domain.com.conf`\n\nThen restart Apache.\n\n`sudo systemctl restart apache2`\n\n## TLS/SSL certificate with Let's Encrypt\n\nHTTPS helps us prevent man-in-the-middle attack and password sniffing. We can obtain a free TLS/SSL certificate from Let’s Encrypt CA. First Let’s install the certbot client. The client is still named letsnecrypt in Ubuntu repository. The following command will install the client and apache plugin.\n\n`sudo apt install letsencrypt python-letsencrypt-apache`\n\nNow issue the following command to obtain a free TLS/SSL certificate. Replace the text with your actual data.\n\n`sudo letsencrypt --apache --agree-tos --email YOUR-EMAIL-ADDRESS -d COCKPIT.YOUR-DOMAIN.COM`\n\nYou will be asked to choose easy or secure. It’s recommended to choose secure so that all http requests will be redirected to https.\n\nOnce you hit the OK button, a free TLS/SSL certificate is obtained and installed on the Apache virtual host.\n\nNow copy the certificates information into the cockpit certificate folder using the following commands\n\n`cat /etc/letsencrypt/live/cockpit.your-domain.com/fullchain.pem >> /etc/cockpit/ws-certs.d/1-my-cert.cert`\n\n`cat /etc/letsencrypt/live/cockpit.your-domain.com/privkey.pem >> /etc/cockpit/ws-certs.d/1-my-cert.cert`\n\nYou will need to do this every time the certificate gets renewed (every 3 months).\n\n## Set up Apache Reverse Proxy in a Subdomain\n\nTo be able to proxy traffic using Apache, run the following commands to enable each of these Apache modules.\n\n`sudo a2enmod proxy proxy_wstunnel proxy_http ssl rewrite`\n\nThen run the following command to edit the new virtual host file created by Let’s Encrypt (certbot) client.\n\n`sudo nano /etc/apache2/sites-enabled/cockpit.your-domain.com-le-ssl.conf`\n\nChange this file so it looks like the following.\n\n```apacheconf\n<IfModule mod_ssl.c>\n<VirtualHost *:443>\n  ServerName cockpit.your-domain.com\n  SSLCertificateFile /etc/letsencrypt/live/cockpit.your-domain.com/fullchain.pem\n  SSLCertificateKeyFile /etc/letsencrypt/live/cockpit.your-domain.com/privkey.pem\n  Include /etc/letsencrypt/options-ssl-apache.conf\n\n  ProxyPreserveHost On\n  ProxyRequests Off\n\n  # allow for upgrading to websockets\n  RewriteEngine On\n  RewriteCond %{HTTP:Upgrade} =websocket [NC]\n  RewriteRule /(.*)           ws://127.0.0.1:9090/$1 [P,L]\n  RewriteCond %{HTTP:Upgrade} !=websocket [NC]\n  RewriteRule /(.*)           http://127.0.0.1:9090/$1 [P,L]\n\n  # Proxy to your local cockpit instance\n  ProxyPass / http://127.0.0.1:9090/\n  ProxyPassReverse / http://127.0.0.1:9090/\n</VirtualHost>\n</IfModule>\n```\n\nWith Apache 2.4.47 or later, this could also be written as:\n\n```apacheconf\n<IfModule mod_ssl.c>\n<VirtualHost *:443>\n  ServerName cockpit.your-domain.com\n  SSLCertificateFile /etc/letsencrypt/live/cockpit.your-domain.com/fullchain.pem\n  SSLCertificateKeyFile /etc/letsencrypt/live/cockpit.your-domain.com/privkey.pem\n  Include /etc/letsencrypt/options-ssl-apache.conf\n\n  ProxyPreserveHost On\n  ProxyRequests Off\n\n  # Proxy to your local cockpit instance\n  ProxyPass / http://127.0.0.1:9090/ upgrade=websocket\n  ProxyPassReverse / http://127.0.0.1:9090/\n</VirtualHost>\n</IfModule>\n```\n\nSave and close the file. Then restart Apache web server.\n\n`sudo systemctl restart apache2`\n\nMake sure you changed `/etc/cockpit/cockpit.conf` to include the following:\n\n```ini\n[WebService]\nOrigins = https://cockpit.your-domain.com http://127.0.0.1:9090\nProtocolHeader = X-Forwarded-Proto\nAllowUnencrypted = true\n```\n\nRestart cockpit\n\n`sudo systemctl restart cockpit.service`\n\nYou can now login to cockpit at the specified subdomain.\n\n## Set up Apache Reverse Proxy in a Subdirectory\n\nThe following steps allow proxying traffic from a subdirectory of an existing Apache virtual host.  \nImportant: `/cockpit/` and `/cockpit+/` are reserved. Do not use any reserved names [listed here]({{ site.baseurl }}/guide/latest/cockpit.conf.5). This example will use /UrlRoot/.  \n\nRun the following command to enable all the required Apache modules.  \n\n`sudo a2enmod proxy proxy_wstunnel proxy_http ssl rewrite`  \n\nThen run the following command to edit the new virtual host file created by Let’s Encrypt (certbot) client.  \n\n`sudo nano /etc/apache2/sites-enabled/cockpit.your-domain.com-le-ssl.conf`  \n\nIf you are not using certbot, an example file normally exists at the following:  \n\n`sudo nano /etc/apache2/sites-available/default-ssl.conf`  \n\nOtherwise, consult your man pages/packager for the correct filepath, or follow the prior certbot tutorial, or create a site manually.\n\nAssuming you followed the prior LetsEncrypt strategy, are using the common default file, or have an existing virtual host such that the file starts with `<IfModule mod_ssl.c> <VirtualHost *:443>` and has the appropriate directives for TLS/SSL, append the following to your virtual host, replacing `UrlRoot` with your desired subdirectory name.  \n\n```apacheconf\n                SSLProxyEngine          On\n                # required module\n                RewriteEngine           On\n                # required module\n                ProxyPreserveHost       On\n                # required\n                ProxyRequests           Off\n                # RECOMMENDED, disables forwarding, see https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxyrequests\n                ProxyErrorOverride      Off\n                # if possible, present cockpit's error pages instead of apache's\n                SSLProxyVerify optional_no_ca\n                # cockpit has a self-signed cert by default, therefore no CA\n                SSLProxyCheckPeerCN Off\n                # SSL error without this\n                SSLProxyCheckPeerName Off\n                # SSL error without this\n                SSLProxyCheckPeerExpire Off\n                # recommended since potential SSL error without this\n                RequestHeader set \"X-Forwarded-Proto\" \"https\"\n                # required by cockpit.conf\n                # following is adapted from https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html\n                RewriteCond %{HTTP:Upgrade} websocket [NC]\n                RewriteCond %{HTTP:Connection} upgrade [NC]\n                RewriteRule \"^/UrlRoot/(.*)\" \"wss://127.0.0.1:9090/UrlRoot/$1\" [P,L]\n                # when websocket in upgrade AND\n                # within UrlRoot, rewrite proxy with wss://\n                RewriteCond ${HTTP:Upgrade} !=websocket [NC]\n                RewriteRule \"^/UrlRoot/(.*)\" \"https://127.0.0.1:9090/UrlRoot/$1\" [P,L]\n                # when no websocket upgrade AND\n                # within UrlRoot, rewrite proxy with https://\n        </VirtualHost>\n</IfModule>\n```\n\nSave and close the file. Then restart Apache web server.\n\n`sudo systemctl restart apache2`\n\nLastly, change the `/etc/cockpit/cockpit.conf` to include the following:\n\n```ini\n[WebService]\nOrigins = https://your-domain.com http://127.0.0.1:9090\nProtocolHeader = X-Forwarded-Proto\nUrlRoot = /UrlRoot/\n```\nReplace `/UrlRoot/` with your choice of subdirectory, though keep the enclosing `/`.  \nThis method does not require you to disable encryption (`AllowUnencrypted = true`) since the self-signed certificate is allowed.  \n\nRestart cockpit\n\n`sudo systemctl restart cockpit.service`\n\nYou can now login to cockpit at `https://your-domain.com/UrlRoot/`."
  },
  {
    "path": "external/wiki/Proxying-Cockpit-over-NGINX.md",
    "content": "---\ntitle: Proxying Cockpit over NGINX\nsource: https://github.com/cockpit-project/cockpit/wiki/Proxying-Cockpit-over-NGINX\n---\n\n## Preamble\n\nCockpit uses web sockets to deliver active content back and forth between the client and the server in real time. One of the challenges of placing Cockpit behind a proxy server such as [nginx](https://nginx.org) is that additional configuration is required to ensure that web socket connections are proxied as well.\n\nFor the purposes of this example we will assume:\n* Cockpit is listening on port 9090\n* Nginx is listening on port 80 (http) and port 443 (https)\n* You have a subdomain of cockpit.domain.tld pointed to your nginx instance\n* You can access your nginx instance by connecting to http://cockpit.domain.tld, even if you just get the default page\n\n## Make Cockpit proxy aware\n\nFor security Cockpit will be unable to serve requests from origins it is unfamiliar with due to [cross domain limitations](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing). In our example, Cockpit will see the origin as cockpit.domain.tld however it will believe it's running on 127.0.0.1 and therefore be unable to serve the request.\n\nTo make Cockpit proxy aware, you will need to modify the [Cockpit config file]({{ site.baseurl }}/guide/latest/cockpit.conf.5.html) located at /etc/cockpit/cockpit.conf. This file may not exist and if it doesn't you should create it.\n\n```\n[WebService]\nOrigins = https://cockpit.domain.tld wss://cockpit.domain.tld\nProtocolHeader = X-Forwarded-Proto\n```\n\nThese changes will let Cockpit know that connections will come through for https (secure http) and wss (secure websockets) on the subdomain cockpit.domain.tld, and that it should look for the `X-Forwarded-Proto` header to determine if the connection is secure or not, this is important as Cockpit will [redirect any non-local connection from http to https automatically]({{ site.baseurl }}/guide/149/https.html) and sees cockpit.domain.tld is non-local.\n\nOnce these changes are made you will need to restart cockpit.\n\n## Virtual host file\n\nTo create a proxy you will first need to create a [virtual server block](https://www.nginx.com/resources/wiki/start/topics/examples/server_blocks/) so nginx is aware of what to do when it receives a request for your subdomain. If this block doesn't exist, nginx will just serve the default page.\n\nThis server block will allow you to access Cockpit via http://cockpit.domain.tld:\n\n```\nserver {\n    listen         80;\n    listen         443 ssl;\n    server_name    cockpit.domain.tld;\n\n    location / {\n        # Required to proxy the connection to Cockpit\n        proxy_pass https://127.0.0.1:9090;\n        proxy_set_header Host $host;\n        proxy_set_header X-Forwarded-Proto $scheme;\n\n        # Required for web sockets to function\n        proxy_http_version 1.1;\n        proxy_buffering off;\n        proxy_set_header Upgrade $http_upgrade;\n        proxy_set_header Connection \"upgrade\";\n\n        # Pass ETag header from Cockpit to clients.\n        # See: https://github.com/cockpit-project/cockpit/issues/5239\n        gzip off;\n    }\n}\n```\n\n> **_NOTE:_** Since Cockpit automatically handles the http to https redirect you can have one server block which covers both http and https connections.\n\nOnce you have added the new virtual host block you will need to restart nginx.\n\n## Security\n\nIt is recommended you generate a valid, signed certificate for your server, you can do this for free by using [Certbot](https://certbot.eff.org) and [Let's Encrypt](https://letsencrypt.org).\n\n> **_NOTE:_** Once you have a certificate you will need to update the certificate and keys paths in the virtual server block.\n\nAlternatively if you don't require a valid certificate you can [generate your own certificate](https://www.digitalocean.com/community/tutorials/openssl-essentials-working-with-ssl-certificates-private-keys-and-csrs#generating-ssl-certificates). This approach is only recommended for testing as you will get browser security warnings notifying you the connection is not secure.\n\nIf all else fails you can use cockpits self signed certificates which are stored in `/etc/cockpit/ws-certs.d/`. To do this you will need to split the `0-self-signed.cert` into two files, one containing the key and one containing the certificate.\n\n### 502 Bad Gateway & SELinux \nIf SELinux is enabled, change boolean setting (solves 502 gateway error):\n\n`setsebool -P httpd_can_network_connect on`\n\n\n## Other configurations\n\nThere are other common ways you can configure your proxy.\n\n### Serving via a subdirectory rather than subdomain\n\nYou may want to serve cockpit from a subdirectory rather than a subdomain. \n\nFor this example we will assume:\n* Cockpit is listening on port 9090\n* Nginx is listening on on port 80 (http) and port 443 (https)\n* You have a domain of domain.tld pointed to your nginx instance\n* You can access your nginx instance by connecting to http://domain.tld, even if you just get the default page\n* You want to access Cockpit via http://domain.tld/secret/\n* You already have a virtual server block for this domain with existing content in it\n\n```\nserver {\n    ...\n\n    location /secret/ {\n        # Required to proxy the connection to Cockpit\n        proxy_pass https://127.0.0.1:9090/secret/;\n\n        ...\n    }\n}\n```\n\nThe /secret/ location block here contains the exact same information as the location block in the [original example](#virtual-host-file), the /secret/ location block should be placed at the end of the virtual server block.\n\nYou will also need to let Cockpit know that you are serving the requests from a subdirectory by modifying the cockpit.conf file:\n\n```\n[WebService]\nOrigins = https://domain.tld wss://domain.tld\nProtocolHeader = X-Forwarded-Proto\nUrlRoot=/secret\n```\n\n### Using an external proxy\n\nIf you're not running nginx locally alongside Cockpit you will need to adjust the configuration so it works across a network IP address. This may be an instance where nginx is on another server or running in a docker container or otherwise doesn't have access to 127.0.0.1. \n\nFor this example we will assume:\n* Cockpit is listening on port 9090 on system 192.168.10.15\n* Nginx is listening on on port 80 (http) and port 443 (https) on system 192.168.10.29\n* You have a domain of domain.tld pointed to your nginx instance\n* You can access your nginx instance by connecting to http://domain.tld, even if you just get the default page\n\n```\nserver {\n    ...\n\n    location / {\n        # Required to proxy the connection to Cockpit\n        proxy_pass https://192.168.10.15:9090;\n\n        ...\n    }\n}\n```\n\nFor nginx to proxy the connection successfully you'll need to ensure the proxy pass is also using https. By default nginx doesn't check the validity of the SSL certificates for proxied connections, this means you can proxy directly to cockpit using https without needing to tell nginx it's using a self signed certificate. \n\n### Insecure connections\n\nIf you really want to disable the secure connection requirement in Cockpit and instead proxy to http this is possible by disabling the secure connection requirement in the cockpit.conf file:\n\n```\n[WebService]\nAllowUnencrypted=true\n```\n\nDisabling the secure connection requirement doesn't provide any real advantage since nginx doesn't check the certificate for validity. Since you are transmitting sensitive information to Cockpit it is recommended to leave this setting intact unless you are troubleshooting or have no other option but to serve requests over http. "
  },
  {
    "path": "external/wiki/Workflow.md",
    "content": "---\ntitle: Workflow\nsource: https://github.com/cockpit-project/cockpit/wiki/Workflow\n---\n\nThese are the rules we try to follow when working on Cockpit.\n\n## Review Criteria\n* Each commit should be easy to read.\n\n  Commits are for people to read, so try to tell the story of a new feature clearly.  For example, refactor the code in a preparatory commit to make the actual change in the next commit easier to understand.  Try to separate changes to separate pieces of the code base.\n\n  Historical accuracy of how you figured out the final form of a change is usually not very interesting, but it doesn't need to be totally hidden of course.  If rewriting historical commits is tricky and has a high risk of introducing bugs, don't do it.\n\n* Each commit should adhere to the [Cockpit Coding Guidelines](https://github.com/cockpit-project/cockpit/wiki/Cockpit-Coding-Guidelines)\n\n* The tip of main must always pass the test suites\n\n  A fleet of robots run the test suites for each pull request.  This includes unit tests, integration tests, and browser-compatibility tests.\n\n  The integration tests performed are slow and brittle, and not all failures are caused by bugs in the pull request, but don't just blame every failure on the crappy tests.\n\n* Whenever a pull request changes the API or makes other significant changes, the documentation needs to be updated. Documentation locations that require manual updating include:\n  * [the top-level README.md](https://github.com/cockpit-project/cockpit/blob/main/README.md) about the most important user-facing information about Cockpit\n  * [HACKING.md]({{ site.baseurl }}/external/source/HACKING.html) for development information\n  * [test/README.md](https://github.com/cockpit-project/cockpit/blob/main/test/README.md) for how to set up and run the integration tests\n  * the [documentation tree](https://github.com/cockpit-project/cockpit/tree/main/doc), used for [the guide]({{ site.baseurl }}/guide/latest/)\n\n* [Screenshots](#screenshot) and/or [videos](#video) should be included in every pull request that causes visual changes.\n\n  Having visuals communicates changes, helps with design reviews, and provides a way to highlight features in the release notes on Cockpit-project.org.\n\n  When a pull request changes, it's a good idea to include a new screenshot or video to reflect the current state.\n\n## Git-related / Merging Conventions\n\n* No merge commits on main.\n\n  See https://sandofsky.com/blog/git-workflow.html for the motivation.  In brief, merge commits are confusing when rolling back history to find the commit that introduced a particular bug/feature.\n\n  Thus, we normally use \"Rebase and Merge\" when merging pull requests.\n\n* Each commit on main must be reviewed.\n\n  We trust that all information about the review process will be available from GitHub, thus we don't add Reviewed-By lines or similar markers to the commit messages. We also trust that GitHub can find the pull request for a given SHA1 by itself.\n\n* The subject of a commit should start with a short `<topic>: ` prefix.\n\n  This is usually the package name for frontend code, such as `shell`, `base`, or `systemd`, or some other suitable directory name.  Check the existing commits for examples.\n\n* If a commit fixes an issue, it should have a `Fixes #NNN` line.\n\n* Force pushing to main or other release branches is not allowed.\n\n  The only way to get commits onto main is to rebase/merge a pull request onto it. If you regret merging a pull request, revert its changes with a new pull request.\n \n* The main cockpit-project/cockpit repository should not have any work-in-progress branches.\n\n  Otherwise, there will be a huge number of these branches over time.  We could delete them, but that throws away information, and people would still have them in their local clones.\n\n  Instead, each developer (including the core developers) should make his/her own clone and submit pull requests from there.  This makes it slightly harder to take over a pull request from another developer, but it can be done.\n\n* A pull request in \"Draft\" state is not yet ready for serious review.\n\n  You can make those pull requests to more visibly share some of your work with the rest of the team.\n\n* Github's 'Request changes' feature will be used to mark pull requests that have been reviewed and need action from the submitter.\n\n  This includes changes to the code, or just replies to comments.  Once you have done all that work, you should dismiss the review and comment to indicate that it is ready for review again.\n\n* A pull request is updated with copious rewrites and rebases until it has a small number of 'perfect' commits.\n\n  These commits should be fit for main and the pull request is merged by rebasing these commits onto main.\n\n* A pull request that depends on other pull requests declares that in its description.\n\n  When the commits of a pull request sit on top of the commits of another pull request, it's not easy to see from github where one pull request ends and the other begins.  Thus, it is import to note dependencies explicitly so that the reviewer is less likely to get confused.\n\n## Merge Workflow\n\nWe merge requests from the GitHub Web UI with the \"Rebase and Merge\" button.\n\n## Screenshot\n\nScreenshots should be in a PNG format.\n\nIn some cases, you'll want a full Cockpit page. In others, you may want to crop to the specific section, dialog, or feature you're working on. Some of the tools (like Firefox Screenshots) allow you to crop to the area before saving. Otherwise, you may consider using an additional tool like GIMP to crop the image afterward.\n\n### Firefox \n\nFirefox has two built-in ways to take screenshots.\n1. [Firefox Screenshots](https://screenshots.firefox.com/) is integrated in the URL bar, in the `…` dropdown by default. (You can right click on the option and add it to always be in the URL bar if you take a lot of screenshots.)\n   - When running the screenshot tool, it lets you screenshot a portion of the page (with an interactive, resizable area that lets you focus on a specific element), the visible area of a page, or the full page (if the page scrolls off the area — which shouldn't be an issue in Cockpit itself).\n   - Once you're happy with the screenshot, click the down arrow to save the screenshot to your computer (in the Downloads folder). It will be in a PNG format, perfect for uploading to GitHub in the comment form of an issue or pull request.\n2. Firefox Development Tools\n   - If it's not on already, you might need to visit the DevTools configuration area and toggle the screenshot tool on.\n   - Clicking on the camera icon will screenshot the whole page and save it to ~/Downloads/ with no UI. If you're already in development tools, it's a quick way to take a screenshot for uploading later. Depending on the context, might need to be cropped, or it might already be perfect for posting.\n   - Firefox's responsive view includes this same screenshot tool in the mobile view switcher.\n\n### Chrome\n\nChrome does not have an easy-to-find screenshot tool built-in by default. It does, however, have hidden developer functionality to take a screenshot:\n\n1. Press \"F12\" (or hit `Ctrl`+`Shift`+`I`) to activate developer tools, if not active already.\n2. Hit `Ctrl`+`Alt`+`P` to bring up developer tool action palette.\n3. Start to type \"screenshot\"\n4. Select full size (full page), node (selected element), or screenshot (visible).\n5. Chrome saves the screenshot in ~/Downloads/\n\nAlso, Chrome has a tricky way to get a vector screenshot. This is super-useful for mockups and experimentation.\n\n1. Open developer tools (F12, just like any other browser).\n2. Click on the dev tools' ⠇ menu next to the × button.\n3. Choose \"More tools\".\n4. Select \"Rendering\".\n5. Scroll down to \"Emulate CSS media\".\n6. Choose \"screen\" in the dropdown.\n7. Print the page. (`Ctrl`+`P` or select \"Print…\" from the browser's ⠇ menu in the top-right.)\n8. Make the \"Destination\" set to \"Save as PDF\".\n9. Ensure layout is \"Landscape\" (in most cases).\n10. Click on \"More settings\".\n11. Experiment with paper size (usually A4 or A3).\n12. Set \"Margins\" to \"None\".\n13. Be sure to have \"Background graphics\" checked.\n14. Click the \"Save\" button.\n15. Choose a name and place for your PDF. (The name should default to the title of the page. The location is probably \"Downloads\" by default.)\n16. You can open the PDF in Inkscape to make an SVG, modify the graphics, export as a PNG, or anything else you'd like.\n\n### GNOME Screenshot\n\nGNOME itself has two screenshot tools.\n\n1. Hit the `PrtScn` key (this is customizable, in case your keyboard doesn't have the key by default). A full screenshot is saved in your ~/Pictures/ folder as a PNG. This screenshot will most likely need to be cropped in the GIMP or a similar tool.\n2. Type \"Screenshot\" when in overview mode and the screenshot tool will show up. It lets you grab the whole screen, current window, or select an area to grab. You can add a delay, include the cursor, or apply an effect. When done, you can save the screenshot or copy it to the clipboard (to paste into a tool like GIMP or Inkscape).\n\n### GIMP\n\nGIMP has the ability to take screenshots under the file menu. It has options similar to the GNOME Screenshot tool.\n\n## Video\n\nInstall video applications as Flatpaks from Flathub, to ensure the video output works on your system. (Distribution packages sometimes have issues with various codecs and other dependencies.)\n\n### Recording\n\nBe sure to check your desktop to make sure there is no personal information onscreen or odd background tabs in your browser.\n\n- GNOME has a built-in screen recorder: `Ctrl`+`Alt`+`Shift`+`R` toggles the recording state. Your full video output is captured, regardless of the resolution or number of external monitors. Videos are saved in WebM format in the Videos folder in your home directory. Resulting videos probably need to be cropped & edited. This works on Wayland and X11.\n- [Peek](https://flathub.org/apps/details/com.uploadedlobster.peek) can record an arbitrary part of a screen, in both X11 and also on Wayland. Be sure to change the format from GIF to either MP4 or WebM (both can be edited in a video editor). In the preferences, change the framerate to 30.\n- [SimpleScreenRecorder](http://www.maartenbaert.be/simplescreenrecorder/) works great on X11, but does not work on Wayland.\n\n### Editing\n\n- [Kdenlive](https://flathub.org/apps/details/org.kde.kdenlive) is a full-featured editor.\n- [Flathub also has several other video editors](https://flathub.org/apps/search/video%20editor) available. Most are adequate for simple editing.\n\n### Audio\n\nIn most cases, videos should have speech indicating what is happening. In everything but the quickest demos, you should have good quality audio.\n\nAudio quality is important.\n- Think about what you're going to talk about in advance\n- Try to clearly enunciate words\n- Record in a quiet environment\n- Use a good microphone\n- Consider re-recording audio after the video, when you're not trying to multitask by showing the feature and speaking — a good video editing tool lets you swap out the audio tracks\n\nIf you do not have an external microphone that works with your laptop, you might want to rely on your phone's built-in mic and swap out the audio track in the video editor.\n\nAudio quality can be ranked (in order of best to worst):\n1. Dedicated studio condenser microphone. ([A not-so-bad one can be purchased for €35](https://smile.amazon.de/gp/product/B01MQYWKYY/) — be sure to use the USB adapter if you get it.)\n2. Phone's built-in microphone (as it's optimized for speech quality)\n3. Webcam microphone\n4. Headset/headphones/earbuds microphone (but the quality varies: sometimes it's great, sometimes it's awful)\n100. Laptop's built-in microphone\n\n_All_ of the above options will have a background hiss or background noise, unless you go with a higher-end dedicated microphone. Sometimes this comes from line noise; other times it may pick up noise from nearby electronics. Nearly every audio file benefits from processing in a tool like Audacity.\n\nCleaning up the audio track is a good idea. [Audacity](https://flathub.org/apps/details/org.audacityteam.Audacity) can process audio to [remove background noise](https://fedoramagazine.org/audacity-quick-tip-quickly-remove-background-noise/) and normalize the levels. While this works with audio recorded on a laptop's built-in microphone too, the principle of GIGO (garbage-in, garbage-out) still applies, so try to use a higher quality recording device."
  },
  {
    "path": "faq.md",
    "content": "---\ntitle: Frequently Asked Questions (FAQ)\n---\n\n- this list will be replaced by the Table of Contents\n{:toc}\n\n## General\n\n### How do I contact the Cockpit team?\n\n- If you're filing an issue, use our issue tracker.\n   - For general Cockpit bugs and feature requests, use [Cockpit's issue tracker](https://github.com/cockpit-project/cockpit/issues).\n   - For other parts of Cockpit use specific issues:\n      - [Website issues](https://github.com/cockpit-project/cockpit-project.github.io/issues)\n      - [Virtual machine related issues](https://github.com/cockpit-project/cockpit-machines/issues)\n      - [Podman UI related issues](https://github.com/cockpit-project/cockpit-podman/issues)\n      - [OStree related issues](https://github.com/cockpit-project/cockpit-ostree/issues)\n    - If you're not sure where to file the issue, [use the general issue tracker](https://github.com/cockpit-project/cockpit/issues). (We can move it if necessary.)\n    - If it's not an issue, ask us in the forum or Matrix.\n- There's [a discussion forum for Cockpit on GitHub](https://github.com/cockpit-project/cockpit/discussions).\n- The Cockpit team is on Matrix, usually during European business hours, from Monday through Friday, at [#cockpit:fedoraproject.org](https://matrix.to/#/#cockpit:fedoraproject.org).\n- [Cockpit has a mailing list](https://lists.fedorahosted.org/admin/lists/cockpit-devel.lists.fedorahosted.org/).\n\n### How do I create an application for Cockpit?\n\nAll development-focused documentation is located on the [Contribute page](https://cockpit-project.org/external/wiki/Contributing.html) of the website. This includes creating your own [app page with the starter kit](blog/cockpit-starter-kit.html) and other related topics.\n\n## Installation\n\n### How do I install a recent version of Cockpit on Debian or Ubuntu?\n\nWhile Debian and Ubuntu both ship with access to Cockpit in their main repositories, the version in each might be older than the latest available. This is due to the nature of \"stable\" and \"long term support\" distributions.\n\nThere's often a newer version of Cockpit available in the \"backports\" repositories, for both [Debian](https://backports.debian.org/) and [Ubuntu](https://wiki.ubuntu.com/UbuntuBackports). We recommend using this newer version, if you're able to do so.\n\nPlease read the installation instructions for the appropriate distribution:\n- [Debian installation instructions](running.html#debian)\n- [Ubuntu installation instructions](running.html#ubuntu)\n\n### How do I use Cockpit on another port?\n\nCockpit runs on port 9090 by default. If you'd like to change the port to something else, please [consult the Cockpit guide's section on TCP port and address](https://cockpit-project.org/guide/latest/listen).\n\n### How do I avoid opening a port on my production machines?\n\nIt's possible to not run the Cockpit socket systemd service and log into your target machines with SSH.\n\nIf you use a Linux-based desktop, use the [Cockpit Client desktop application, available on Flathub](https://flathub.org/apps/details/org.cockpit_project.CockpitClient).\n\nIf you cannot use Cockpit Client, we provide Cockpit's web server in the [cockpit/ws container image](https://quay.io/repository/cockpit/ws). You can run that on any other host with SSH access to the target machine. This includes running the container on Kubernetes.\n\n### How do I use Cockpit with a reverse proxy?\n\nCockpit can be used from behind a proxy.\n\nRead one of the following documents:\n\n- [Proxying Cockpit over NGINX](external/wiki/Proxying-Cockpit-over-NGINX.html)\n- [Proxying Cockpit over Apache with LetsEncrypt](external/wiki/Proxying-Cockpit-over-Apache-with-LetsEncrypt.html)\n- [Proxying Cockpit with Pomerium](https://www.pomerium.com/docs/guides/cockpit)\n\n## Development\n\n### How do I build an app for Cockpit?\n\n- [Starter Kit](blog/cockpit-starter-kit.html)\n- [Make your Cockpit page easily installable](blog/making-a-cockpit-application.html)\n- [Additional developer-related resources are on the Contributing page](external/wiki/Contributing.html)\n\n## Troubleshooting\n\n### Login\n\n#### Blank white page after login\n\nIf you see a blank page after logging in, it's a good first step to check the browser console (`Ctrl`+`Shift`+`J` in most browsers) and system logs (using `sudo journalctl --since \"5 minutes ago\"` on your system running Cockpit) for related error messages.\n\n##### Blank page with a Proxy\n\nYou may be using Cockpit with an improperly set up proxy.\n\n###### Solutions\n{:.no_toc}\n\n- [Proxying Cockpit over NGINX](external/wiki/Proxying-Cockpit-over-NGINX.html)\n- [Proxying Cockpit over Apache with LetsEncrypt](external/wiki/Proxying-Cockpit-over-Apache-with-LetsEncrypt.html)\n\n##### Blank page using Safari\n\nOlder versions of Safari on iPhones, iPads, and Safari on macOS on M1 (ARM) machines have a problem with encrypted WebSocket.\n\n###### Solution\n{:.no_toc}\n\nNewer updates of Safari no longer have this issue, but some older [devices may need to use a workaround](running/safari.html).\n\n### Software update\n\n#### Error message about being offline\n\nThe software update page shows \"packagekit cannot refresh cache whilst offline\" on a Debian or Ubuntu system.\n\n##### Solution\n{:.no_toc}\n\nCreate a placeholder file and network interface.\n\n1. Create `/etc/NetworkManager/conf.d/10-globally-managed-devices.conf` with the contents:\n\n    ```ini\n    [keyfile]\n    unmanaged-devices=none\n    ```\n\n2. If you run on Ubuntu with arm64 (e.g.: on a Raspberry Pi), install extra Linux kernel modules for networking:\n\n    ```\n    sudo apt install linux-modules-extra-raspi\n    ```\n\n3. Set up a \"dummy\" network interface:\n\n    ```\n    nmcli con add type dummy con-name fake ifname fake0 ip4 192.0.2.2/24 gw4 192.0.2.1\n    ```\n\n4. Reboot\n\n##### Explanation\n{:.no_toc}\n\nUbuntu uses two different network stacks which don't play so well together.\n\nCockpit's software update page uses PackageKit, which checks NetworkManager. However, as the network interfaces are primarily managed by netplan and systemd-networkd in Ubuntu, NetworkManager reports back to PackageKit that the network is offline as a critical error message and stops further actions.\n\nUnfortunately, this means in many Ubuntu configurations, Cockpit's software update page might fail with a message about not being able to \"refresh cache whilst offline\". Other software that relies on PackageKit, such as KDE's Discover, can also hit this bug.\n\nAdditionally, there's nothing Cockpit itself can do to fix this problem. It's an \"emergent bug\" that happens much lower in the software stack. It's up to Ubuntu to patch the way they're using netplan and networkd... or, alternatively, PackageKit could provide a workaround. Unfortunately, none of these fixes have been implemented yet.\n\nMeanwhile, to be able to update your server using Cockpit when you get this error, you have to do a workaround similar to the one suggested above.\n\n#### Excludes in dnf.conf are ignored\n\nWhen there are specific package excludes, the Software update page may still show packages are available to update.\n\n##### Solution\n{:.no_toc}\n\nAdd excludes to the .repo files with a space-separated list. Wildcards `*` and `?` are supported.\n\n```ini\nexclude=emacs-* jed xeyes\n```\n\n##### Explanation\n{:.no_toc}\n\nCockpit uses PackageKit for the Software updates page. PackageKit does not currently support excludes, except in `.repo` files.\n\nMore details at:\n- [Red Hat bug 1237014: PackageKit ignores exclude in /etc/dnf/dnf.conf](https://bugzilla.redhat.com/show_bug.cgi?id=1237014#c6)\n- [Cockpit bug #17955: Cockpit update is ignoring excludes in yum/dnf configurations](https://github.com/cockpit-project/cockpit/issues/17955)\n- [SysTutorials: How to exclude a package from a specific repository only in yum?](https://www.systutorials.com/how-to-exclude-a-package-from-a-specific-repository-only-in-yum/)\n\n### Virtual machines\n\n#### Virtual machines don't boot\n\nIf a VM hangs during boot or you see an error message such as \"No bootable device\", it may be due to a configuration option in your computer's BIOS / EFI settings.\n\nOn many servers, desktops, and laptops, the setting is turned off by default.\n\n##### Solution\n{:.no_toc}\n\n1. Turn off the computer that is running Cockpit. Then, turn it back on and immediately press the appropriate key to enter the BIOS / EFI settings (e.g. Delete, F1, F12, etc.).\n2. In the BIOS / EFI settings, look for the option to enable virtualization and ensure it is enabled.\n3. Save the changes and exit the BIOS / EFI settings.\n4. Wait for the computer to finish booting and try starting a VM in Cockpit again.\n\n{:.note}\nNote: You may need to consult your computer's manual or the manufacturer's website to determine the correct key to press to enter the BIOS/EFI settings. The exact steps for enabling virtualization vary depending on your computer's make and model.\n\n*[VM]: Virtual Machine\n"
  },
  {
    "path": "feed.xml",
    "content": "---\nlayout: null\n---\n{% include feed.html %}\n"
  },
  {
    "path": "files/starter-kit/check-puppeteer.js",
    "content": "#!/usr/bin/node\n/* Usage:\n * 1. Build a Cockpit starter kit test VM:\n *   $ git clone https://github.com/cockpit-project/starter-kit.git\n *   $ cd starter-kit\n *   $ make vm\n *\n * 2. Install puppeteer, using the already installed chromium browser:\n *\n *   $ PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 npm install puppeteer@0.12.0\n *\n *   (You can also just do \"npm install puppeteer\" if you don't mind\n *   downloading an internal copy of Chromium and want to use the latest\n *   version.)\n *\n * 3. Run this test, with some debug output:\n *\n *   $ DEBUG=\"puppeteer:page,puppeteer:frame\" PYTHONPATH=bots/machine test/check-puppeteer.js\n */\n\nconst testOS = process.env[\"TEST_OS\"] || \"centos-7\";\n\nconst child_process = require('child_process');\nconst puppeteer = require(\"puppeteer\");\n\n// start virtual machine and return VM object; call vm.proc.kill() to stop it again\nfunction startVm() {\n    return new Promise((resolve, reject) => {\n        let proc = child_process.spawn(\"bots/machine/testvm.py\", [testOS], { stdio: [\"pipe\", \"pipe\", \"inherit\"] });\n        let buf = \"\";\n        proc.stdout.on(\"data\", data => {\n            buf += data.toString();\n            if (buf.indexOf(\"\\nRUNNING\\n\") > 0) {\n                let lines = buf.split(\"\\n\");\n                resolve({ proc: proc, ssh: lines[0], cockpit: lines[1] });\n            }\n        });\n        proc.on(\"error\", err => { throw `Failed to start vm-run: ${err}` });\n    });\n}\n\n// run shell command in VM object and return its output\nfunction vmExecute(vm, command) {\n    let cmd = vm.ssh + ' ' + command;\n    let out = child_process.execSync(cmd, { encoding: 'utf8' });\n    console.log(`vmExecute \"${cmd}\" output: ${out}`);\n    return out;\n}\n\n// return Puppeteer frame object for given frame ID\nfunction getFrame(page, id) {\n    return page.mainFrame().childFrames().find(f => f.name() == id);\n}\n\nasync function testStarterKit() {\n    const vm = await startVm();\n\n    const browser = await puppeteer.launch(\n        { headless: true, executablePath: 'chromium-browser', args: [ \"--no-sandbox\" /* to work in docker */ ] });\n\n    const page = await browser.newPage();\n\n    try {\n        // log in\n        await page.goto(vm.cockpit);\n        await page.type('#login-user-input', 'admin');\n        await page.type('#login-password-input', 'foobar');\n        await page.click('#login-button');\n\n        await page.waitFor('#host-nav a[title=\"Starter Kit\"]');\n        await page.goto(vm.cockpit + \"/starter-kit\");\n        let frame = getFrame(page, 'cockpit1:localhost/starter-kit');\n\n        // verify expected heading\n        await frame.waitFor('.container-fluid h2');\n        await frame.waitForFunction(() => document.querySelector(\".container-fluid h2\").innerHTML == \"Starter Kit\");\n\n        // verify expected host name\n        let hostname = vmExecute(vm, \"cat /etc/hostname\").trim();\n        await frame.waitFor('.container-fluid span');\n        await frame.waitForFunction(\n            h => document.querySelector(\".container-fluid span\").innerHTML == (\"Running on \" + h),\n            {}, hostname);\n    } catch (err) {\n        const attachments = process.env[\"TEST_ATTACHMENTS\"];\n        if (attachments) {\n            console.error(\"Test failed, taking screenshot...\");\n            await page.screenshot({ path: attachments + \"/testStarterKit-FAIL.png\"});\n        }\n        throw err;\n    } finally {\n        await browser.close();\n        vm.proc.kill();\n    }\n};\n\ntestStarterKit()\n    .catch(err => {\n        console.error(err);\n        process.exit(1);\n    });\n"
  },
  {
    "path": "guide/195/api-base1-patternfly.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>patternfly.css</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"cockpit-manifest.html\" title=\"cockpit.js: Manifests\">\n<link rel=\"next\" href=\"api-docker.html\" title=\"API: docker\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-manifest.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"api-docker.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"api-base1-patternfly\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2><span class=\"refentrytitle\">patternfly.css</span></h2>\n<p>patternfly.css — Patternfly standard style sheets</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsection\">\n<a name=\"api-base1-patternfly-description\"></a><h2>Description</h2>\n<pre class=\"programlisting\">\n&lt;link href=\"../base1/patternfly.css\" type=\"text/css\" rel=\"stylesheet\"&gt;\n@import url('../base1/patternfly.css');\n</pre>\n<p>The standard <a class=\"ulink\" href=\"https://www.patternfly.org/\" target=\"_top\">PatternFly</a> CSS stylesheets.\n        They automatically pull in the PatternFly and Bootstrap styles that they depend on.</p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/api-base1.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>API: base1</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"development.html\" title=\"Part III. Developer Guide\">\n<link rel=\"prev\" href=\"urls.html\" title=\"Cockpit URLs\">\n<link rel=\"next\" href=\"api-cockpit.html\" title=\"cockpit.js\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"urls.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"development.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"api-cockpit.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"reference\">\n<div class=\"titlepage\">\n<div><div><h1 class=\"title\">\n<a name=\"api-base1\"></a>API: base1</h1></div></div>\n<hr>\n</div>\n<div class=\"partintro\">\n<div></div>\n<p>This package contains basic support API available to other packages.</p>\n<div class=\"toc\">\n<p><b>Table of Contents</b></p>\n<dl class=\"toc\">\n<dt>\n<span class=\"refentrytitle\"><a href=\"api-cockpit.html\">cockpit.js</a></span><span class=\"refpurpose\"> — Basic cockpit API to interact with the system</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-dbus.html\">cockpit.js: DBus Client</a></span><span class=\"refpurpose\"> — DBus API communication</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-file.html\">cockpit.js: File Access</a></span><span class=\"refpurpose\"> — Reading, writing, and watching files.</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-http.html\">cockpit.js: HTTP Client</a></span><span class=\"refpurpose\"> — HTTP and REST API communication</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-spawn.html\">cockpit.js: Spawning Processes</a></span><span class=\"refpurpose\"> — Spawning processes or scripts</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-metrics.html\">cockpit.js: Metrics</a></span><span class=\"refpurpose\"> — Reading and streaming metric data</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-series-data.html\">cockpit.js: Series Data</a></span><span class=\"refpurpose\"> — Representing series data</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-channels.html\">cockpit.js: Raw Channels</a></span><span class=\"refpurpose\"> — Raw communication channels</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-location.html\">cockpit.js: Page Location and Jumping</a></span><span class=\"refpurpose\"> — Page location and navigation between components</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-locale.html\">cockpit.js: Localization</a></span><span class=\"refpurpose\"> — Localization and translations</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-error.html\">cockpit.js: Errors</a></span><span class=\"refpurpose\"> — Problem codes and messages</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-login.html\">cockpit.js: User Session</a></span><span class=\"refpurpose\"> — User information and login session state</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-util.html\">cockpit.js: Utilities</a></span><span class=\"refpurpose\"> — Various utility functions</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-cache.html\">cockpit.js: Object Cache</a></span><span class=\"refpurpose\"> — Caching and sharing data</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-manifest.html\">cockpit.js: Manifests</a></span><span class=\"refpurpose\"> — Manifest info</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"api-base1-patternfly.html\">patternfly.css</a></span><span class=\"refpurpose\"> — Patternfly standard style sheets</span>\n</dt>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/api-cockpit.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.js</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"next\" href=\"cockpit-dbus.html\" title=\"cockpit.js: DBus Client\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"api-base1.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-dbus.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"api-cockpit\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2><span class=\"refentrytitle\">cockpit.js</span></h2>\n<p>cockpit.js — Basic cockpit API to interact with the system</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsection\">\n<a name=\"api-cockpit-loading\"></a><h2>Loading cockpit.js</h2>\n<p><code class=\"code\">cockpit.js</code> should be loaded via a script tag.</p>\n<pre class=\"programlisting\">\n&lt;script src=\"../base1/cockpit.js\"&gt;\n</pre>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/api-console-html.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>console.html</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-docker.html\" title=\"API: docker\">\n<link rel=\"prev\" href=\"api-docker.html\" title=\"API: docker\">\n<link rel=\"next\" href=\"api-shell.html\" title=\"API: shell\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"api-docker.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-docker.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"api-shell.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"api-console-html\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2><span class=\"refentrytitle\">console.html</span></h2>\n<p>console.html — Container console component</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsection\">\n<a name=\"api-console-html-description\"></a><h2>Description</h2>\n<pre class=\"programlisting\">\n&lt;iframe src=\"http://server:9090/cockpit/@localhost/docker/console.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;\n</pre>\n<p>This is a Cockpit component that shows a live console for the container.\n        If the container has a TTY then this will be a live interactive terminal,\n        otherwise this shows log output.</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\">Component URL</span></p></td>\n<td><p><code class=\"code\">/cockpit/@localhost/docker/console.html</code></p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\">Container Identifier</span></p></td>\n<td>\n<p><code class=\"code\">#/6e272d82993c4e0d...</code></p>\n<p>The complete container identifier must be provided as shown in the hash above.</p>\n</td>\n</tr>\n</tbody>\n</table></div>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/api-docker.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>API: docker</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"development.html\" title=\"Part III. Developer Guide\">\n<link rel=\"prev\" href=\"api-base1-patternfly.html\" title=\"patternfly.css\">\n<link rel=\"next\" href=\"api-console-html.html\" title=\"console.html\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"api-base1-patternfly.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"development.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"api-console-html.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"reference\">\n<div class=\"titlepage\">\n<div><div><h1 class=\"title\">\n<a name=\"api-docker\"></a>API: docker</h1></div></div>\n<hr>\n</div>\n<div class=\"partintro\">\n<div></div>\n<p>This package contains components for control of Docker containers.</p>\n<div class=\"toc\">\n<p><b>Table of Contents</b></p>\n<dl class=\"toc\"><dt>\n<span class=\"refentrytitle\"><a href=\"api-console-html.html\">console.html</a></span><span class=\"refpurpose\"> — Container console component</span>\n</dt></dl>\n</div>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/api-logs-html.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>logs.html</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-system.html\" title=\"API: system\">\n<link rel=\"prev\" href=\"api-system.html\" title=\"API: system\">\n<link rel=\"next\" href=\"api-terminal-html.html\" title=\"terminal.html\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"api-system.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-system.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"api-terminal-html.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"api-logs-html\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2><span class=\"refentrytitle\">logs.html</span></h2>\n<p>logs.html — System log component</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsection\">\n<a name=\"api-logs-html-description\"></a><h2>Description</h2>\n<pre class=\"programlisting\">\n&lt;iframe src=\"http://127.0.0.1:9090/cockpit+app/@localhost/system/logs.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;\n</pre>\n<p>This is a Cockpit component that brings up system log viewer, with filtering\n        capabilities. On systemd based systems this displays the entries from journal.</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\">Component URL</span></p></td>\n<td><p><code class=\"code\">/cockpit+app/@localhost/system/logs.html</code></p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\">Filter by priority</span></p></td>\n<td>\n<p><code class=\"code\">#?prio=5</code></p>\n<p>Filters the log to show entries below the specific priority, inclusive. These\n              <a class=\"ulink\" href=\"https://en.wikipedia.org/wiki/Syslog#Severity_levels\" target=\"_top\">priorities are syslog levels</a>.\n              Specifying <code class=\"code\">*</code> as a priority will show all available entries. The default\n              priority is <code class=\"code\">3</code>.</p>\n</td>\n</tr>\n<tr>\n<td><p><span class=\"term\">Filter by service</span></p></td>\n<td>\n<p><code class=\"code\">#?service=sshd.service</code></p>\n<p>Filters the log to show entries related to the specific service. The format of\n              the service is specific to the logging implementation. For journald these are systemd\n              service unit names.</p>\n</td>\n</tr>\n<tr>\n<td><p><span class=\"term\">Filter by tag</span></p></td>\n<td>\n<p><code class=\"code\">#?tag=kernel</code></p>\n<p>Filters the log to show entries related to the specific syslog identifier.</p>\n</td>\n</tr>\n<tr>\n<td><p><span class=\"term\">Start at point</span></p></td>\n<td>\n<p><code class=\"code\">#?start=boot</code></p>\n<p>Filters the log to show entries after the specific point in time. Valid values\n              are <code class=\"code\">boot</code> (since last boot), <code class=\"code\">last-24h</code> (last 24 hours),\n              <code class=\"code\">last-week</code> (last seven days).</p>\n</td>\n</tr>\n<tr>\n<td><p><span class=\"term\">Show log entry</span></p></td>\n<td>\n<p><code class=\"code\">#/6e272d82993c4e0d...</code></p>\n<p>To show a specific log entry, put the log entry cursor in a path after\n              the hash above. Note that cursors are logging system specific, and journal\n              cursors are subject to change.</p>\n</td>\n</tr>\n</tbody>\n</table></div>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/api-shell-html.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>index.html</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-shell.html\" title=\"API: shell\">\n<link rel=\"prev\" href=\"api-shell.html\" title=\"API: shell\">\n<link rel=\"next\" href=\"api-system.html\" title=\"API: system\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"api-shell.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-shell.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"api-system.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"api-shell-html\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2><span class=\"refentrytitle\">index.html</span></h2>\n<p>index.html — Main cockpit shell, for a single machine</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsection\">\n<a name=\"api-shell-html-description\"></a><h2>Description</h2>\n<pre class=\"programlisting\">\n&lt;iframe src=\"http://127.0.0.1:9090/cockpit+app/@localhost/shell/index.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;\n</pre>\n<p>This is a Cockpit component that provides an interface to configure a\n        single machine. It loads other components on demand to make that happen.</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody><tr>\n<td><p><span class=\"term\">Component URL</span></p></td>\n<td><p><code class=\"code\">/cockpit+app/@localhost/shell/index.html</code></p></td>\n</tr></tbody>\n</table></div>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/api-shell.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>API: shell</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"development.html\" title=\"Part III. Developer Guide\">\n<link rel=\"prev\" href=\"api-console-html.html\" title=\"console.html\">\n<link rel=\"next\" href=\"api-shell-html.html\" title=\"index.html\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"api-console-html.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"development.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"api-shell-html.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"reference\">\n<div class=\"titlepage\">\n<div><div><h1 class=\"title\">\n<a name=\"api-shell\"></a>API: shell</h1></div></div>\n<hr>\n</div>\n<div class=\"partintro\">\n<div></div>\n<p>This package contains the shell that loads other components.</p>\n<div class=\"toc\">\n<p><b>Table of Contents</b></p>\n<dl class=\"toc\"><dt>\n<span class=\"refentrytitle\"><a href=\"api-shell-html.html\">index.html</a></span><span class=\"refpurpose\"> — Main cockpit shell, for a single machine</span>\n</dt></dl>\n</div>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/api-system.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>API: system</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"development.html\" title=\"Part III. Developer Guide\">\n<link rel=\"prev\" href=\"api-shell-html.html\" title=\"index.html\">\n<link rel=\"next\" href=\"api-logs-html.html\" title=\"logs.html\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"api-shell-html.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"development.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"api-logs-html.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"reference\">\n<div class=\"titlepage\">\n<div><div><h1 class=\"title\">\n<a name=\"api-system\"></a>API: system</h1></div></div>\n<hr>\n</div>\n<div class=\"partintro\">\n<div></div>\n<p>This package contains general components for basic control of a system.</p>\n<div class=\"toc\">\n<p><b>Table of Contents</b></p>\n<dl class=\"toc\">\n<dt>\n<span class=\"refentrytitle\"><a href=\"api-logs-html.html\">logs.html</a></span><span class=\"refpurpose\"> — System log component</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"api-terminal-html.html\">terminal.html</a></span><span class=\"refpurpose\"> — Server terminal component</span>\n</dt>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/api-terminal-html.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>terminal.html</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-system.html\" title=\"API: system\">\n<link rel=\"prev\" href=\"api-logs-html.html\" title=\"logs.html\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"api-logs-html.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-system.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td> </td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"api-terminal-html\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2><span class=\"refentrytitle\">terminal.html</span></h2>\n<p>terminal.html — Server terminal component</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsection\">\n<a name=\"api-terminal-html-description\"></a><h2>Description</h2>\n<pre class=\"programlisting\">\n&lt;iframe src=\"http://127.0.0.1:9090/cockpit+app/@localhost/system/terminal.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;\n</pre>\n<p>This is a Cockpit component that brings up a web-based terminal for\n        the logged in user.</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody><tr>\n<td><p><span class=\"term\">Component URL</span></p></td>\n<td><p><code class=\"code\">/cockpit+app/@localhost/system/terminal.html</code></p></td>\n</tr></tbody>\n</table></div>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/authentication.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Cockpit Authentication</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"guide.html\" title=\"Part I. Deployment Guide\">\n<link rel=\"prev\" href=\"startup.html\" title=\"Start up\">\n<link rel=\"next\" href=\"sso.html\" title=\"Single Sign On\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"startup.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"guide.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"sso.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"authentication\"></a>Cockpit Authentication</h2></div></div></div>\n<div class=\"toc\"><dl class=\"toc\">\n<dt><span class=\"section\"><a href=\"authentication.html#initial-auth\">Primary server authentication</a></span></dt>\n<dt><span class=\"section\"><a href=\"authentication.html#secondary-auth\">Secondary server authentication</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"authentication.html#password\">Password</a></span></dt>\n<dt><span class=\"section\"><a href=\"authentication.html#kerberos\">Kerberos</a></span></dt>\n<dt><span class=\"section\"><a href=\"authentication.html#public-key\">Public key</a></span></dt>\n</dl></dd>\n</dl></div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"initial-auth\"></a>Primary server authentication</h2></div></div></div>\n<p>While cockpit allows you to monitor and administer several servers at the\n      same time, there is always a primary server your browser connects to\n      that runs the Cockpit web service (cockpit-ws) through which connections to\n      additional servers are established.\n      See <a class=\"ulink\" href=\"https://raw.githubusercontent.com/cockpit-project/cockpit/master/doc/cockpit-transport.png\" target=\"_top\">this diagram</a> for how it works.</p>\n<p>By default the cockpit web service is installed on the base system and\n      <a class=\"link\" href=\"listen.html\" title=\"TCP Port and Address\">socket activated by systemd</a>. In this setup\n      access is controlled by a cockpit specific pam stack, generally located\n      at <code class=\"filename\">/etc/pam.d/cockpit</code>. By default this is configured\n      to allow you to login with the username and password of any local account on the\n      system or you can setup a <a class=\"link\" href=\"sso.html\" title=\"Single Sign On\">Kerberos based SSO\n      solution</a>.</p>\n<p>The web server can also be run from the <code class=\"filename\">cockpit/ws</code> docker\n      container. If you are running cockpit on an <a class=\"ulink\" href=\"https://www.projectatomic.io/\" target=\"_top\">\n      Atomic Host</a> this will be the default. In this setup, cockpit establishes an\n      SSH connection from the container to the underlying host, meaning that it is up to\n      your SSH server to grant access. To login with a local account, <code class=\"filename\">sshd\n      </code> will need to be configured to allow password based authentication.\n      Alternatively you can setup a <a class=\"link\" href=\"sso.html\" title=\"Single Sign On\">Kerberos based SSO\n      solution</a>.</p>\n<p>Like <code class=\"filename\">sshd</code>, cockpit can be configured to limit the number\n      of concurrent login attempts allowed. This is done by adding a <code class=\"code\">MaxStartups</code>\n      option to the <code class=\"code\">WebService</code> section of your <code class=\"code\">cockpit.conf</code>.\n      Additional connections will be dropped until authentication succeeds or\n      the connections are closed.</p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"secondary-auth\"></a>Secondary server authentication</h2></div></div></div>\n<p>Once you are able to login to the primary server you will be able to connect to\n      additional servers. These servers will need to be running an SSH server on port 22\n      and be configured to support one of the following authentication methods.</p>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h3 class=\"title\">\n<a name=\"password\"></a>Password</h3></div></div></div>\n<p>The target server will need to have password based authentication\n        enabled in <code class=\"filename\">sshd</code>. When this is setup for the first time,\n        Cockpit will ensure that the user connected to primary server has the\n        same password on the secondary server.</p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h3 class=\"title\">\n<a name=\"kerberos\"></a>Kerberos</h3></div></div></div>\n<p>The target server will need to be a member of the same domain as the\n        primary server and your domain must be whitelisted in your browser.\n        See the <a class=\"link\" href=\"sso.html\" title=\"Single Sign On\">SSO documentation</a> for how to set\n        this up.</p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h3 class=\"title\">\n<a name=\"public-key\"></a>Public key</h3></div></div></div>\n<p>When you successfully log into the primary server, an <code class=\"filename\">ssh-agent\n      </code> is started. The following keys are then preloaded into the\n      <code class=\"filename\">ssh-agent</code> provided they are supported by your SSH\n      version, present, with the correct permissions, and either unencrypted\n      or encrypted with the same password that was used to login.</p>\n<pre class=\"programlisting\">\n~/.ssh/id_rsa\n~/.ssh/id_dsa\n~/.ssh/id_ed25519\n~/.ssh/id_ecdsa\n</pre>\n<p>Cockpit provides an interface for loading other keys into the agent\n      that could not be automatically loaded.</p>\n<p>The target server will need to have public key authentication enabled in\n      <code class=\"filename\">sshd</code>, and the public key you wish to use must be present in\n      <code class=\"filename\">~/.ssh/authorized_keys</code>.</p>\n<p>Note that when a user is authenticated in this way the authentication\n      happens without a password, as such the standard cockpit reauthorization\n      mechanisms do not work. The user will only be able to obtain additional\n      privileges if they do not require a password.</p>\n</div>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-bridge.1.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit-bridge</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"cockpit-manual.html\" title=\"Manual pages\">\n<link rel=\"prev\" href=\"remotectl.8.html\" title=\"remotectl\">\n<link rel=\"next\" href=\"https.html\" title=\"SSL/TLS Usage\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"remotectl.8.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"cockpit-manual.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"https.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-bridge.1\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2><span class=\"refentrytitle\">cockpit-bridge</span></h2>\n<p>cockpit-bridge — Cockpit Host Bridge</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsynopsisdiv\">\n<h2>Synopsis</h2>\n<div class=\"cmdsynopsis\"><p><code class=\"command\">cockpit-bridge</code>  [<code class=\"option\">--help</code>] [<code class=\"option\">--packages</code>]</p></div>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-bridge-description\"></a><h2>DESCRIPTION</h2>\n<p>The <span class=\"command\"><strong>cockpit-bridge</strong></span> program is used by Cockpit to\n      relay messages and commands from the Web front end to the server. Among\n      other things it relays DBus, and spawns processes on behalf of the\n      Web user interface.</p>\n<p>This program is not routinely run by users or administrators. It\n      is in the <code class=\"code\">$PATH</code> so that Cockpit can find it when connecting\n      between hosts. However there are some diagnostics available when running\n      from the command line.</p>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-bridge-options\"></a><h2>OPTIONS</h2>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">--help</code></span></p></td>\n<td><p>\n            Show help options.\n          </p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">--interact=boundary</code></span></p></td>\n<td><p>Interact with the raw cockpit1 protocol. Useful for debugging and testing.\n            Specify a <code class=\"option\">boundary</code> which should be on an empty line between\n            messages.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">--packages</code></span></p></td>\n<td><p>List all available Cockpit packages and exit. Note this includes packages\n            available to the user running this command.</p></td>\n</tr>\n</tbody>\n</table></div>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-bridge-bugs\"></a><h2>BUGS</h2>\n<p>\n      Please send bug reports to either the distribution bug tracker or the\n      <a class=\"ulink\" href=\"https://github.com/cockpit-project/cockpit/issues/new\" target=\"_top\">upstream bug tracker</a>.\n    </p>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-bridge-author\"></a><h2>AUTHOR</h2>\n<p>Cockpit has been written by many\n      <a class=\"ulink\" href=\"https://github.com/cockpit-project/cockpit/\" target=\"_top\">contributors</a>.</p>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-bridge-also\"></a><h2>SEE ALSO</h2>\n<p>\n      <span class=\"citerefentry\"><span class=\"refentrytitle\">cockpit-ws</span>(8)</span>\n    </p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-cache.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.js: Object Cache</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"cockpit-util.html\" title=\"cockpit.js: Utilities\">\n<link rel=\"next\" href=\"cockpit-manifest.html\" title=\"cockpit.js: Manifests\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-util.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-manifest.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-cache\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2>cockpit.js: Object Cache</h2>\n<p>cockpit.js: Object Cache — Caching and sharing data</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsynopsisdiv\">\n<h2>Synopsis</h2>\n<p>If the same information is displayed by multiple components in Cockpit,\n    <code class=\"code\">cockpit.cache()</code> provides a way to share data between them. The shared\n    data should be simple objects, arrays, and values, and not contain functions or\n    other objects.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-cache-func\"></a><h2>cockpit.cache()</h2>\n<pre class=\"programlisting\">\ncache = cockpit.cache(key, provider, consumer)\n</pre>\n<p>Create a new cache object. The <code class=\"code\">key</code> should be a globally unique string\n      that describes the data being cached. This string must describe the data, across all\n      machines and all versions of cockpit. It is customary to include a version number in\n      the <code class=\"code\">key</code> string.</p>\n<pre class=\"programlisting\">\nfunction provider(result, key) {\n    result(\"myvalue\");\n\n    return {\n        close: function() {\n            /* closed */\n        }\n    };\n}\n</pre>\n<p>The <code class=\"code\">provider</code> is a function that will be invoked to start retrieving\n      data for the cache. It will be passed a <code class=\"code\">result</code> function as its first\n      argument. The <code class=\"code\">result</code> should be invoked whenever new data is available.\n      The <code class=\"code\">key</code> argument matches the key string the cache was created with.</p>\n<p>The <code class=\"code\">provider</code> can return an object with a <code class=\"code\">close</code> method.\n      This method will be invoked when the cache no longer needs data from the provider.</p>\n<pre class=\"programlisting\">\nfunction consumer(value, key) {\n    /* ... */\n}\n</pre>\n<p>The <code class=\"code\">consumer</code> is a function that will be passed new values when they\n      are available, whether they come from the <code class=\"code\">provider</code> or a source in a\n      different component/frame.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-cache-close\"></a><h2>cache.close()</h2>\n<pre class=\"programlisting\">\ncache.close()\n</pre>\n<p>Close a cache and stop calling its <code class=\"code\">consumer</code>. If the <code class=\"code\">provider</code>\n      was invoked, then the <code class=\"code\">close()</code> method it returned will be invoked.</p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-channels.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.js: Raw Channels</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"cockpit-series-data.html\" title=\"cockpit.js: Series Data\">\n<link rel=\"next\" href=\"cockpit-location.html\" title=\"cockpit.js: Page Location and Jumping\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-series-data.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-location.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-channels\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2>cockpit.js: Raw Channels</h2>\n<p>cockpit.js: Raw Channels — Raw communication channels</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsynopsisdiv\">\n<h2>Synopsis</h2>\n<p>At a low level Cockpit communicates with the system via messages passed\n      through various channels. These are usually exposed via higher level APIs,\n      such as the <code class=\"code\"><a class=\"link\" href=\"cockpit-spawn.html\" title=\"cockpit.js: Spawning Processes\">cockpit.spawn()</a></code> function.\n      It is rare to use raw channels directly.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-channels-channel\"></a><h2>cockpit.channel()</h2>\n<pre class=\"programlisting\">\nchannel = cockpit.channel(options)\n</pre>\n<p>This function creates a new channel for communication with the system.\n      It returns a new channel object. The <code class=\"code\">options</code> argument is a\n      plain object. At least the <code class=\"code\">\"payload\"</code> option is required, and\n      based on the payload type, other options may be required.</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"binary\"</code></span></p></td>\n<td><p>Set to <code class=\"code\">true</code> to transfer binary payloads. Both messages\n          sent via <a class=\"link\" href=\"cockpit-channels.html#cockpit-channels-send\" title=\"channel.send()\"><code class=\"code\">channel.send()</code></a>\n          and those received via\n          <a class=\"link\" href=\"cockpit-channels.html#cockpit-channels-message\" title=\"channel.onmessage\"><code class=\"code\">channel.onmessage</code></a>\n          should be arrays of bytes, either <code class=\"code\">Uint8Array</code> or <code class=\"code\">Array</code>\n          depending on browser support.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"host\"</code></span></p></td>\n<td><p>The host to open the channel to. If an alternate user or port is\n          required it can be specified as <code class=\"code\">\"user@myhost:port\"</code>. If no host\n          is specified then the correct one will be automatically selected based on the page\n          calling this function.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"payload\"</code></span></p></td>\n<td><p>The payload type for the channel. Only specific payload\n          types are supported.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"superuser\"</code></span></p></td>\n<td>\n<p>Set to <code class=\"code\">\"require\"</code> to open this channel as root. If the currently\n          logged in user is not permitted to become root (eg: via <code class=\"code\">pkexec</code>) then the\n          <code class=\"code\">channel</code> will immediately be\n          <a class=\"link\" href=\"cockpit-channels.html#cockpit-channels-close-ev\" title=\"channel.onclose\">closed</a> with a <code class=\"code\">\"access-denied\"</code>\n          problem code.</p>\n<p>Set to <code class=\"code\">\"try\"</code> to try to open the channel as root, but if that fails,\n          then fall back to an unprivileged channel.</p>\n</td>\n</tr>\n</tbody>\n</table></div>\n<p>The channel object returned has the following fields and methods and\n      events. You should call the\n      <code class=\"code\"><a class=\"link\" href=\"cockpit-channels.html#cockpit-channels-close\" title=\"channel.close()\">channel.close()</a></code>\n      method when done with the channel.</p>\n<p>A valid channel will always be returned and the is ready to\n      <code class=\"code\"><a class=\"link\" href=\"cockpit-channels.html#cockpit-channels-send\" title=\"channel.send()\">channel.send()</a></code>. The channel may\n      <a class=\"link\" href=\"cockpit-channels.html#cockpit-channels-close-ev\" title=\"channel.onclose\">close shortly afterword</a> due\n      to a failure.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-channels-binary\"></a><h2>channel.binary</h2>\n<p>Will be <code class=\"code\">true</code> for an binary channel. Will be set to <code class=\"code\">false</code> if the\n      channel is textual.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-channels-options\"></a><h2>channel.options</h2>\n<p>The options used to open this channel. This should not be changed.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-channels-valid\"></a><h2>channel.valid</h2>\n<p>Will be <code class=\"code\">true</code> for an open channel. Will be set to <code class=\"code\">false</code> if the channel\n      closes.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-channels-send\"></a><h2>channel.send()</h2>\n<pre class=\"programlisting\">\nchannel.send(data)\n</pre>\n<p>Send a message over the channel. The contents of the message depends on the\n      payload type of the channel. If a binary channel, then <code class=\"code\">data</code> is expected\n      to be an <code class=\"code\">Array</code> of bytes or a <code class=\"code\">Uint8Array</code>. If not binary,\n      then the <code class=\"code\">data</code> will be converted to a string if not already a string.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-channels-control\"></a><h2>channel.control()</h2>\n<pre class=\"programlisting\">\nchannel.control(options)\n</pre>\n<p>Notify the channel to tune certain parameters on the fly. The <code class=\"code\">options</code>\n      is a plain javascript object, and the contents depend on the <code class=\"code\">\"payload\"</code>\n      of the channel.</p>\n<p>One common operation is to set <code class=\"code\">\"command\"</code> to <code class=\"code\">\"done\"</code> in the\n      options field. To indicate that no further messages will be sent through the channel.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-channels-wait\"></a><h2>channel.wait()</h2>\n<pre class=\"programlisting\">\npromise = channel.wait([callback])\n</pre>\n<p>Returns a <code class=\"code\">promise</code> that is ready when the channel is ready, or fails if the\n      client closes. If a <code class=\"code\">callback</code> is specified, it is attached to the promise. The\n      promise will be rejected or resolved with the contents <code class=\"code\">options</code> passed to the\n      <a class=\"link\" href=\"cockpit-channels.html#cockpit-channels-onready\" title=\"channel.onready\">channel.onready</a> and\n      <a class=\"link\" href=\"cockpit-channels.html#cockpit-channels-close-ev\" title=\"channel.onclose\">channel.onclose</a> events respectively.</p>\n<p>In general it's not necessary to wait for the channel before starting to use the channel.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-channels-close\"></a><h2>channel.close()</h2>\n<pre class=\"programlisting\">\nchannel.close([options])\n</pre>\n<p>Close the channel.</p>\n<p>If <code class=\"code\">options</code> is present it can be a plain javascript object\n      containing additional channel close options to send to the peer. If closing for\n      because of a problem, set the <code class=\"code\">\"problem\"</code> field to a\n      <a class=\"link\" href=\"cockpit-error.html#cockpit-problems\" title=\"Problem Codes\">problem code</a>. If <code class=\"code\">options</code>\n      is not an object it will be treated as a <code class=\"code\">\"problem\"</code>.</p>\n<p>The <a class=\"link\" href=\"cockpit-channels.html#cockpit-channels-close-ev\" title=\"channel.onclose\">close event</a> will fire.\n      A channel can also be closed by a peer or if the underlying transport closes.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-channels-message\"></a><h2>channel.onmessage</h2>\n<pre class=\"programlisting\">\nchannel.addEventListener(\"message\", function(event, data) { ... })\n</pre>\n<p>An event triggered when the channel receives a message. The message is\n      passed as a string to the handler in the <code class=\"code\">data</code>. In the case of binary\n      channels <code class=\"code\">data</code> is an <code class=\"code\">Uint8Array</code> or an <code class=\"code\">Array</code>\n      of bytes if the former is not supported by the browser. The contents of\n      the message depends on the payload type of the channel.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-channels-oncontrol\"></a><h2>channel.oncontrol</h2>\n<pre class=\"programlisting\">\nchannel.addEventListener(\"control\", function(event, options) { ... })\n</pre>\n<p>An event triggered when the channel receives an control message in the\n      middle of the flow. One particular use is when the <code class=\"code\">command</code> is set to\n      <code class=\"code\">\"done\"</code> then no further messages will be received in the channel.\n      The exact form of these messages depend on the <code class=\"code\">\"payload\"</code> of the\n      channel.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-channels-onready\"></a><h2>channel.onready</h2>\n<pre class=\"programlisting\">\nchannel.addEventListener(\"ready\", function(event, options) { ... })\n</pre>\n<p>An event triggered when the other end of the channel is ready to start processing\n      messages. This indicates the channel is completely open. It is possible to start\n      sending messages on the channel before this point.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-channels-close-ev\"></a><h2>channel.onclose</h2>\n<pre class=\"programlisting\">\nchannel.addEventListener(\"close\", function(event, options) { ... })\n</pre>\n<p>An event triggered when the channel closes. This can happen either because\n      <a class=\"link\" href=\"cockpit-channels.html#cockpit-channels-close\" title=\"channel.close()\">channel.close()</a> function was called,\n      or if the peer closed the channel, or the underlying transport closes.</p>\n<p>The <code class=\"code\">options</code> will contain various close information, including a\n      <code class=\"code\">\"problem\"</code> field which will be set if the channel was closed because\n      of a problem.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-transport-origin\"></a><h2>cockpit.transport.origin</h2>\n<pre class=\"programlisting\">\ncockpit.transport.origin\n</pre>\n<p>The HTTP origin that is being used by the underlying channel transport. This is\n      read-only, you should not assign a value. If the browser supports\n      <code class=\"code\">window.location.origin</code> then this will be identical to that value.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-transport-host\"></a><h2>cockpit.transport.host</h2>\n<pre class=\"programlisting\">\ncockpit.transport.host\n</pre>\n<p>The host that this transport is going to talk to by default. This is\n      read-only, you should not assign a value. If the value is null that means that the\n      transport has not been setup yet.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-transport-csrf-token\"></a><h2>cockpit.transport.csrf_token</h2>\n<pre class=\"programlisting\">\ncockpit.transport.csrf_token\n</pre>\n<p>A cross site request forgery token for use with external channels. This becomes\n      valid once the connection is properly established.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-transport-options\"></a><h2>cockpit.transport.options</h2>\n<pre class=\"programlisting\">\ncockpit.transport.options\n</pre>\n<p>Initialization options received over the underlying channel transport. These\n      will be empty until connection is properly established.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-transport-wait\"></a><h2>cockpit.transport.wait()</h2>\n<pre class=\"programlisting\">\ncockpit.transport.wait(callback)\n</pre>\n<p>Call the <code class=\"code\">callback</code> function once the underlying channel transport is initialized.\n      This will start the initialization if not already in progress or completed. If the\n      channel transport is already initialized, then <code class=\"code\">callback</code> will be called\n      immediately.</p>\n<p>In general it's not necessary to wait for the transport before starting to open channels.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-transport-close\"></a><h2>cockpit.transport.close()</h2>\n<pre class=\"programlisting\">\ncockpit.transport.close([problem])\n</pre>\n<p>Close the underlying channel transport. All channels open channels will close.\n      The <code class=\"code\">problem</code> argument should be a problem code string. If not specified\n      it will default to <code class=\"code\">\"disconnected\"</code>.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-transport-filter\"></a><h2>cockpit.transport.filter()</h2>\n<pre class=\"programlisting\">\ncockpit.transport.filter(function(message, channelid, control) { ... }, [out])\n</pre>\n<p>Add a filter to the underlying channel transport. All incoming messages will be\n      passed to each of the filter callbacks that are registered. If the <code class=\"code\">out</code>\n      argument is equal to <code class=\"code\">true</code> then the filter will receive outgoing messages\n      that being sent on the underlying channel transport.</p>\n<p>This function is rarely used.</p>\n<p>Filter callbacks are called in the order they are registered. If a filter\n      callback returns <code class=\"code\">false</code> then the message will not be dispatched\n      further, whether to other filters, or to channels, etc.</p>\n<p>The <code class=\"code\">message</code> is the string or array with the raw message including,\n      the framing. The <code class=\"code\">channelid</code> is the channel identifier or an empty string\n      for control messages. If <code class=\"code\">control</code> is set then this is a control message,d\n      and the <code class=\"code\">control</code> argument contains the parsed JSON object of the\n      control message.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-transport-inject\"></a><h2>cockpit.transport.inject()</h2>\n<pre class=\"programlisting\">\ncockpit.transport.inject(message, [out])\n</pre>\n<p>Inject a message into the underlying channel transport. The <code class=\"code\">message</code>\n      should be a <code class=\"code\">string</code> or an array of bytes, and should be valid\n      according to the Cockpit message protocol. If the <code class=\"code\">out</code> argument is equal\n      to <code class=\"code\">false</code> then the message will be injected as an incoming message as if\n      it was received on the underlying channel transport.</p>\n<p>This function is rarely used. In general you should only <code class=\"code\">inject()</code>\n      messages you got from a <code class=\"code\"><a class=\"link\" href=\"cockpit-channels.html#cockpit-transport-filter\" title=\"cockpit.transport.filter()\">filter()</a></code>.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-base64-encode\"></a><h2>cockpit.base64_encode()</h2>\n<pre class=\"programlisting\">\nstring = cockpit.base64_encode(data)\n</pre>\n<p>Encode binary data into a string using the Base64 encoding. The <code class=\"code\">data</code>\n      argument can either be a <code class=\"code\">string</code>, an <code class=\"code\">Array</code>, an <code class=\"code\">ArrayBuffer</code>\n      or a <code class=\"code\">Uint8Array</code>. The return value is a string.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-base64-decode\"></a><h2>cockpit.base64_decode()</h2>\n<pre class=\"programlisting\">\ndata = cockpit.base64_decode(string, [constructor])\n</pre>\n<p>Decode binary data from a Base64 encoded string. The <code class=\"code\">string</code>\n      argument should be a javascript string. The returned <code class=\"code\">data</code>&gt; will be an\n      array of bytes.</p>\n<p>You can pass <code class=\"code\">Uint8Array</code>, <code class=\"code\">Array</code> or <code class=\"code\">String</code>\n      as an alternate <code class=\"code\">constructor</code> if you want the decoded data in an\n      alternate form. The default is to return an <code class=\"code\">Array</code>. Note that if you use a\n      <code class=\"code\">String</code> for the decoded data, then you must guarantee that the data\n      does not contain bytes that would be invalid for a string.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-utf8-encoder\"></a><h2>cockpit.utf8_encoder()</h2>\n<pre class=\"programlisting\">\nencoder = cockpit.utf8_encoder([constructor])\n</pre>\n<p>Create an encoder for encoding a string into a UTF8 sequence of bytes.</p>\n<p>You can pass <code class=\"code\">Uint8Array</code>, <code class=\"code\">Array</code> or <code class=\"code\">String</code>\n      as an alternate <code class=\"code\">constructor</code> if you want the decoded data in an\n      alternate form. The default is to return an <code class=\"code\">Array</code>.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-utf8-encoder-encode\"></a><h2>encoder.encode()</h2>\n<pre class=\"programlisting\">\ndata = encoder.encode(string)\n</pre>\n<p>Encode a <code class=\"code\">string</code> into a UTF8 sequence of bytes.</p>\n<p>The resulting <code class=\"code\">data</code> is an array of bytes, but it's type may be\n      modified by passing an alternate <code class=\"code\">constructor</code> to\n      <a class=\"link\" href=\"cockpit-channels.html#cockpit-utf8-encoder\" title=\"cockpit.utf8_encoder()\">cockpit.utf8_encoder()</a>.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-utf8-decoder\"></a><h2>cockpit.utf8_decoder()</h2>\n<pre class=\"programlisting\">\ndecoder = cockpit.utf8_decoder([fatal])\n</pre>\n<p>Creates a decoder to decode a UTF8 sequence of bytes data into a string.</p>\n<p>If the <code class=\"code\">fatal</code> is set to <code class=\"code\">true</code> then the <code class=\"code\">decoder</code>\n      will throw an exception when it encounters invalid UTF8 data. By default invalid data\n      will be substituted with special UTF8 characters.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-utf8-decoder-decode\"></a><h2>decoder.decode()</h2>\n<pre class=\"programlisting\">\nstring = decoder.decode(data, [options])\n</pre>\n<p>Decode an array of UTF8 bytes into a <code class=\"code\">string</code>. The <code class=\"code\">data</code>\n      argument may be an <code class=\"code\">Array</code>, a <code class=\"code\">Uint8Array</code> or a string containing\n      binary data.</p>\n<p>If <code class=\"code\">options</code> is passed it should be a plain javascript object. If\n      <code class=\"code\">options</code> has a <code class=\"code\">stream</code> property equal to <code class=\"code\">true</code>,\n      then multiple invocations of this function can be made with parts of the UTF8 sequence\n      of bytes. Any trailing bytes that don't yet build a complete unicode character, will be\n      cached until the next invocation. To drain the last data, call this function without\n      the <code class=\"code\">stream</code> property set.</p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-dbus.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.js: DBus Client</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"api-cockpit.html\" title=\"cockpit.js\">\n<link rel=\"next\" href=\"cockpit-file.html\" title=\"cockpit.js: File Access\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"api-cockpit.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-file.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-dbus\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2>cockpit.js: DBus Client</h2>\n<p>cockpit.js: DBus Client — DBus API communication</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsynopsisdiv\">\n<h2>Synopsis</h2>\n<p>Cockpit allows access to DBus services via this API.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-types\"></a><h2>DBus Types</h2>\n<p>DBus values are represented as javascript values and objects as follows:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">BYTE 'y'</code></span></p></td>\n<td><p>Javascript number.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">BOOLEAN 'b'</code></span></p></td>\n<td><p>Javascript boolean.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">INT16 'n'</code></span></p></td>\n<td><p>Javascript number.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">UINT16 'q'</code></span></p></td>\n<td><p>Javascript number.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">INT32 'i'</code></span></p></td>\n<td><p>Javascript number.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">UINT32 'u'</code></span></p></td>\n<td><p>Javascript number.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">INT64 'x'</code></span></p></td>\n<td><p>Javascript number.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">UINT64 't'</code></span></p></td>\n<td><p>Javascript number.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">DOUBLE 'd'</code></span></p></td>\n<td><p>Javascript number.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">STRING 's'</code></span></p></td>\n<td><p>Javascript string.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">OBJECT_PATH 'o'</code></span></p></td>\n<td><p>Javascript string.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">SIGNATURE 'g'</code></span></p></td>\n<td><p>Javascript string.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">ARRAY of BYTE 'ay'</code></span></p></td>\n<td><p>A string containing base64 encoded data.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">ARRAY of DICT_ENTRY with STRING keys 'a{s?}'</code></span></p></td>\n<td><p>A javascript plain object with the keys as property names.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">ARRAY of DICT_ENTRY with other keys 'a{??}'</code></span></p></td>\n<td><p>A javascript plain object each key JSON encoded into a string property\n            name.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">ARRAY of other</code></span></p></td>\n<td><p>A javascript array.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">VARIANT</code></span></p></td>\n<td><p>A javascript plain object with the <code class=\"code\">\"t\"</code> property set to a DBus type string,\n            and the <code class=\"code\">\"v\"</code> property set to a value.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">HANDLE 'h'</code></span></p></td>\n<td><p>A javascript object that describes a cockpit channel which represents the\n           passed file descriptor. The <code class=\"code\">payload</code> is always set to <code class=\"code\">stream</code>.\n           Pass it to <a class=\"link\" href=\"cockpit-channels.html#cockpit-channels-channel\" title=\"cockpit.channel()\">cockpit.channel()</a> to create\n           the channel and start reading or writing on it. Handles can only be\n           received, not sent from within cockpit.</p></td>\n</tr>\n</tbody>\n</table></div>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-dbus\"></a><h2>cockpit.dbus()</h2>\n<pre class=\"programlisting\">\nclient = cockpit.dbus(name, [options])\n</pre>\n<p>Create a DBus client for the given bus <code class=\"code\">name</code> (eg: service name). Use the\n      following functions to make DBus method calls, watch for events, etc. The optional\n      <code class=\"code\">options</code> argument is a javascript plain object, and may include:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"bus\"</code></span></p></td>\n<td><p>The DBus bus to connect to. Specifying <code class=\"code\">\"session\"</code> will\n            connect to the DBus user session bus, <code class=\"code\">\"user\"</code> will connect to the\n            user bus (on some systems this is identical to the session bus), and <code class=\"code\">\"system\"</code>\n            will connect to the DBus system bus. This defaults to \"system\" if not\n            present.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"host\"</code></span></p></td>\n<td><p>The host to open the channel to. If an alternate user or port is\n          required it can be specified as <code class=\"code\">\"user@myhost:port\"</code>. If no host is\n          specified then the correct one will be automatically selected based on the page\n          calling this function.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"superuser\"</code></span></p></td>\n<td>\n<p>Set to <code class=\"code\">\"require\"</code> to talk to this service as root.\n          The DBus service will see the DBus method calls and accesses as coming from root,\n          rather than the logged in user. This is useful for talking to services that do not\n          correctly use <a class=\"ulink\" href=\"https://www.freedesktop.org/software/polkit\" target=\"_top\">polkit</a>\n          to authorize administrative users. If the currently logged in user is not\n          permitted to become root (eg: via <code class=\"code\">pkexec</code>) then the <code class=\"code\">client</code> will\n          immediately be <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-onclose\" title=\"client.onclose\">closed</a> with a\n          <code class=\"code\">\"access-denied\"</code> problem code.</p>\n<p>Set to <code class=\"code\">\"try\"</code> to try to talk as root, but if that fails,\n          fall back to unprivileged.</p>\n</td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"track\"</code></span></p></td>\n<td><p>It is valid for a DBus service to exit, and be restarted in such a\n          way that clients continue to talk to it across the restart. Some services are not\n          written with this in mind. If the <code class=\"code\">\"track\"</code> option is set to\n          <code class=\"code\">true</code> then the channel will close when the service exits and/or disconnects\n          from the DBus bus.</p></td>\n</tr>\n</tbody>\n</table></div>\n<p>If the <code class=\"code\">name</code> argument is null, and no options other than <code class=\"code\">\"bus\"</code>\n      are specified, then a shared DBus <code class=\"code\">client</code> is created. When using such a client\n      with a DBus bus, a <code class=\"code\">\"name\"</code> option must be specified on various other methods\n      in order to specify which client to talk to.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-wait\"></a><h2>client.wait()</h2>\n<pre class=\"programlisting\">\npromise = client.wait([callback])\n</pre>\n<p>Returns a <code class=\"code\">promise</code> that is ready when the client is ready, or fails if the\n      client closes. If a <code class=\"code\">callback</code> is specified, it is attached to the promise.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-close\"></a><h2>client.close()</h2>\n<pre class=\"programlisting\">\nclient.close([problem])\n</pre>\n<p>Close the DBus client. If <code class=\"code\">problem</code> is specified it should be a\n      <a class=\"link\" href=\"cockpit-error.html#cockpit-problems\" title=\"Problem Codes\">problem code</a> string.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-onclose\"></a><h2>client.onclose</h2>\n<pre class=\"programlisting\">\nclient.addEventListener(\"close\", function(options) { ... })\n</pre>\n<p>An event triggered when the DBus client closes. This can happen either because\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-close\" title=\"client.close()\">client.close()</a> function was called,\n      or the DBus service went away, or some other problem or disconnection.</p>\n<p>The <code class=\"code\">options</code> will contain various close information, including a\n      <code class=\"code\">\"problem\"</code> field which will be set if the channel was closed because\n      of a problem.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-onowned\"></a><h2>client.onowner</h2>\n<pre class=\"programlisting\">\nclient.addEventListener(\"owner\", function(event, owner) { ... })\n</pre>\n<p>An event triggered when the owner of the DBus name changes. The owner\n      value will be the id of the name owner on the bus or null if the name\n      is unowned. The absence of an owner should not be treated as a disconnection.\n      However this makes it possible to take some action based on the\n      actual status of the service, for example disconnecting a pending signal handler.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-options\"></a><h2>client.options</h2>\n<p>Set to the options used when creating the client. Will not change for the life of\n      the client.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-unique-name\"></a><h2>client.unique_name</h2>\n<p>The unique DBus name of the client. Initially null, and becomes valid once the\n      the client is ready.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxy\"></a><h2>client.proxy()</h2>\n<pre class=\"programlisting\">\nproxy = client.proxy([interface, path], [options])\n</pre>\n<p>Create proxy javascript object for a DBus <code class=\"code\">interface</code>. At the\n      specified DBus object <code class=\"code\">path</code>. The proxy will have\n      properties, methods and signals from to the DBus interface, and allows for\n      natural interaction. If no <code class=\"code\">interface</code> is specified then the DBus\n      bus name of the client is used. If no <code class=\"code\">path</code> is specified, then\n      the DBus name of the client is converted to a path.</p>\n<p>If creating lots of proxies for a given <code class=\"code\">interface</code> it is more\n      efficient to use the\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxies\" title=\"client.proxies()\"><code class=\"code\">client.proxies()</code></a>\n      function.</p>\n<p>The proxy is loaded when the\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy-valid\" title=\"proxy.valid\"><code class=\"code\">proxy.valid</code></a> field is\n      <code class=\"code\">true</code>, and it is set to <code class=\"code\">false</code> if the underlying\n      <code class=\"code\">interface</code> and/or <code class=\"code\">path</code> don't or no longer exist, or\n      the <code class=\"code\">client</code> has closed. You can wait for proxy to become valid\n      by passing a callback to its\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy-wait\" title=\"proxy.wait()\"><code class=\"code\">proxy.wait()</code></a> function.\n      The <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy-onchanged\" title=\"proxy.onchanged\"><code class=\"code\">proxy.onchanged</code></a>\n      event will also fire when the proxy becomes valid or invalid. DBus properties and\n      methods on the proxy are not defined until the proxy becomes valid.</p>\n<pre class=\"programlisting\">\nvalue = proxy.Prop1\nproxy.WritableProp = value\n</pre>\n<p>All DBus properties on the <code class=\"code\">interface</code> that start with an upper case\n      letter (as is convention) will be automatically defined on this proxy, and will update\n      their values as the DBus property values change. In addition the\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy-onchanged\" title=\"proxy.onchanged\"><code class=\"code\">proxy.onchanged</code></a> event\n      will fire every time the properties change.</p>\n<p>If you assign a value to a writable property on the proxy, the proxy will try to set\n      that property on the DBus <code class=\"code\">interface</code> at <code class=\"code\">path</code>. The actual proxy\n      property value will not update until the DBus service has notified the proxy of the\n      change. If setting a property fails a warning will be logged. In order to have more\n      reliable setting of properties, or track when they have been set, or if setting fails,\n      use the <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-call\" title=\"client.call()\"><code class=\"code\">client.call()</code></a> directly.\n      It should be noted that DBus service implementations may also be inconsistent in\n      their behavior when setting a property fails.</p>\n<p>You can access the raw property data using the\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy-data\" title=\"proxy.data\"><code class=\"code\">proxy.data</code></a> field, including\n      data for properties that do not start with an upper case letter.</p>\n<pre class=\"programlisting\">\nproxy.Method(arg1, arg2)\n    .done(function(retval1, retval2) {\n        ...\n    })\n    .fail(function(ex) {\n        ...\n    });\n</pre>\n<p>All DBus methods on the <code class=\"code\">interface</code> that start with an upper case\n      letter (as is convention) will be automatically defined on this proxy. These\n      methods are called with arguments as normal javascript arguments. A\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>\n      that will complete successfully when the method returns, or fail if an error occurs.\n      The return values from the DBus method will be passed to the <code class=\"code\">done</code> handler\n      function directly.</p>\n<p>Methods that do not start with an upper case letter can be invoked by using\n      the usual <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy-call\" title=\"proxy.call()\"><code class=\"code\">proxy.call()</code></a> directly.</p>\n<pre class=\"programlisting\">\nproxy.addEventListener(\"Signal\", function(event, arg1, arg2) {\n    ...\n});\n</pre>\n<p>All DBus signals on the <code class=\"code\">interface</code> that start with an upper case\n      letter (as is convention) will be automatically emit events on this proxy. These\n      events will contain the signal arguments after the standard <code class=\"code\">event</code>\n      argument.</p>\n<p>Signals that do not start with an upper case letter can be subscribed to by\n      using <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy-signal\" title=\"proxy.onsignal\"><code class=\"code\">proxy.onsignal</code></a>\n      directly.</p>\n<p>Usually a proxy asks the <code class=\"code\">client</code> to watch and notify it of changes\n      to the relevant object or path. You can pass an <code class=\"code\">options</code> argument with\n      the <code class=\"code\">watch</code> field set to <code class=\"code\">false</code> to prevent this.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxy-client\"></a><h2>proxy.client</h2>\n<p>Set to the DBus client of the proxy. Will not change for the life of\n      the proxy.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxy-path\"></a><h2>proxy.path</h2>\n<p>Set to the DBus object path of the proxy. Will not change for the life of\n      the proxy.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxy-iface\"></a><h2>proxy.iface</h2>\n<p>Set to the DBus interface name of the proxy. Will not change for the life\n      of the proxy.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxy-valid\"></a><h2>proxy.valid</h2>\n<p>Set to <code class=\"code\">true</code> when the proxy's DBus interface is present at its\n      DBus path, and all information for the proxy has loaded. Is set to <code class=\"code\">false</code>\n      while loading, and after the proxy no longer refers a DBus interface and path.\n      Also set to <code class=\"code\">false</code> if the <code class=\"code\">client</code> closes.</p>\n<p>Use the by <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy-wait\" title=\"proxy.wait()\"><code class=\"code\">proxy.wait()</code></a>\n      function to wait for a proxy to load. The\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy-onchanged\" title=\"proxy.onchanged\"><code class=\"code\">proxy.onchanged</code></a>\n      event will also be emitted when the proxy becomes valid or invalid. DBus properties and\n      methods on the proxy are not defined until the proxy becomes valid.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxy-data\"></a><h2>proxy.data</h2>\n<p>A plain javascript object containing all the raw property data that this\n      proxy has loaded. This will be updated automatically as the proxy is notified\n      of property changes from the DBus service. The\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy-onchanged\" title=\"proxy.onchanged\"><code class=\"code\">proxy.onchanged</code></a>\n      event will be emitted when it changes.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxy-call\"></a><h2>proxy.call()</h2>\n<pre class=\"programlisting\">\ninvocation = proxy.call(method, args, [options])\n</pre>\n<p>Make a DBus method call on this proxy.</p>\n<p>For DBus methods that start with an upper case letter, is usually more convenient\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy\" title=\"client.proxy()\">to call the method directly on the proxy</a>.\n      However if methods that do not follow the usual DBus convention,\n      or specify additional options, or the caller cannot be sure that the method actually\n      exists, you can use this method.</p>\n<p>This function also works on proxies that have are still loading and have not\n      become valid yet.</p>\n<p>The <code class=\"code\">method</code> should be a DBus method name, and the <code class=\"code\">args</code>\n      should be an array of arguments to pass to the method. The <code class=\"code\">options</code>\n      are <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-call\" title=\"client.call()\">described elsewhere</a>.</p>\n<p>The returned value is identical to the one returned from\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-call\" title=\"client.call()\">client.call()</a>. It is a\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>\n      that will complete successfully when the method returns, or fail if an error occurs.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxy-wait\"></a><h2>proxy.wait()</h2>\n<pre class=\"programlisting\">\npromise = proxy.wait()\nproxy.wait(function() {\n    ...\n});\n</pre>\n<p>Wait for a proxy to finish loading. This function returns a promise. If a callback function\n      is passed as an argument then that function will be invoked when the proxy is ready.\n      If this method is called after a proxy has already loaded, then the promise will be\n      resolved immediately, and any callback will be invoked immediately. Use the promise or\n      <code class=\"code\">proxy.valid</code> to determine whether the proxy is valid.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxy-onchanged\"></a><h2>proxy.onchanged</h2>\n<pre class=\"programlisting\">\nproxy.addEventListener(\"changed\", function(event, data) {\n    ...\n});\n</pre>\n<p>This event is emitted when the proxy's properties change.</p>\n<p>The <code class=\"code\">data</code> has the following form, and will only include\n      properties that have changed:</p>\n<pre class=\"programlisting\">\n{\n    \"Prop1\": \"value\",\n    \"Prop2\": 5\n}\n</pre>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxy-signal\"></a><h2>proxy.onsignal</h2>\n<pre class=\"programlisting\">\nproxy.addEventListener(\"signal\", function(event, name, args) {\n    ...\n});\n</pre>\n<p>This event is emitted when the proxy's emits an event.</p>\n<p>For most events, that have names which start with an upper case letter, you can\n      just <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy\" title=\"client.proxy()\">connect to that event as a signal directly</a>.\n      However if you wish to be notified when any signal is emitted, or for signals that do not\n      follow the usual DBus convention, you can connect to this event.</p>\n<p>The <code class=\"code\">name</code> is the DBus signal name, and the <code class=\"code\">args</code> is an array\n      of arguments that were emitted with the signal.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxies\"></a><h2>client.proxies()</h2>\n<pre class=\"programlisting\">\nproxies = client.proxies([interface], [path_namespace], [options])\n</pre>\n<p>Create <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy\" title=\"client.proxy()\">proxy javascript objects</a> for\n      a DBus interfaces. The proxies will have properties, methods and signals from\n      the DBus <code class=\"code\">interface</code>, and allow for natural interaction. If no\n      <code class=\"code\">interface</code> is specified then the DBus bus name of the client is used.\n      If no <code class=\"code\">path_namespace</code> is provided then <code class=\"code\">\"/\"</code> will be used.</p>\n<p>Proxies will be automatically created for instances of the\n      <code class=\"code\">interface</code> available at the DBus service. The optional\n      <code class=\"code\">path_namespace</code> argument can be used to restrict the proxies for\n      instances that have DBus paths which have the namespace path prefix.</p>\n<pre class=\"programlisting\">\nproxy1 = proxies[\"/dbus/path1\"];\nproxy2 = proxies[\"/dbus/path2\"];\nfor (proxy in proxies) {\n    ...\n}\n</pre>\n<p>The returned <code class=\"code\">proxies</code> object will is used as a dictionary,\n      and will have values containing proxies for DBus interface instances, with the\n      keys being the DBus paths of those instances. It is possible to enumerate over\n      the returned <code class=\"code\">proxies</code>.</p>\n<p>Proxies will be automatically added and removed from the <code class=\"code\">proxies</code>\n      object as they appear and disappear in the service. The\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxies-onadded\" title=\"proxies.onadded\"><code class=\"code\">proxies.onadded</code></a>\n      and <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxies-onremoved\" title=\"proxies.onremoved\"><code class=\"code\">proxies.onremoved</code></a>\n      events will be emitted. DBus services may not support notifications of paths\n      disappearing.</p>\n<p>Use the <code class=\"code\">proxies.wait()</code> function to be notified when the initial\n      set of proxies has been populated.</p>\n<p>Usually a proxies ask the <code class=\"code\">client</code> to watch and be notified of changes\n      to the relevant object or path. You can pass an <code class=\"code\">options</code> argument with\n      the <code class=\"code\">watch</code> field set to <code class=\"code\">false</code> to prevent this.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxies-wait\"></a><h2>proxies.wait()</h2>\n<pre class=\"programlisting\">\npromise = proxies.wait()\nproxies.wait(function() {\n    ...\n});\n</pre>\n<p>Wait for a <code class=\"code\">proxies</code> object to populate its initial set of proxies.\n      This function returns a promise. If a callback function is passed as an argument then\n      that function will be invoked when the proxies are ready. If this method is called after\n      the proxies have populated, then the promise will be resolved immediately, and any callback\n      will be invoked immediately.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxies-client\"></a><h2>proxies.client</h2>\n<p>Set to the DBus client of the proxies. Will not change.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxies-iface\"></a><h2>proxies.iface</h2>\n<p>Set to the DBus interface name of the proxies. Will not change.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxies-path_namespace\"></a><h2>proxies.path_namespace</h2>\n<p>Set to the DBus path namespace used which the proxies must have as a DBus\n      path prefix. Will not change.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxies-onadded\"></a><h2>proxies.onadded</h2>\n<pre class=\"programlisting\">\nproxies.addEventListener(\"added\", function(event, proxy) {\n    ...\n})\n</pre>\n<p>This event is emitted when a proxy is added to the <code class=\"code\">proxies</code> object.\n      The proxy will already have loaded.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxies-onchanged\"></a><h2>proxies.onchanged</h2>\n<pre class=\"programlisting\">\nproxies.addEventListener(\"changed\", function(event, proxy) {\n    ...\n})\n</pre>\n<p>This event is emitted when one of the proxy in the <code class=\"code\">proxies</code> object\n      changes its properties.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-proxies-onremoved\"></a><h2>proxies.onremoved</h2>\n<pre class=\"programlisting\">\nproxies.addEventListener(\"removed\", function(event, proxy) {\n    ...\n})\n</pre>\n<p>This event is emitted when a proxy is removed to the <code class=\"code\">proxies</code> object.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-call\"></a><h2>client.call()</h2>\n<pre class=\"programlisting\">\ninvocation = client.call(path, interface, method, args, [options])\n</pre>\n<p>Make a DBus method call.</p>\n<p>The <code class=\"code\">path</code> is the DBus object path to make\n      the call on, <code class=\"code\">interface</code> is the DBus interface for the method and\n      <code class=\"code\">method</code> is the name of the method to call. The <code class=\"code\">args</code> is an\n      array of arguments to pass to the method, each of which must be appropriate for the\n      expected <a class=\"link\" href=\"cockpit-dbus.html\" title=\"cockpit.js: DBus Client\">DBus type</a> of that argument. The\n      <code class=\"code\">args</code> may be <code class=\"code\">null</code> if no arguments are to be sent.</p>\n<p>The returned value is a\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>\n      that will complete successfully when the method returns, or fail if an error occurs.</p>\n<p>If <code class=\"code\">options</code> is specified it should be a plain javascript object,\n      which may contain the following properties:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">flags</code></span></p></td>\n<td><p>A string containing DBus message flags. The character <code class=\"code\">\"i\"</code>\n            indicates to the dbus service that interactive authentication is allowed. If the\n            entire <code class=\"code\">flags</code> field is missing, then <code class=\"code\">\"i\"</code> is set by\n            default.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">type</code></span></p></td>\n<td><p>A valid DBus type signature to use when calling the method. In the\n            absence of this, the DBus service will be introspected (and the result cached) to\n            ask what the method type signature is.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">timeout</code></span></p></td>\n<td><p>The timeout of the call in milliseconds. The call will fail with\n           the <code class=\"code\">\"timeout\"</code> problem code. If \"timeout\" is not given,\n           the call will never time out.</p></td>\n</tr>\n</tbody>\n</table></div>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-done\"></a><h2>invocation.done()</h2>\n<pre class=\"programlisting\">\ninvocation.done(function(args, options) { ... })\n</pre>\n<p>This is a standard\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>\n      method. It sets up a handler to be called when the DBus method call finishes\n      successfully.</p>\n<p>The <code class=\"code\">args</code> argument is an array of return values from the DBus method.\n      Each of them will be converted to an appropriate\n      <a class=\"link\" href=\"cockpit-dbus.html\" title=\"cockpit.js: DBus Client\">javascript type</a>.</p>\n<p>The <code class=\"code\">options</code> argument may contain additional information about the\n      reply. If the <code class=\"code\">type</code> option was specified when performing the method call,\n      then the <code class=\"code\">options</code> in the reply here will also contain a <code class=\"code\">type</code>\n      field containing the DBus type signature of the output. If the <code class=\"code\">flags</code> option\n      was specified when performing the call then the <code class=\"code\">options</code> in the reply here\n      will contain message flags. Possible out message flags are:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">&gt;</code></span></p></td>\n<td><p>A big endian message.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">&lt;</code></span></p></td>\n<td><p>A little endian message.</p></td>\n</tr>\n</tbody>\n</table></div>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-fail\"></a><h2>invocation.fail()</h2>\n<pre class=\"programlisting\">\ninvocation.fail(function(exception) { ... })\n</pre>\n<p>This is a standard\n      <a class=\"ulink\" href=\"https://api.jquery.com/category/deferred-object/\" target=\"_top\">jQuery promise</a> method.\n      It sets up a handler to be called when the DBus method call fails.</p>\n<p>The <code class=\"code\">exception</code> object passed to the handler can have the\n      following properties:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">problem</code></span></p></td>\n<td><p>A <a class=\"link\" href=\"cockpit-error.html#cockpit-problems\" title=\"Problem Codes\">problem code</a> string when\n            a problem occurred starting or communicating with the DBus service. This is\n            <code class=\"code\">null</code> in the cases where an actual DBus error was occurred.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">name</code></span></p></td>\n<td><p>The DBus error name. This will be <code class=\"code\">null</code> in cases where the\n          failure was not due to a DBus error.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">message</code></span></p></td>\n<td><p>A DBus error message. This will be <code class=\"code\">null</code> in cases where the\n          failure was not due to a DBus error.</p></td>\n</tr>\n</tbody>\n</table></div>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-always\"></a><h2>invocation.always()</h2>\n<pre class=\"programlisting\">\ninvocation.always(function() { ... })\n</pre>\n<p>This is a standard\n      <a class=\"ulink\" href=\"https://api.jquery.com/category/deferred-object/\" target=\"_top\">jQuery promise</a> method.\n      It sets up a handler to be called when the DBus method call finishes whether successfully,\n      or fails.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-subscribe\"></a><h2>client.subscribe()</h2>\n<pre class=\"programlisting\">\nsubscription = client.subscribe(match, function(path, interface, signal, args) { ... })\n</pre>\n<p>Subscribe to signals. The <code class=\"code\">match</code> argument is a javascript plain object which\n      defines what signals to subscribe to. Each property in the <code class=\"code\">match</code> argument restricts\n      signals subscribed to. If a property is not present then it is treated as a wildcard, matching\n      anything. If an empty object is specified as <code class=\"code\">match</code> then all signals will be\n      subscribed to. The <code class=\"code\">match</code> argument may contain the following properties:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">interface</code></span></p></td>\n<td><p>A DBus interface to match.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">path</code></span></p></td>\n<td><p>A DBus object path to match. May not be used together with the\n          <code class=\"code\">path_namespace</code> property. It should be a valid DBus object path,\n          that is, it should have no trailing slash.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">path_namespace</code></span></p></td>\n<td><p>A DBus object path prefix to match. Any paths in the hierarchy below this\n          top path will match. May not be used together with the <code class=\"code\">path</code>\n          property.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">member</code></span></p></td>\n<td><p>The DBus signal name to match.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">arg0</code></span></p></td>\n<td><p>Matches the first argument of a DBus message, which must be a\n           string.</p></td>\n</tr>\n</tbody>\n</table></div>\n<p>The handler passed as the second argument will be invoked when the signal is received.\n      A <code class=\"code\">subscription</code> is returned which can be used to remove the subscription by\n      calling its <code class=\"code\">subscription.remove()</code> method.</p>\n<p>It is not a problem to subscribe to the same signals more than once, with identical\n      or slightly different <code class=\"code\">match</code> arguments.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-remove\"></a><h2>subscription.remove()</h2>\n<pre class=\"programlisting\">\nsubscription.remove()\n</pre>\n<p>Unsubscribe from the DBus signal subscription.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-watch\"></a><h2>client.watch()</h2>\n<pre class=\"programlisting\">\nwatch = client.watch(path)\nwatch = client.watch({ \"path_namespace\": path_namespace, \"interface\": interface })\n</pre>\n<p>Watch for property and interface changes on the given DBus object\n      <code class=\"code\">path</code> DBus <code class=\"code\">path_namespace</code>. If <code class=\"code\">interface</code> is\n      specified only properties on that DBus interface will be watched.</p>\n<p>The <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy\" title=\"client.proxy()\"><code class=\"code\">client.proxy()</code></a> and\n        <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxies\" title=\"client.proxies()\"><code class=\"code\">client.proxies()</code></a> functions and\n      the objects they return are high level wrappers around <code class=\"code\">client.watch()</code>.</p>\n<p>The property and interface changes will be available in raw form on the\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-onnotify\" title=\"client.onnotify\"><code class=\"code\">client.onnotify</code></a> event.</p>\n<p>Property and interface changes that are caused by a method call or signal will\n      show up before that method call reply is received, or signal event is triggered.\n      It should be possible to rely on this guarantee, unless the DBus service in question\n      behaves incorrectly. Internally these watches work well with code that implements the\n      <a class=\"ulink\" href=\"https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager\" target=\"_top\">ObjectManager</a>\n      portion of the DBus specification. If no ObjectManager implementation is available, the\n      watch falls back to using DBus\n      <a class=\"ulink\" href=\"https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-introspectable\" target=\"_top\">Introspection</a> along with the usual\n      <a class=\"ulink\" href=\"https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties\" target=\"_top\">PropertiesChanged</a> signal. If the DBus service implements none of these, or implements them in an\n      inconsistent manner, then this function will provide inconsistent or unexpected\n      results.</p>\n<p>The parameter is either a DBus <code class=\"code\">path</code> or a plain javascript object\n      with zero or more of the following fields. If an empty javascript object is used as\n      an argument, then all paths, interfaces and properties will be watched.</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">interface</code></span></p></td>\n<td><p>Watch properties on this DBus interface.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">path</code></span></p></td>\n<td><p>Watch interfaces and properties at this DBus path. May not be\n            used together with the <code class=\"code\">path_namespace</code> property.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">path_namespace</code></span></p></td>\n<td><p>Watch interfaces and properties under this DBus path. It should\n            be a valid DBus object path, that is, it should have no trailing slash.\n            If an ObjectManager implementation is available at this interface, then it\n            is used. May not be used together with the <code class=\"code\">path</code> property.</p></td>\n</tr>\n</tbody>\n</table></div>\n<p>The returned value is a\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>\n      that will complete successfully when the watch has populated its initial set of properties\n      and interfaces, and these have been notified via\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-onnotify\" title=\"client.onnotify\"><code class=\"code\">client.onnotify</code></a>.</p>\n<p>A watch can be removed by calling the\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-watch-remove\" title=\"watch.remove()\"><code class=\"code\">watch.remove()</code></a> method on\n      the returned value. If identical watches are added more than once, then they must\n      also be removed the same number of times before the removal takes effect.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-watch-done\"></a><h2>watch.done()</h2>\n<pre class=\"programlisting\">\nwatch.done(function() { ... })\n</pre>\n<p>This is a standard\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>\n      method. It sets up a handler to be called when the watch has populated its initial\n      properties and interfaces.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-watch-fail\"></a><h2>watch.fail()</h2>\n<pre class=\"programlisting\">\nwatch.fail(function() { ... })\n</pre>\n<p>This is a standard\n      <a class=\"ulink\" href=\"https://api.jquery.com/category/deferred-object/\" target=\"_top\">jQuery promise</a>\n      method. It sets up a handler to be called if the watch fails to populate its initial\n      properties and interfaces. Note that a watch will only fail if the DBus client\n      closes or is somehow disconnected. It does not fail in the case of missing\n      interfaces or properties.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-watch-always\"></a><h2>watch.always()</h2>\n<pre class=\"programlisting\">\nwatch.always(function() { ... })\n</pre>\n<p>This is a standard\n      <a class=\"ulink\" href=\"https://api.jquery.com/category/deferred-object/\" target=\"_top\">jQuery promise</a>\n      method. It sets up a handler to be called when the watch has populated its initial\n      properties and interfaces or has failed to do so.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-watch-remove\"></a><h2>watch.remove()</h2>\n<pre class=\"programlisting\">\nwatch.remove()\n</pre>\n<p>Remove the watch. This may not have any immediate effect if other watches are in\n      place. In particular, if identical watches are added more than once, then they must\n      also be removed the same number of times before the removal takes effect.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-onnotify\"></a><h2>client.onnotify</h2>\n<pre class=\"programlisting\">\nclient.addEventListener(\"notify\", function(data) { ... })\n</pre>\n<p>An event triggered when\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-watch\" title=\"client.watch()\">watched</a> properties or interfaces change.</p>\n<p>The <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy\" title=\"client.proxy()\"><code class=\"code\">client.proxy()</code></a> and\n        <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxies\" title=\"client.proxies()\"><code class=\"code\">client.proxies()</code></a> functions and\n        the objects they return are high level wrappers around the <code class=\"code\">data</code> provided\n        by this event.</p>\n<p>The <code class=\"code\">data</code> has the following form:</p>\n<pre class=\"programlisting\">\n{\n    \"/path1\": {\n        \"org.Interface1\": {\n            \"Prop1\": \"value\",\n            \"Prop2\": 5\n        },\n        \"org.Interface2\": null\n    }\n}\n</pre>\n<p>Multiple paths may be present, each of which may have multiple interfaces, each\n      of which may have multiple properties. The first time a given path and interface is\n      emitted from this signal, it will have all its properties and interfaces. Thereafter\n      only changes are noted. If an interface is set to <code class=\"code\">null</code>, then that\n      interface has disappeared.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-notify\"></a><h2>client.notify()</h2>\n<pre class=\"programlisting\">\nclient.notify(data)\n</pre>\n<p>Emits a synthetic <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-onnotify\" title=\"client.onnotify\"><code class=\"code\">notify</code></a> event.\n  The <code class=\"code\">data</code> argument should follow the same layout as\n  described for the <code class=\"code\">notify</code> event.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-onmeta\"></a><h2>client.onmeta</h2>\n<pre class=\"programlisting\">\nclient.onmeta = function(ev, data) { ... }\n</pre>\n<p>An event triggered when the meta data about\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-watch\" title=\"client.watch()\">watched</a> interfaces is loaded.</p>\n<p>The <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy\" title=\"client.proxy()\"><code class=\"code\">client.proxy()</code></a> and\n        <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxies\" title=\"client.proxies()\"><code class=\"code\">client.proxies()</code></a> functions and\n        the objects they return are high level wrappers around the <code class=\"code\">data</code> provided\n        by this event.</p>\n<p>The <code class=\"code\">data</code> has the following form:</p>\n<pre class=\"programlisting\">\n  {\n      \"org.Interface\": {\n          \"methods\": {\n              \"Method1\": {\n                  \"in\": [ \"s\", \"v\" ],\n                  \"out\": [ \"i\" ]\n              },\n              \"Method2\": { }\n          },\n          \"signals\": {\n              \"Signal\": {\n                  \"in\": [ \"b\", \"s\" ]\n              }\n          },\n          \"properties\": {\n              \"Prop1\": {\n                  \"flags\": \"rw\",\n                  \"type\": \"s\"\n              },\n              \"Prop2\": {\n                  \"flags\": \"r\",\n                  \"type\": \"b\"\n              }\n          }\n      }\n  }\n</pre>\n<p>Multiple interfaces may be present, each of which may have methods and properties.\n      This is emitted before the first <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-proxy\" title=\"client.proxy()\"><code class=\"code\">client.onnotify</code></a>\n      event for the relevant interface.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-meta\"></a><h2>client.meta()</h2>\n<pre class=\"programlisting\">\nclient.meta(data)\n</pre>\n<p>Populate DBus introspection metadata about DBus interfaces. Usually this metadata\n      is automatically introspected from the DBus services called by the <code class=\"code\">client</code>,\n      but in certain cases it is useful to populate this info from javascript code. One such\n      case is when exporting a DBus service from javascript.</p>\n<p>The <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-onmeta\" title=\"client.onmeta\"><code class=\"code\">client.onmeta</code></a> event will\n      be emitted by this method call. It's documentation includes information about the form\n      of the <code class=\"code\">data</code>.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-publish\"></a><h2>client.publish()</h2>\n<pre class=\"programlisting\">\npublished = client.publish(path, interface, object, [options])\n</pre>\n<p>Publish a DBus <code class=\"code\">interface</code> at the specified object <code class=\"code\">path</code>.\n      Methods on the Javascript <code class=\"code\">object</code> will be invoked when DBus methods on the\n      specified <code class=\"code\">interface</code> are invoked by callers.</p>\n<p>The meta data for the DBus interface must have been populated using the\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-meta\" title=\"client.meta()\"><code class=\"code\">client.meta()</code></a> function. The\n      returned <code class=\"code\">published</code> object is a promise object. It will resolve when the\n      DBus interface has been published on the bus. It is not an error to publish the same\n      interface and path repeatedly: Previously published objects at the interface and\n      path are replaced by those published later.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-published\"></a><h2>published.remove()</h2>\n<pre class=\"programlisting\">\npublished.remove()\n</pre>\n<p>Un-publishes a DBus interface at an object path. This method can be invoked\n      on the <code class=\"code\">published</code> result returned from the\n      <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-publish\" title=\"client.publish()\"><code class=\"code\">client.publish()</code></a> function.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-variant\"></a><h2>cockpit.variant()</h2>\n<pre class=\"programlisting\">\nvariant = cockpit.variant(type, value)\n</pre>\n<p>A DBus variant is represented as a plain javascript object with a\n      <code class=\"code\">\"t\"</code> property represesting the full DBus type of the variant,\n      and a <code class=\"code\">\"v\"</code> property containing the variant value.</p>\n<p>This is a helper function for creating such a variant object.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-dbus-byte-array\"></a><h2>cockpit.byte_array()</h2>\n<pre class=\"programlisting\">\nbyte_array = cockpit.byte_array(value)\n</pre>\n<p>A DBus byte array is represented as base64 data encoded in a string. This\n      is a helper function for creating such a byte array.</p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-desktop.1.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit-desktop</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"cockpit-manual.html\" title=\"Manual pages\">\n<link rel=\"prev\" href=\"cockpit-ws.8.html\" title=\"cockpit-ws\">\n<link rel=\"next\" href=\"remotectl.8.html\" title=\"remotectl\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-ws.8.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"cockpit-manual.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"remotectl.8.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-desktop.1\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2><span class=\"refentrytitle\">cockpit-desktop</span></h2>\n<p>cockpit-desktop — Cockpit Desktop integration</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsynopsisdiv\">\n<h2>Synopsis</h2>\n<div class=\"cmdsynopsis\"><p><code class=\"command\">cockpit-desktop</code>  {URLPATH}</p></div>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-desktop-description\"></a><h2>DESCRIPTION</h2>\n<p>\n      The <span class=\"command\"><strong>cockpit-desktop</strong></span> program provides secure access to\n      Cockpit pages in an already running desktop session. It starts a web server\n      (<span class=\"command\"><strong>cockpit-ws</strong></span>) and a web browser in an isolated network\n      namespace, and a\n      <span class=\"citerefentry\"><span class=\"refentrytitle\">cockpit-bridge</span>(8)</span>\n      in the running user session.\n    </p>\n<p>\n      This avoids having to log into Cockpit, and having to enable\n      <code class=\"filename\">cockpit.socket</code> system-wide. The network isolation\n      ensures that no other user, and not even other processes in the user's\n      session, can access this local web server.\n    </p>\n<p>\n      <code class=\"literal\">URLPATH</code> is the Cockpit page to open, i. e. the path\n      component of Cockpit URLs. It is highly recommended to only open a\n      <a class=\"ulink\" href=\"https://cockpit-project.org/guide/latest/embedding.html\" target=\"_top\">particular page frame</a>,\n      not the entire Cockpit navigation and menu. For example, the path\n      <code class=\"literal\">/cockpit/@localhost/storage/index.html</code> will open the Storage\n      page.  It is also possible to give abbreviated forms of urls, such as \"<code class=\"literal\">storage</code>\"\n      or \"<code class=\"literal\">network/firewall</code>\".\n    </p>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-desktop-environment\"></a><h2>ENVIRONMENT</h2>\n<p>\n      The <code class=\"literal\">BROWSER </code> environment variable specifies\n      the browser command (and possibly options) that will be used to open the\n      requested Cockpit page. If not set, <span class=\"command\"><strong>cockpit-desktop</strong></span> attempts to use\n      an internal minimalistic WebKit browser, and failing that, will attempt to detect some\n      reasonable alternatives.\n    </p>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-desktop-bugs\"></a><h2>BUGS</h2>\n<p>\n      Please send bug reports to either the distribution bug tracker or the\n      <a class=\"ulink\" href=\"https://github.com/cockpit-project/cockpit/issues/new\" target=\"_top\">upstream bug tracker</a>.\n    </p>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-desktop-author\"></a><h2>AUTHOR</h2>\n<p>Cockpit has been written by many\n      <a class=\"ulink\" href=\"https://github.com/cockpit-project/cockpit/\" target=\"_top\">contributors</a>.</p>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-desktop-also\"></a><h2>SEE ALSO</h2>\n<p>\n      <span class=\"citerefentry\"><span class=\"refentrytitle\">cockpit-ws</span>(8)</span>,\n      <span class=\"citerefentry\"><span class=\"refentrytitle\">cockpit-bridge</span>(1)</span>\n    </p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-error.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.js: Errors</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"cockpit-locale.html\" title=\"cockpit.js: Localization\">\n<link rel=\"next\" href=\"cockpit-login.html\" title=\"cockpit.js: User Session\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-locale.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-login.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-error\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2>cockpit.js: Errors</h2>\n<p>cockpit.js: Errors — Problem codes and messages</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsection\">\n<a name=\"cockpit-problems\"></a><h2>Problem Codes</h2>\n<p>Cockpit represents problems with standardized problem string codes.</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"access-denied\"</code></span></p></td>\n<td><p>The user is not permitted to perform the action in question.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"authentication-failed\"</code></span></p></td>\n<td><p>User authentication failed.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"internal-error\"</code></span></p></td>\n<td><p>An unexpected internal error without further info. This should\n          not happen during the normal course of operations.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"no-cockpit\"</code></span></p></td>\n<td><p>The system does not have a compatible version of Cockpit installed\n          or installed properly.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"no-session\"</code></span></p></td>\n<td><p>Cockpit is not logged in.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"not-found\"</code></span></p></td>\n<td><p>Something specifically requested was not found, such as a file,\n          executable etc.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"terminated\"</code></span></p></td>\n<td><p>Something was terminated forcibly, such as a connection, process\n          session, etc.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"timeout\"</code></span></p></td>\n<td><p>Something timed out.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"unknown-hostkey\"</code></span></p></td>\n<td><p>The remote host had an unexpected or unknown key.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"no-forwarding\"</code></span></p></td>\n<td><p>Could not forward authentication credentials to the remote host.</p></td>\n</tr>\n</tbody>\n</table></div>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-messages\"></a><h2>cockpit.message()</h2>\n<pre class=\"programlisting\">\nmessage = cockpit.message(problem)\nmessage = cockpit.message(exception)\n</pre>\n<p>Return a message for the <code class=\"code\">exception</code> or <code class=\"code\">problem</code> code\n      passed as an argument. If the argument is an object with a <code class=\"code\">\"message\"</code> property,\n      as is the case with most exceptions, that will be returned directly. If the argument is\n      an object with a <code class=\"code\">\"problem\"</code> property, then it will be used as the problem code.\n      An appropriate message will be returned for problem codes.</p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-file.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.js: File Access</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"cockpit-dbus.html\" title=\"cockpit.js: DBus Client\">\n<link rel=\"next\" href=\"cockpit-http.html\" title=\"cockpit.js: HTTP Client\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-dbus.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-http.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-file\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2>cockpit.js: File Access</h2>\n<p>cockpit.js: File Access — Reading, writing, and watching files.</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsynopsisdiv\">\n<h2>Synopsis</h2>\n<p>The <code class=\"code\">cockpit.file</code> API lets you read, write, and watch regular files in their entirety.\n    It cannot efficiently do random access in a big file or read non-regular files such as\n    <code class=\"code\">/dev/random</code>.\n    </p>\n<pre class=\"programlisting\">\nfile = cockpit.file(path,\n                    { syntax: syntax_object,\n                      binary: boolean,\n                      max_read_size: int,\n                      superuser: string,\n                      host: string\n                    })\n\npromise = file.read()\npromise\n    .done(function (content, tag) { ... })\n    .fail(function (error) { ... })\n\npromise = file.replace(content, [ expected_tag ])\npromise\n    .done(function (new_tag) { ... })\n    .fail(function (error) { ... })\n\npromise = file.modify(callback, [ initial_content, initial_tag ]\npromise\n    .done(function (new_content, new_tag) { ... })\n    .fail(function (error) { ... })\n\nfile.watch(function (content, tag, [error]) { })\n\nfile.close()\n</pre>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-file-simple\"></a><h2>Simple reading and writing</h2>\n<p>You can read a file with code like this:</p>\n<pre class=\"programlisting\">\ncockpit.file(\"/path/to/file\").read()\n    .done(function (content, tag) {\n        ...\n    })\n    .fail(function (error) {\n        ...\n    });\n</pre>\n<p>The <code class=\"code\">read()</code> method returns a\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>.</p>\n<p>When successful, the promise will be resolved with the content of the\n      file. Unless you specify options to change this (see below), the file\n      is assumed to be text in the UTF-8 encoding, and <code class=\"code\">content</code>\n      will be a string.</p>\n<p>The tag that is passed to the <code class=\"code\">done()</code> callback is a short\n      string that is associated with the file and changes whenever the\n      content of the file changes.  It is meant to be used with <code class=\"code\">replace()</code>.</p>\n<p>It is not an error when the file does not exist. In this case, the\n      <code class=\"code\">done()</code> callback will be called with a <code class=\"code\">null</code>\n      value for <code class=\"code\">content</code> and <code class=\"code\">tag</code> is <code class=\"code\">\"-\"</code>.</p>\n<p>The <code class=\"code\">superuser</code> and <code class=\"code\">host</code> options can be used the same way\n      as described in the <a class=\"link\" href=\"cockpit-channels.html#cockpit-channels-channel\" title=\"cockpit.channel()\">cockpit.channel()</a>\n      to provide a different access level to the file.</p>\n<p>You can use the <code class=\"code\">max_read_size</code> option to limit\n      the amount of data that is read.  If the file is larger than the\n      given limit, no data is read and the channel is closed with\n      problem code <code class=\"code\">too-large</code>.  The default limit is 16 MiB.</p>\n<p>To write to a file, use code like this:\n</p>\n<pre class=\"programlisting\">\ncockpit.file(\"/path/to/file\").replace(\"my new content\\n\")\n    .done(function (tag) {\n        ...\n    })\n    .fail(function (error) {\n        ...\n    });\n</pre>\n<p>\n    </p>\n<p>The <code class=\"code\">replace()</code> method returns a\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>.</p>\n<p>When the promise is resolved, the file has been atomically replaced\n      (via the <code class=\"code\">rename()</code> syscall) with the new content. As with\n      <code class=\"code\">read()</code>, by default the new content is a string and will\n      be written to the file as UTF-8. The returned tag corresponds to the\n      new content of the file.</p>\n<p>When the promise is rejected because of an error, the file or its meta\n      data has not been changed in any way.</p>\n<p>As a special case, passing the value <code class=\"code\">null</code> to\n      <code class=\"code\">replace()</code> will remove the file.</p>\n<p>The <code class=\"code\">replace()</code> method can also check for conflicting\n      changes to a file.  You can pass a tag (as returned by\n      <code class=\"code\">read()</code> or <code class=\"code\">replace()</code>) to\n      <code class=\"code\">replace()</code>, and the file will only be replaced if it still\n      has the given tag.  If the tag of the file has changed,\n      <code class=\"code\">replace()</code> will fail with an error object that has\n      <code class=\"code\">error.problem == \"change-conflict\"</code>. See\n      <code class=\"code\">modify()</code> below for a convenient way to achieve\n      transactional updates to a file.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-file-format\"></a><h2>File format</h2>\n<p>By default, a file is assumed to be text encoded in UTF-8, and the\n      <code class=\"code\">read()</code> and <code class=\"code\">replace()</code> functions use strings to\n      represent the content.</p>\n<p>By specifying the <code class=\"code\">syntax.parser()</code> and\n      <code class=\"code\">syntax.stringify()</code> options, you can cause\n      <code class=\"code\">read()</code> to parse the content before passing it back to\n      you, and <code class=\"code\">replace()</code> to unparse it before writing.</p>\n<p>The main idea is to be able to write <code class=\"code\">{ syntax: JSON }</code>, of\n      course, but you can easily pass in individual functions or make your\n      own parser/unparser object:\n</p>\n<pre class=\"programlisting\">\ncockpit.file(\"/path/to/file.json\", { syntax: JSON })\n\nvar syntax_object = {\n    parse:     my_parser,\n    stringify: my_unparser\n};\n\ncockpit.file(\"/path/to/file\", { syntax: syntax_object })\n</pre>\n<p>\n      Any exceptions thrown by the <code class=\"code\">parse()</code> and\n      <code class=\"code\">stringify()</code> functions are caught and reported as read or\n      write errors.</p>\n<p>The <code class=\"code\">null</code> value that is used to represent the content of a\n      non-existing file (see \"Simple reading and writing\", above) is not\n      passed through the <code class=\"code\">parse()</code> and <code class=\"code\">stringify()</code>\n      functions.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-file-binary\"></a><h2>Binary files</h2>\n<p>By default the content of the file is assumed to be text encoded as\n      UTF-8 and it can not contain zero bytes.  The content is represented\n      as a JavaScript string with <code class=\"code\">read()</code>,\n      <code class=\"code\">replace()</code>, etc. By setting the <code class=\"code\">binary</code> option\n      to true when creating the proxy, no assumptions are placed on the\n      content, and it is represented as a <code class=\"code\">Uint8Array</code> in\n      JavaScript.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-file-atomic\"></a><h2>Atomic modifications</h2>\n<p>Use <code class=\"code\">modify()</code> to modify the content of the file safely.  A\n      call to <code class=\"code\">modify()</code> will read the content of the file, call\n      <code class=\"code\">callback</code> on the content, and then replace the content of\n      the file with the return value of the callback.</p>\n<p>The <code class=\"code\">modify()</code> method uses the <code class=\"code\">read()</code> and\n      <code class=\"code\">replace()</code> methods internally in the obvious way. Thus,\n      the <code class=\"code\">syntax.parse()</code> and <code class=\"code\">syntax.stringify()</code>\n      options work as expected, <code class=\"code\">null</code> represents a non-existing\n      file, and the watch callbacks are fired.</p>\n<p>It will do this one or more times, until no other conflicting changes\n      have been made to the file between reading and replacing it.</p>\n<p>The callback is called like this\n</p>\n<pre class=\"programlisting\">\nnew_content = callback (old_content)\n</pre>\n<p>\n      The callback is allowed to mutate <code class=\"code\">old_content</code>, but note\n      that this will also mutate the objects that are passed to the watch\n      callbacks. Returning <code class=\"code\">undefined</code> from the proxy is the\n      same as returning <code class=\"code\">old_content</code>.</p>\n<p>The <code class=\"code\">modify()</code> method returns a\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>.</p>\n<p>The promise will be resolved with the new content and its tag, like so\n</p>\n<pre class=\"programlisting\">\nfunction shout(old_content) {\n    return old_content.toUpperCase();\n}\n\ncockpit.file(\"/path/to/file\").modify(shout)\n    .done(function (content, tag) {\n        ...\n    })\n    .fail(function (error) {\n        ...\n    });\n</pre>\n<p>\n      If you have cached the last content and tag results of the\n      <code class=\"code\">read()</code> or <code class=\"code\">modify()</code> method, or the last\n      values passed to a watch callback, you can pass them to\n      <code class=\"code\">modify()</code> as the second and third argument.  In this case,\n      <code class=\"code\">modify()</code> will skip the initial read and start with the\n      given values.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-file-notify\"></a><h2>Change notifications</h2>\n<p>Calling <code class=\"code\">watch()</code> will start monitoring the file for\n      external changes.\n</p>\n<pre class=\"programlisting\">\nhandle = file.watch(callback);\n</pre>\n<p>\n      Whenever a change occurs, the <code class=\"code\">callback()</code> is called with\n      the new content and tag of the file.  This might happen because of\n      external changes, but also as part of calls to <code class=\"code\">read()</code>,\n      <code class=\"code\">replace()</code>, and <code class=\"code\">modify()</code>.</p>\n<p>When a read error occurs, the <code class=\"code\">callback()</code> is called with\n      an error as a third argument. Write errors are not reported via the watch callback.</p>\n<p>Calling <code class=\"code\">watch()</code> will also automatically call\n      <code class=\"code\">read()</code> to get the initial content of the file.</p>\n<p>Thus, you normally don't need to call <code class=\"code\">read()</code> at all when\n      using <code class=\"code\">watch()</code>.</p>\n<p>To free the resources used for monitoring, call <code class=\"code\">handle.remove()</code>.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-file-path\"></a><h2>file.path</h2>\n<p>A string containing the path that was passed to the <code class=\"code\">cockpit.file()</code>\n      method.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-file-close\"></a><h2>Closing</h2>\n<p>Call the <code class=\"code\">close()</code> method on a file proxy to cancel all\n      ongoing operations, such as reading, writing, and monitoring. The\n      proxy should not be used after closing it.</p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-http.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.js: HTTP Client</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"cockpit-file.html\" title=\"cockpit.js: File Access\">\n<link rel=\"next\" href=\"cockpit-spawn.html\" title=\"cockpit.js: Spawning Processes\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-file.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-spawn.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-http\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2>cockpit.js: HTTP Client</h2>\n<p>cockpit.js: HTTP Client — HTTP and REST API communication</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsynopsisdiv\">\n<h2>Synopsis</h2>\n<p>Cockpit allows access to local HTTP and REST services via this API.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-http-constructor\"></a><h2>cockpit.http()</h2>\n<pre class=\"programlisting\">\nhttp = cockpit.http(endpoint, [options])\nhttp = cockpit.http(options)\n</pre>\n<p>Create a new HTTP client. The <code class=\"code\">endpoint</code> can be a file path starting with\n      <code class=\"code\">/</code> to connect to a unix socket, or it can be a port number to connect to.\n      The optional <code class=\"code\">options</code> argument is a javascript plain object, and may\n      include:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"address\"</code></span></p></td>\n<td><p>Connect to an address other than localhost. Must be a valid host name or IP address.\n          To use this option you also must provide a port number.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"port\"</code></span></p></td>\n<td><p>Port number to use with \"address\" option, when not given in <code class=\"code\">endpoint</code>.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"tls\"</code></span></p></td>\n<td><p>Object properties for an https connection. See\n        <code class=\"code\"><a class=\"ulink\" href=\"https://github.com/cockpit-project/cockpit/blob/master/doc/protocol.md#payload-http-stream2\" target=\"_top\">http-stream2 TLS options</a></code>.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"connection\"</code></span></p></td>\n<td><p>A connection identifier. Subsequent channel requests with the same\n          identifier will try to use the same connection if it is still open.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"headers\"</code></span></p></td>\n<td><p>Additional HTTP headers to include with the HTTP request. This is a plain\n          javascript object with each key as a header name, and each value as the header\n          value.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"superuser\"</code></span></p></td>\n<td>\n<p>Set to <code class=\"code\">\"require\"</code> to open this channel as root. If the\n          currently logged in user is not permitted to become root (eg: via <code class=\"code\">pkexec</code>)\n          then the <code class=\"code\">channel</code> will immediately be\n          <a class=\"link\" href=\"cockpit-channels.html#cockpit-channels-close-ev\" title=\"channel.onclose\">closed</a> with a <code class=\"code\">\"access-denied\"</code>\n          problem code.</p>\n<p>Set to <code class=\"code\">\"try\"</code> to try to make the request as root, but if that fails,\n          fall back to perform an unprivileged request.</p>\n</td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"tls\"</code></span></p></td>\n<td>\n<p>If set to a plain javascript object, then the connection will be an HTTPS\n            connection and include TLS encryption. The fields of the <code class=\"code\">tls</code> object\n            declare various TLS configuration and data. All fields are optional:</p>\n<div class=\"itemizedlist\"><ul class=\"itemizedlist\" style=\"list-style-type: disc; \">\n<li class=\"listitem\"><p><code class=\"code\">\"authority\"</code>: Certificate authority(s) to expect as signers\n              of the server's TLS certificate, represented as a plain javascript object.\n              It should have either a <code class=\"code\">\"file\"</code> field containing a\n              readable PEM file on the system containing authorities, or a <code class=\"code\">\"data\"</code> with\n              PEM encoded certificate data.</p></li>\n<li class=\"listitem\"><p><code class=\"code\">\"certificate\"</code>: A client certificate to use, represented as\n              a plain javascript object. It should have either a <code class=\"code\">\"file\"</code> field containing a\n              readable PEM file on the system to use as a certificate, or a <code class=\"code\">\"data\"</code> with\n              PEM encoded certificate data.</p></li>\n<li class=\"listitem\"><p><code class=\"code\">\"key\"</code>: A client key to use, represented as\n              a plain javascript object. It should have either a <code class=\"code\">\"file\"</code> field containing a\n              readable PEM file on the system to use as a key, or a <code class=\"code\">\"data\"</code> with\n              PEM encoded key data.</p></li>\n<li class=\"listitem\"><p><code class=\"code\">\"validate\"</code>: A boolean that describes whether to validate\n              the server's TLS certificate or not. By default local connections are not validated,\n              and remote connections are validated.</p></li>\n</ul></div>\n</td>\n</tr>\n</tbody>\n</table></div>\n<p>Here is a somewhat complex example of using most of the above <code class=\"code\">options</code> when\n      when calling <code class=\"code\">cockpit.http()</code>:</p>\n<pre class=\"programlisting\">\nhttp = cockpit.http({\n    \"address\": \"localhost\",\n    \"headers\": {\n        \"Authorization\": \"Basic dXNlcjpwYXNzd29yZA==\"\n    },\n    \"port\": 443,\n    \"tls\": {\n        \"validate\": true,\n        \"authority\": {\n            \"file\": \"/etc/pki/tls/certs/ca-bundle.crt\",\n        },\n        \"certificate\": {\n            \"data\": \"-----BEGIN CERTIFICATE-----\\nMIIDsDCCA...\"\n        },\n        \"key\": {\n            \"data\": \"-----BEGIN RSA PRIVATE KEY-----\\nMIIEogIBA...\"\n        }\n    }\n});\n</pre>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-http-get\"></a><h2>http.get()</h2>\n<pre class=\"programlisting\">\nrequest = http.get(path, [params, [headers]])\n</pre>\n<p>Perform an HTTP GET request for the given <code class=\"code\">path</code>. If the <code class=\"code\">params</code>\n      is specified it should be a plain javascript object, which will be turned into a query string.</p>\n<p>Optionally a plain javascript object containing headers can be included in the\n      <code class=\"code\">headers</code> argument.</p>\n<p>The return value is a\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>\n      that will complete if the request happens successfully, or fail if there's a problem.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-http-post\"></a><h2>http.post()</h2>\n<pre class=\"programlisting\">\nrequest = http.post(path, body, [headers])\n</pre>\n<p>Perform an HTTP POST request for the given <code class=\"code\">path</code>. The <code class=\"code\">body</code>\n      can be a string, or a javascript plain object, which will be encoded as JSON data. If\n      <code class=\"code\">body</code> is <code class=\"code\">undefined</code> or <code class=\"code\">null</code> then an empty HTTP body\n      will be sent.</p>\n<p>Optionally a plain javascript object containing headers can be included in the\n      <code class=\"code\">headers</code> argument.</p>\n<p>The return value is a\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>\n      that will complete if the request happens successfully, or fail if there's a problem.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-http-request\"></a><h2>http.request()</h2>\n<pre class=\"programlisting\">\nrequest = http.request(options)\n</pre>\n<p>Perform an HTTP request. The <code class=\"code\">options</code> can contain the following:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"body\"</code></span></p></td>\n<td><p>The HTTP request body. If you do not specify a body, then you must\n          call <a class=\"link\" href=\"cockpit-http.html#cockpit-http-input\" title=\"request.input()\">request.input()</a> to complete the body\n          and allow the request to start.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"headers\"</code></span></p></td>\n<td><p>A javascript plain object containing HTTP headers.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"method\"</code></span></p></td>\n<td><p>The HTTP method. Defaults to <code class=\"code\">\"GET\"</code>.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"params\"</code></span></p></td>\n<td><p>A javascript plain object containing query string parameters.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"path\"</code></span></p></td>\n<td><p>The HTTP path. Defaults to <code class=\"code\">/</code>.</p></td>\n</tr>\n</tbody>\n</table></div>\n<p>The return value is a\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>\n      that will complete if the request happens successfully, or fail if there's a problem.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-http-done\"></a><h2>request.done()</h2>\n<pre class=\"programlisting\">\nrequest.done(function(data) { ... })\n</pre>\n<p>This is a standard\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>\n      method. It sets up a handler to be called when the request finishes successfully.</p>\n<p>The <code class=\"code\">data</code> argument contains the body result of the request.\n      If it a string, unless the process was opened in binary mode, in which case the\n      <code class=\"code\">data</code> is an array of bytes. If a\n      <code class=\"code\"><a class=\"link\" href=\"cockpit-http.html#cockpit-http-stream\" title=\"request.stream()\">request.stream()</a></code>\n      handler is set up, then any standard output data consumed by the handler will not\n      be included in the <code class=\"code\">data</code> argument.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-http-fail\"></a><h2>request.fail()</h2>\n<pre class=\"programlisting\">\nrequest.fail(function(exception[, data]) { ... })\n</pre>\n<p>This is a standard\n      <a class=\"ulink\" href=\"https://api.jquery.com/category/deferred-object/\" target=\"_top\">jQuery promise</a> method.\n      It sets up a handler to be called when the request fails, or returns an error code.</p>\n<p>The <code class=\"code\">exception</code> object passed to the handler can have the\n      following fields:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">problem</code></span></p></td>\n<td><p>A <a class=\"link\" href=\"cockpit-error.html#cockpit-problems\" title=\"Problem Codes\">problem code</a> string when\n          a problem occurred starting or communicating with the server. This is <code class=\"code\">null</code>\n          if the process exited or was terminated.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">status</code></span></p></td>\n<td><p>The numeric status of the response. This is <code class=\"code\">null</code> if\n          no response was received.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">reason</code></span></p></td>\n<td><p>A string reason returned in the response. This is <code class=\"code\">null</code> if\n          no response was received.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">message</code></span></p></td>\n<td><p>A string message returned in the response. This is <code class=\"code\">null</code> if\n          no response was received.</p></td>\n</tr>\n</tbody>\n</table></div>\n<p>If the request returned a response body, it will be available in\n      the <code class=\"code\">data</code> argument. Otherwise this argument will be <code class=\"code\">undefined</code>.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-http-always\"></a><h2>request.always()</h2>\n<pre class=\"programlisting\">\nrequest.always(function() { ... })\n</pre>\n<p>This is a standard\n      <a class=\"ulink\" href=\"https://api.jquery.com/category/deferred-object/\" target=\"_top\">jQuery promise</a> method.\n      It sets up a handler to be called when the process completes, whether it exits successfully,\n      fails, terminates, or exits with a failure.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-http-response\"></a><h2>request.response()</h2>\n<pre class=\"programlisting\">\nrequest.response(function(status, headers) { ... })\n</pre>\n<p>This sets up a handler to be called when the HTTP request gets the initial response\n      from the server. The <code class=\"code\">status</code> argument is the HTTP status integer, and the\n      <code class=\"code\">headers</code> is a plain javascript object containing the headers of the\n      response.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-http-stream\"></a><h2>request.stream()</h2>\n<pre class=\"programlisting\">\nrequest.stream(function(data) { ... })\n</pre>\n<p>This sets up a handler to be called when the request returns output data. The\n      handler will be called multiple times.</p>\n<p>Only one handler may be registered at a time. Registering an additional handler\n      replaces the previous one. The handler receives either string <code class=\"code\">data</code> or\n      an array of binary bytes as its argument. A stream handler may return a number, which\n      indicates the number of characters or bytes consumed from <code class=\"code\">data</code>. Any data\n      not consumed will be included again the next time the handler is called.</p>\n<p>If a <code class=\"code\">request.stream()</code> handler is set up, then the\n      <code class=\"code\"><a class=\"link\" href=\"cockpit-http.html#cockpit-http-done\" title=\"request.done()\">request.done()</a></code> handlers will\n      only get any remaining data not consumed by the stream handler.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-http-input\"></a><h2>request.input()</h2>\n<pre class=\"programlisting\">\nrequest.input(data, [stream])\n</pre>\n<p>This method writes <code class=\"code\">data</code> to the HTTP request body. It is only valid\n      if no <code class=\"code\">\"body\"</code> has been specified in\n      <a class=\"link\" href=\"cockpit-http.html#cockpit-http-request\" title=\"http.request()\">http.request()</a> options. If <code class=\"code\">stream</code>\n      is <code class=\"code\">true</code> then this function can be called again to provide further data.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-http-close\"></a><h2>request.close()</h2>\n<pre class=\"programlisting\">\nrequest.close([problem])\n</pre>\n<p>Cancel the request. If <code class=\"code\">problem</code> is specified it should be a\n      standard <a class=\"link\" href=\"cockpit-error.html#cockpit-problems\" title=\"Problem Codes\">problem code</a> string.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-http-close-all\"></a><h2>http.close()</h2>\n<pre class=\"programlisting\">\nhttp.close([problem])\n    </pre>\n<p>Cancel all outstanding requests with the given problem code.  This is useful when\n    you know that the server is going down soon.\n    </p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-locale.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.js: Localization</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"cockpit-location.html\" title=\"cockpit.js: Page Location and Jumping\">\n<link rel=\"next\" href=\"cockpit-error.html\" title=\"cockpit.js: Errors\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-location.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-error.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-locale\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2>cockpit.js: Localization</h2>\n<p>cockpit.js: Localization — Localization and translations</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsynopsisdiv\">\n<h2>Synopsis</h2>\n<p>Cockpit provides a\n    <a class=\"ulink\" href=\"https://www.gnu.org/software/gettext/\" target=\"_top\"><code class=\"code\">gettext()</code></a> like\n    API for easy translation of strings.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-locale-language\"></a><h2>cockpit.language</h2>\n<p>The current locale language code. This is set based on the\n      <a class=\"link\" href=\"cockpit-locale.html#cockpit-locale-locale\" title=\"cockpit.locale()\"><code class=\"code\">cockpit.locale()</code></a> data loaded.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-locale-locale\"></a><h2>cockpit.locale()</h2>\n<pre class=\"programlisting\">\ncockpit.locale(po)\n</pre>\n<p>Load locale information for a given <code class=\"code\">po</code> data. The data should\n      be JSON data in the <a class=\"ulink\" href=\"https://www.npmjs.org/package/po2json\" target=\"_top\">po2json</a>\n      format. The data will be loaded globally. If <code class=\"code\">po</code> data has already been\n      loaded, then this will extend that loaded data with additional strings. Any identical\n      translations strings will be replaced with the new strings. A <code class=\"code\">null</code> argument\n      clears all the locale information previously loaded.</p>\n<p>Various methods such as\n      <a class=\"link\" href=\"cockpit-locale.html#cockpit-locale-gettext\" title=\"cockpit.gettext()\"><code class=\"code\">cockpit.gettext()</code></a> make use\n      of the loaded data.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-locale-gettext\"></a><h2>cockpit.gettext()</h2>\n<pre class=\"programlisting\">\ntranslated = cockpit.gettext([context], string)\nvar _ = cockpit.gettext\nvar C_ = cockpit.gettext\ntranslated = _(\"string\")\ntranslated = C_(\"context\", \"string\")\n</pre>\n<p>Lookup <code class=\"code\">string</code> for translation in the loaded locale data. The translated string will\n      be returned, or <code class=\"code\">string</code> will be returned if no such translated string is\n      present. The <code class=\"code\">context</code> argument is an optional string used to qualify the\n      string.</p>\n<p>This function can be assigned to a variable called <code class=\"code\">_</code> (underscore) which\n      will make your code work with the typical <code class=\"code\">_(\"string\")</code> syntax.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-locale-noop\"></a><h2>cockpit.noop()</h2>\n<pre class=\"programlisting\">\nvar N_ = cockpit.noop\nvar NC_ = cockpit.noop\n</pre>\n<p>A noop function suitable for assigning to <code class=\"code\">N_</code> or <code class=\"code\">NC_</code> so that\n      gettext scanners will be able to find translatable strings. More specifically this function\n      returns its last argument.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-locale-ngettext\"></a><h2>cockpit.ngettext()</h2>\n<pre class=\"programlisting\">\ntranslated = cockpit.ngettext([context], string1, stringN, number)\n</pre>\n<p>Lookup a string appropriate for a pluralization form of the <code class=\"code\">number</code>.\n      Various languages have complex pluralization forms that go far between the singular\n      and plural forms speakers of English are familiar with. If no such translated\n      string is found then either one of <code class=\"code\">string1</code> or <code class=\"code\">stringN</code> is\n      returned according to simple pluralization rules.</p>\n<p>The <code class=\"code\">context</code> argument is an optional string used to qualify the string.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-locale-translate\"></a><h2>cockpit.translate()</h2>\n<pre class=\"programlisting\">\ncockpit.translate()\ncockpit.translate(element, ...)\ncockpit.translate(selection)\n</pre>\n<p>The document will be scanned for <code class=\"code\">translate</code> tags and they will be translated according\n      to the strings in loaded locale data. One or more <code class=\"code\">element</code> arguments may be specified.\n      These are DOM elements for specific parts of the document to be translated. If no <code class=\"code\">element</code>\n      is specified then the entire document is translated.</p>\n<p>If an array or array-like object is passed as a <code class=\"code\">selection</code> then all DOM elements\n      in the array will be treated as parts of the document to be translated.</p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-location.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.js: Page Location and Jumping</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"cockpit-channels.html\" title=\"cockpit.js: Raw Channels\">\n<link rel=\"next\" href=\"cockpit-locale.html\" title=\"cockpit.js: Localization\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-channels.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-locale.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-location\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2>cockpit.js: Page Location and Jumping</h2>\n<p>cockpit.js: Page Location and Jumping — Page location and navigation between components</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsection\">\n<a name=\"cockpit-location-general\"></a><h2>Page location</h2>\n<pre class=\"programlisting\">\nlocation = cockpit.location\ncockpit.location = \"/path\"\n</pre>\n<p>Cockpit components often have different views, without changing the HTML file that is\n      being viewed. These are known as pages. <code class=\"code\">cockpit.location</code> is an object that can\n      be used to read the current page and to navigate to a different page location. It works by\n      updating <code class=\"code\">window.location.hash</code>.</p>\n<p>The <code class=\"code\">cockpit.location</code> looks like a HTTP path with a possible query\n      string:</p>\n<pre class=\"programlisting\">\n/path/sub/page?option=value,option2\n</pre>\n<p>The <a class=\"link\" href=\"cockpit-location.html#cockpit-location-path\" title=\"location.path\"><code class=\"code\">location.path</code></a> and\n      <a class=\"link\" href=\"cockpit-location.html#cockpit-location-options\" title=\"location.options\"><code class=\"code\">location.options</code></a> contain a parsed\n      form of the location. While the location cannot be modified in place, a new one can be\n      created by assigning a string to <code class=\"code\">cockpit.location</code> or by calling the\n      <a class=\"link\" href=\"cockpit-location.html#cockpit-location-go\" title=\"location.go()\"><code class=\"code\">location.go()</code></a> function.</p>\n<p><code class=\"code\">cockpit.location</code> is designed similarly to <code class=\"code\">window.location</code>\n      in that the location object is preplaced whenever the current page location changes. To be\n      aware of when the page location changes listen for the\n      <a class=\"link\" href=\"cockpit-location.html#cockpit-location-changed\" title=\"cockpit.onlocationchanged\"><code class=\"code\">cockpit.onlocationchanged</code></a>\n      event.</p>\n<p>Using the location object as a string will result in the\n      <a class=\"link\" href=\"cockpit-location.html#cockpit-location-href\" title=\"location.href\"><code class=\"code\">location.href</code></a>.</p>\n<div class=\"refsection\">\n<a name=\"cockpit-location-href\"></a><h3>location.href</h3>\n<p>The string representation of this page location, including any options.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-location-path\"></a><h3>location.path</h3>\n<p>An array of path segments, parsed and decoded appropriately. An empty array denotes\n        the root path.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-location-options\"></a><h3>location.options</h3>\n<p>A javascript object containing the various options present in the location.</p>\n<p>If an option appears more than once, its value will be an array.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-location-go\"></a><h3>location.go()</h3>\n<pre class=\"programlisting\">\nlocation.go(path, [options])\n</pre>\n<p>Changes the current location to the given <code class=\"code\">path</code> and <code class=\"code\">options</code>.\n        If the <code class=\"code\">path</code> argument is a string, it will be parsed into a path. If it is\n        a relative path, then the result will be relative to the current <code class=\"code\">location.path</code>.\n        If the <code class=\"code\">path</code> argument is an array of path segments, it will be treated as a\n        full parsed absolute path.</p>\n<p>Any options found in a <code class=\"code\">path</code> will be added to those in the optional\n        <code class=\"code\">options</code> argument, and used in the result.</p>\n<p>The location change will only take effect if the location has not changed in the\n        meantime. This can be to good effect by saving a <code class=\"code\">cockpit.location</code> object\n        and doing a conditional navigation, by calling the saved <code class=\"code\">location.go()</code>\n        method later. This will only navigate if the user or other code has not navigated in\n        the meantime.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-location-replace\"></a><h3>location.replace()</h3>\n<pre class=\"programlisting\">\nlocation.replace(path, [options])\n</pre>\n<p>Similar to <a class=\"link\" href=\"cockpit-location.html#cockpit-location-go\" title=\"location.go()\"><code class=\"code\">location.go()</code></a>\n        except the location change will not result in a navigation change in the browser's\n        history.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-location-decode\"></a><h3>location.decode()</h3>\n<pre class=\"programlisting\">\npath = location.decode(href, [options])\n</pre>\n<p>Decode a cockpit href into its <code class=\"code\">path</code> array. If the <code class=\"code\">options</code>\n        argument is specified, then it will be populated with options found in the href.</p>\n<p>If href is a relative path it will be resolved relative to\n        <code class=\"code\">location.href</code>.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-location-encode\"></a><h3>location.encode()</h3>\n<pre class=\"programlisting\">\nhref = location.encode(path, [options])\n</pre>\n<p>Encode the given <code class=\"code\">path</code> and <code class=\"code\">options</code> into a cockpit href.\n        The <code class=\"code\">path</code> argument may be an array of path segments, or a string path. If\n        a relative path is passed, it will be resolved relative to <code class=\"code\">location.href</code>.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-location-changed\"></a><h3>cockpit.onlocationchanged</h3>\n<pre class=\"programlisting\">\ncockpit.addEventListener(\"locationchanged\", function() { ... })\n</pre>\n<p>An event emitted when over the <code class=\"code\">cockpit.location</code> changes. Typically a\n        component reacts to this event by updating its interface to reflect the new\n        <a class=\"link\" href=\"cockpit-location.html#cockpit-location-path\" title=\"location.path\"><code class=\"code\">cockpit.location.path</code></a> and\n        <a class=\"link\" href=\"cockpit-location.html#cockpit-location-options\" title=\"location.options\"><code class=\"code\">cockpit.location.options</code></a>.</p>\n<p>This event is not triggered immediately during a <code class=\"code\">location.go()</code> or\n        similar call. It will be triggered asynchronously at a later time.</p>\n</div>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-jump\"></a><h2>Jumping between components</h2>\n<pre class=\"programlisting\">\ncockpit.jump(\"/system/log\")\n</pre>\n<p>In Cockpit in there multiple components shown. In order to tell Cockpit to jump to and show\n      another component and a certain location within that component, use the\n      <code class=\"code\">cockpit.jump()</code> function. Stable component paths are documented. Don't assume\n      you can navigate into paths that are not stable API.</p>\n<div class=\"refsection\">\n<a name=\"cockpit-jump-jump\"></a><h3>cockpit.jump()</h3>\n<pre class=\"programlisting\">\ncockpit.jump(path, [ host ])\n</pre>\n<p>Ask Cockpit to jump to another component. The location of the current component will\n        not be affected. The <code class=\"code\">path</code> argument can be a string path, starting with <code class=\"code\">/</code>\n        or an array containing the parts of a path that will be joined to create a path. If <code class=\"code\">host</code>\n        is not specified, then the component on the same host as the caller will be displayed. If\n        host is null, then the host portion of the path will be removed, displaying the component on\n        the host that cockpit is connected directly to. This is mostly useful for displaying a\n        dashboard or other multi-machine components.</p>\n<p>If the calling component is not running within Cockpit, or the calling component is not\n        currently displayed, then the jump will not happen, and this function has no effect.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-jump-hidden\"></a><h3>cockpit.hidden</h3>\n<p>A boolean property that indicates if the current component page is visible or hidden.\n        When the code or user jumps to another component, the prior one remains loaded and initialized\n        but is hidden. Use this property together with the\n        <a class=\"link\" href=\"cockpit-location.html#cockpit-jump-visibilitychange\" title=\"cockpit.onvisibilitychange\"><code class=\"code\">cockpit.onvisibilitychange</code></a>\n        event to decide whether or not to perform expensive tasks to update the interface.</p>\n<p>This property is analogous to the <code class=\"code\">document.hidden</code> page visibility API, but\n        works with the document and frame implementation of Cockpit.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-jump-visibilitychange\"></a><h3>cockpit.onvisibilitychange</h3>\n<pre class=\"programlisting\">\ncockpit.onvisibilitychange = function() { ... }\n</pre>\n<p>This event is emitted when the\n        <a class=\"link\" href=\"cockpit-location.html#cockpit-jump-hidden\" title=\"cockpit.hidden\"><code class=\"code\">cockpit.hidden</code></a> property changes.\n        This event is similar to the <code class=\"code\">document.onvisibilitychange</code> API, but works with\n        the document and frame implementation of Cockpit.</p>\n</div>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-login.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.js: User Session</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"cockpit-error.html\" title=\"cockpit.js: Errors\">\n<link rel=\"next\" href=\"cockpit-util.html\" title=\"cockpit.js: Utilities\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-error.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-util.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-login\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2>cockpit.js: User Session</h2>\n<p>cockpit.js: User Session — User information and login session state</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsection\">\n<a name=\"cockpit-logout\"></a><h2>cockpit.logout()</h2>\n<pre class=\"programlisting\">\ncockpit.logout([reload])\n</pre>\n<p>Logout of Cockpit. Unless <code class=\"code\">reload</code> is <code class=\"code\">false</code> this will also\n      cause the page to be reloaded, so that the user can see the logged out state.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-user\"></a><h2>cockpit.user()</h2>\n<pre class=\"programlisting\">\nvar promise = cockpit.user();\npromise.done(function (user) { ... });\n</pre>\n<p>This object contains information about the user that's currently logged into cockpit.\n      The following fields are defined:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"id\"</code></span></p></td>\n<td><p>This is unix user id.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"name\"</code></span></p></td>\n<td><p>This is the unix user name like <code class=\"code\">\"root\"</code>.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"full_name\"</code></span></p></td>\n<td><p>This is a readable name for the user.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"groups\"</code></span></p></td>\n<td><p>This is an array of group names to which the user belongs.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"home\"</code></span></p></td>\n<td><p>This is user's home directory.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"shell\"</code></span></p></td>\n<td><p>This is unix user shell.</p></td>\n</tr>\n</tbody>\n</table></div>\n<p>Returns a promise that completes once the user information is available.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-info-changed\"></a><h2>cockpit.user.onchanged</h2>\n<pre class=\"programlisting\">\ncockpit.user.addEventListener(\"changed\", function() { ... })\n</pre>\n<p>This event is fired when the user info changes or first becomes available.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-permission\"></a><h2>Permission lookup</h2>\n<p>Cockpit provides a mechanism for checking if the current user satisfies a\n      given criteria. Currently capable of checking for root users, and group\n      membership. This is meant for updating UI elements based on what actions the\n      user can perform. It is <span class=\"emphasis\"><em>not an access control mechanism</em></span>.</p>\n<div class=\"refsection\">\n<a name=\"cockpit-permission-constructor\"></a><h3>cockpit.permission()</h3>\n<pre class=\"programlisting\">\npermission = cockpit.permission([options])\n</pre>\n<p>Create a new permission object to check if the current user has permission.\n        The \"root\" user is always given permission. The <code class=\"code\">options</code> argument\n        can contain a <code class=\"code\">\"group\"</code> field, and members of that group are also\n        given permission.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-permission-allowed\"></a><h3>permission.allowed</h3>\n<p>A boolean value which indicates if the permission is allowed or not. This will\n        be <code class=\"code\">null</code> if the permission is unknown, or there was an error checking\n        the permission or the permission data has not yet loaded. This property will update\n        asynchronously and if you wish to be notified of changes connect to the\n        <a class=\"link\" href=\"cockpit-login.html#cockpit-permission-changed\" title=\"permission.onchanged\">permission.onchanged</a> event.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-permission-changed\"></a><h3>permission.onchanged</h3>\n<pre class=\"programlisting\">\npermission.addEventListener(\"changed\", function() { ... })\n</pre>\n<p>This event is fired when the permission changes. In particular the\n        <a class=\"link\" href=\"cockpit-login.html#cockpit-permission-allowed\" title=\"permission.allowed\">permission.allowed</a> property.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-permission-close\"></a><h3>permission.close()</h3>\n<pre class=\"programlisting\">\npermission.close()\n</pre>\n<p>Closes the permission object and tears down any registered callbacks and dbus subscriptions.</p>\n</div>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-manifest.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.js: Manifests</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"cockpit-cache.html\" title=\"cockpit.js: Object Cache\">\n<link rel=\"next\" href=\"api-base1-patternfly.html\" title=\"patternfly.css\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-cache.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"api-base1-patternfly.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-manifest\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2>cockpit.js: Manifests</h2>\n<p>cockpit.js: Manifests — Manifest info</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsection\">\n<a name=\"cockpit-manifest-loading\"></a><h2>Loading Manifests</h2>\n<p>You can load manifest info by loading the <code class=\"code\">./manifest.json</code> file in\n      your package. In addition there is a shortcut, by loading the <code class=\"code\">../manifests.json</code>\n      you can load all the manifests at once.</p>\n<p>Lastly load the <code class=\"code\">../manifests.js</code> file to register the manifests at\n      the <code class=\"code\">cockpit.manifests</code> global variable.</p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-manual.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Manual pages</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"guide.html\" title=\"Part I. Deployment Guide\">\n<link rel=\"prev\" href=\"guide.html\" title=\"Part I. Deployment Guide\">\n<link rel=\"next\" href=\"cockpit.conf.5.html\" title=\"cockpit.conf\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"guide.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"guide.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit.conf.5.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"cockpit-manual\"></a>Manual pages</h2></div></div></div>\n<div class=\"toc\"><dl class=\"toc\">\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit.conf.5.html\">cockpit.conf</a></span><span class=\"refpurpose\"> — Cockpit configuration file</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-ws.8.html\">cockpit-ws</a></span><span class=\"refpurpose\"> — Cockpit web service</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-desktop.1.html\">cockpit-desktop</a></span><span class=\"refpurpose\"> — Cockpit Desktop integration</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"remotectl.8.html\">remotectl</a></span><span class=\"refpurpose\"> — Remote Access Configuration</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-bridge.1.html\">cockpit-bridge</a></span><span class=\"refpurpose\"> — Cockpit Host Bridge</span>\n</dt>\n</dl></div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-metrics.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.js: Metrics</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"cockpit-spawn.html\" title=\"cockpit.js: Spawning Processes\">\n<link rel=\"next\" href=\"cockpit-series-data.html\" title=\"cockpit.js: Series Data\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-spawn.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-series-data.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-metrics\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2>cockpit.js: Metrics</h2>\n<p>cockpit.js: Metrics — Reading and streaming metric data</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsynopsisdiv\">\n<h2>Synopsis</h2>\n<p>Metrics about the system can be retrieved from several sources using\n      <a class=\"link\" href=\"cockpit-metrics.html\" title=\"cockpit.js: Metrics\"><code class=\"code\">cockpit.metrics()</code></a> metrics channels.\n      The metrics are made available as series data, and can be used with the\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-series\" title=\"cockpit.series()\"><code class=\"code\">cockpit.series()</code></a> and\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid\" title=\"cockpit.grid()\"><code class=\"code\">cockpit.grid()</code></a> facilities.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-metrics-function\"></a><h2>cockpit.metrics()</h2>\n<pre class=\"programlisting\">\nmetrics = cockpit.metrics(interval, options, cache)\n</pre>\n<p>Opens a new metrics channel. The data retrieved will be available in the\n      <a class=\"link\" href=\"cockpit-metrics.html#cockpit-metrics-series\" title=\"metrics.series\"><code class=\"code\">metrics.series</code></a> series sink, and can\n      be used together with <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid\" title=\"cockpit.grid()\"><code class=\"code\">cockpit.grid()</code></a> objects.</p>\n<p>The <code class=\"code\">interval</code> is in milliseconds, and is the granularity of the series data\n      retrieved. Any grids consuming the data must have the same interval.</p>\n<p>The <code class=\"code\">cache</code> argument is a cache identifier. If\n      specified, then this metrics channel will share data with other\n      metrics channels of the same identifier. Make sure to use a\n      globally unique string.</p>\n<p>The <code class=\"code\">options</code> argument is either a javascript\n      plain object, or an array of those.  Each object can have the\n      following fields.</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"metrics\"</code></span></p></td>\n<td><p>An array of full metric descriptions, as\n          javascript objects. The specifics of these, and how to\n          determine which ones to use, can unfortunately only be found\n          in the low-level protocol documentation. This option is\n          required.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"source\"</code></span></p></td>\n<td><p>The source to use for real-time data.  This\n          is used by the <code class=\"code\">follow</code> method, see below.  Set\n          to <code class=\"code\">\"internal\"</code> to retrieve internal metrics read\n          by the bridge. If set to <code class=\"code\">\"direct\"</code> or\n          <code class=\"code\">\"pmcd\"</code> then data will be retrieved from <a class=\"ulink\" href=\"https://pcp.io\" target=\"_top\">PCP</a>if it is available. The\n          default is <code class=\"code\">\"internal\"</code>.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"archive_source\"</code></span></p></td>\n<td><p>The source to use for retrieving historical\n          data.  This is used by the <code class=\"code\">fetch</code> method, see\n          below.  Set to <code class=\"code\">\"pcp-archive\"</code> to retrieve data\n          from PCP archives.  The default is not to try to retrieve\n          historical data.</p></td>\n</tr>\n</tbody>\n</table></div>\n<p>When the <code class=\"code\">options</code> argument is an array of\n      javascript objects, then the metrics channel tries to use them in\n      order until one succeeds.  This way, you can prefer PCP as the\n      source but fall back to internal metrics when PCP is not\n      available, for example.  The channel gives no indication which\n      of the options has been used, and <code class=\"code\">fetch</code> and\n      <code class=\"code\">follow</code> might use different entries from the\n      list.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-metrics-fetch\"></a><h2>metrics.fetch()</h2>\n<pre class=\"programlisting\">\nmetrics.fetch(beg, end)\n</pre>\n<p>Retrieve archived metrics data between <code class=\"code\">beg</code> and <code class=\"code\">end</code>. The\n      arguments can either be numbers, in which case they are interval based offsets, or they\n      can be javascript Date objects.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-metrics-follow\"></a><h2>metrics.follow()</h2>\n<pre class=\"programlisting\">\nmetrics.follow()\n</pre>\n<p>Start retrieving live metrics data as it become available.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-metrics-close\"></a><h2>metrics.close()</h2>\n<pre class=\"programlisting\">\nmetrics.close()\n</pre>\n<p>Stop the retrieval of metrics and release resources.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-metrics-series\"></a><h2>metrics.series</h2>\n<p>The series sink where data retrieved data will be processed.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-metrics-meta\"></a><h2>metrics.meta</h2>\n<p>The metrics meta data last received.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-metrics-onchanged\"></a><h2>metrics.onchanged</h2>\n<pre class=\"programlisting\">\nmetrics.onchanged = function() { }\n</pre>\n<p>An event triggered when one of the properties on this metrics object changes.</p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-series-data.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.js: Series Data</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"cockpit-metrics.html\" title=\"cockpit.js: Metrics\">\n<link rel=\"next\" href=\"cockpit-channels.html\" title=\"cockpit.js: Raw Channels\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-metrics.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-channels.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-series-data\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2>cockpit.js: Series Data</h2>\n<p>cockpit.js: Series Data — Representing series data</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsynopsisdiv\">\n<h2>Synopsis</h2>\n<p>Series data consists of values along a continuous (usually time) axis. We\n    can place these in grids which expose a distinct subset of these values. These are\n    the underlying mechanism for displaying metrics data in graphs.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-grid\"></a><h2>cockpit.grid()</h2>\n<pre class=\"programlisting\">\ngrid = cockpit.grid(interval, [beg, end])\n</pre>\n<p>Creates a grid object to contain series data.</p>\n<p>The <code class=\"code\">interval</code> is the granularity of the grid. Usually this is\n      a number of milliseconds, when used with time series data. The <code class=\"code\">beg</code>\n      and <code class=\"code\">end</code> are the bounds of the grid. If omitted they will be set to\n      zero for an initially empty grid.</p>\n<p>If <code class=\"code\">beg</code> and/or <code class=\"code\">end</code> are negative (including negative\n      zero) then they are interpreted in number of intervals relative to the current\n      time. Thus cockpit.grid(1000, -300, -0) will create a grid for the most recent\n      5 minutes.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-grid-add\"></a><h2>grid.add()</h2>\n<pre class=\"programlisting\">\nrow = grid.add(series, path)\nrow = grid.add(callback, [early])\nrow = grid.add()\n</pre>\n<p>Adds a row to the grid. The returned <code class=\"code\">row</code> is a Javascript array that will contain\n      series data. The arguments control how the row is populated from the series data.\n      The <code class=\"code\">row</code> is a sparse array. Its <code class=\"code\">row.length</code> will not match the\n      expected size of the grid, unless and until the row has been completely filled in. The first\n      index of the <code class=\"code\">row</code> will contain the data from the series data at the\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid-beg\" title=\"grid.beg\"><code class=\"code\">grid.beg</code></a> offset.</p>\n<p>When no arguments are passed, an empty row is added, and it is not populated with data.</p>\n<p>When called with a <code class=\"code\">series</code> and <code class=\"code\">path</code> argument then the row\n      will be populated directly with series data. The <code class=\"code\">series</code> can either be a\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-series\" title=\"cockpit.series()\">series object</a> or an object that has an <code class=\"code\">obj.series</code>\n      property. The <a class=\"link\" href=\"cockpit-series-data.html#cockpit-series-interval\" title=\"series.interval\">series interval</a> must match the\n      interval of this grid.\n      If <code class=\"code\">path</code> is missing or empty, then the series data is placed into the row\n      directly. Otherwise <code class=\"code\">path</code> indicates which part of the series data to place in the\n      row. When <code class=\"code\">path</code> is an array, it is used as a set of property names or array indexes\n      to follow into nested series data. When <code class=\"code\">path</code> is a dotted string, it is split and used\n      the same way to locate the correct value in nested series data. The exact format of the series\n      data depends on its producer, and relevant paths will be documented there.</p>\n<p>If a <code class=\"code\">callback</code> function is specified, then it will be invoked to provide series data\n      for the row. The function is invoked as <code class=\"code\">callback(row, index, count)</code>, where the\n      <code class=\"code\">row</code> is the row to fill in, the <code class=\"code\">index</code> is the index to start filling in and\n      <code class=\"code\">count</code> is the number of items to fill in. The <code class=\"code\">this</code> variable will be set\n      to the grid while invoking the <code class=\"code\">callback</code>. The callback is called after other data\n      rows for a given series have been filled in. Callbacks are called in the order added, unless the\n      <code class=\"code\">early</code> argument is set to <code class=\"code\">true</code>, in which case the callback is called earlier\n      than callbacks without the <code class=\"code\">early</code> argument set.</p>\n<p>To remove the row use the\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid-remove\" title=\"grid.remove()\"><code class=\"code\">grid.remove()</code> method.</a>\n    </p>\n<p>The row will start being populated with data when the <code class=\"code\">series</code> produces data.\n      To make this happen right away, use the\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid-sync\" title=\"grid.sync()\"><code class=\"code\">grid.sync()</code></a> method.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-grid-remove\"></a><h2>grid.remove()</h2>\n<pre class=\"programlisting\">\ngrid.remove(row)\n</pre>\n<p>Remove a previously added <code class=\"code\">row</code> from the grid. The row will no longer be updated\n      with series data.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-grid-sync\"></a><h2>grid.sync()</h2>\n<pre class=\"programlisting\">\ngrid.sync()\n</pre>\n<p>Load or reload data from the series into the rows. This does not clear the rows before\n      populating them. Some data may be populated immediately, others may have to wait until data\n      can be loaded. Internally this function calls\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-series-load\" title=\"series.load()\"><code class=\"code\">series.load()</code></a> for each series.</p>\n<p>All rows with callbacks will be invoked to regenerate all the data. The\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid-onnotify\" title=\"grid.onnotify\"><code class=\"code\">grid.onnotify</code></a> event will be triggered.\n      It is not necessary to call this function after a call of the\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid-move\" title=\"grid.move()\"><code class=\"code\">grid.move()</code></a> method.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-grid-move\"></a><h2>grid.move()</h2>\n<pre class=\"programlisting\">\ngrid.move(beg[, end])\n</pre>\n<p>Move the grid to new <code class=\"code\">beg</code> and <code class=\"code\">end</code> range. Data will be\n      discarded from the rows and <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid-sync\" title=\"grid.sync()\"><code class=\"code\">grid.sync()</code></a>\n      will be called to load or reload series data for the new range of offsets.</p>\n<p>If <code class=\"code\">end</code> is not specified it will be set to <code class=\"code\">beg</code>. If <code class=\"code\">beg</code>\n      and/or <code class=\"code\">end</code> are negative (including negative zero) then they will be set to the\n      number of intervals prior to the current time taken as an interval.</p>\n<p>If <code class=\"code\">beg</code> and/or <code class=\"code\">end</code> are negative (including negative\n      zero) then they are interpreted in number of intervals relative to the current\n      time. Thus cockpit.grid(1000, -300, -0) will create a grid for the most recent\n      5 minutes.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-grid-walk\"></a><h2>grid.walk()</h2>\n<pre class=\"programlisting\">\ngrid.walk()\n</pre>\n<p>Move the grid forward every\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid-interval\" title=\"grid.interval\"><code class=\"code\">grid.interval</code></a> milliseconds. To stop\n      moving forward, call <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid-move\" title=\"grid.move()\"><code class=\"code\">grid.move()</code></a>.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-grid-notify\"></a><h2>grid.notify()</h2>\n<pre class=\"programlisting\">\ngrid.notify(index, count)\n</pre>\n<p>This function is called to have rows with callbacks recalculate their data. It is not\n      normally necessary to call this function, as it will be invoked automatically when new\n      series data is available or has been loaded. This function triggers the\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid-onnotify\" title=\"grid.onnotify\"><code class=\"code\">grid.onnotify</code></a> event.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-grid-onnotify\"></a><h2>grid.onnotify</h2>\n<pre class=\"programlisting\">\ngrid.addEventListener(\"notify\", function(index, count) { ... });\n</pre>\n<p>An event that is triggered when some part of the series data in grid changes. The\n      <code class=\"code\">index</code> is the row index where things changed, and the <code class=\"code\">count</code>\n      is the length of the data that changed.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-grid-close\"></a><h2>grid.close()</h2>\n<pre class=\"programlisting\">\ngrid.close()\n</pre>\n<p>Close the grid, and stop updating the rows.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-grid-interval\"></a><h2>grid.interval</h2>\n<p>The granularity of the grid. For time series data this is an interval in\n      milliseconds. In order to use a given\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid\" title=\"cockpit.grid()\">grid</a> and\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-series\" title=\"cockpit.series()\">series</a> together, their interval properties\n      must match.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-grid-beg\"></a><h2>grid.beg</h2>\n<p>The beginning offset of the series data in the grid. Do not set this property\n      directly. Use the <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid-move\" title=\"grid.move()\">grid.move()</a> method instead.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-grid-end\"></a><h2>grid.end</h2>\n<p>The ending offset of the series data in the grid. Do not set this property\n      directly. Use the <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid-move\" title=\"grid.move()\">grid.move()</a> method instead.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-series\"></a><h2>cockpit.series()</h2>\n<pre class=\"programlisting\">\nseries = cockpit.series(interval, [cache, fetch])\n</pre>\n<p>Create a new sink of series data. This is usually done by producers of series data,\n      and it is rare to invoke this function directly.</p>\n<p>The <code class=\"code\">interval</code> is the granularity of the series data. For time series data\n      this is an interval in milliseconds. If a <code class=\"code\">cache</code> string is specified, series data\n      will be cached across frames for series with the same <code class=\"code\">cache</code> cache identifier\n      to load and/or reload.</p>\n<p>If a <code class=\"code\">fetch</code> callback\n      is specified, then it will be invoked when grids request certain ranges of data. The\n      <code class=\"code\">fetch</code> callback is invoked with <code class=\"code\">function fetch(beg, end) { ... }</code>\n      range offsets. The <a class=\"link\" href=\"cockpit-series-data.html#cockpit-series-input\" title=\"series.input()\">series.input()</a> should be\n      called with data retrieved, either immediately or at a later time. The callback may be\n      called multiple times for the same ranges of data. It is up to the callback to determine\n      when or whether it should retrieve the data more than once.</p>\n<p>A producer of series data, usually calls this function and creates itself a\n      <code class=\"code\">obj.series</code> property containing this series object.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-series-input\"></a><h2>series.input()</h2>\n<pre class=\"programlisting\">\nseries.input(beg, items[, mapping])\n</pre>\n<p>Send series data into the series sink. Any grids that have added rows based on this\n      series, will have data filled in. The <code class=\"code\">beg</code> is the beginning offset of\n      <code class=\"code\">items</code>. The <code class=\"code\">items</code> are an array one or more series data items.</p>\n<p>Producers may wish to provide additional properties that can be used in lookup paths that\n      rows can pull from. This is done in the <code class=\"code\">mapping</code> argument. If specified it is\n      a tree of objects. Each sub object should have a property with the name <code class=\"code\">\"\"</code>\n      empty string, which will be used as the property name or index in place of the one used\n      in the lookup path.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-series-load\"></a><h2>series.load()</h2>\n<pre class=\"programlisting\">\nseries.load(beg, end)\n</pre>\n<p>Load data from the series into any grids that have rows based on this series data.\n      Any cached data will be filled in immediately. Any data not cached, will be requested\n      from the producer, if possible, and may arrive at a later time.</p>\n<p>The <code class=\"code\">beg</code> and <code class=\"code\">end</code> denote the range of data to load.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-series-interval\"></a><h2>series.interval</h2>\n<p>The granularity of the series. For time series data this is an interval in\n      milliseconds. In order to use a given\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid\" title=\"cockpit.grid()\">grid</a> and\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-series\" title=\"cockpit.series()\">series</a> together, their interval properties\n      must match.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-series-limit\"></a><h2>series.limit</h2>\n<p>The maximum number of items to cache for loading and/or reloading. You can\n      change this value to a different number. Having a number close to zero will break\n      certain usage of grids, such as\n      <a class=\"link\" href=\"cockpit-series-data.html#cockpit-grid-walk\" title=\"grid.walk()\"><code class=\"code\">grid.walk()</code></a>.</p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-spawn.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.js: Spawning Processes</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"cockpit-http.html\" title=\"cockpit.js: HTTP Client\">\n<link rel=\"next\" href=\"cockpit-metrics.html\" title=\"cockpit.js: Metrics\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-http.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-metrics.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-spawn\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2>cockpit.js: Spawning Processes</h2>\n<p>cockpit.js: Spawning Processes — Spawning processes or scripts</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsynopsisdiv\">\n<h2>Synopsis</h2>\n<p>This is the API for spawning a process and receiving its output, as well\n    as exit codes.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-spawn-spawn\"></a><h2>cockpit.spawn()</h2>\n<pre class=\"programlisting\">\nprocess = cockpit.spawn(args, [options])\n</pre>\n<p>Spawns a process on the system.</p>\n<p>The <code class=\"code\">args</code> should be an array starting with the executable and\n      containing all the arguments to pass on the command line. If <code class=\"code\">args</code>\n      is a string then it is interpreted as an executable name. The optional\n      <code class=\"code\">options</code> argument is a javascript plain object and can contain\n      any of the following fields:\n    </p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"binary\"</code></span></p></td>\n<td><p>If set to <code class=\"code\">true</code> then handle the input and output\n          of the process as arrays of binary bytes.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"directory\"</code></span></p></td>\n<td><p>The directory to spawn the process in.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"err\"</code></span></p></td>\n<td><p>Controls where the standard error is sent. By default it is logged\n          to the journal. If set to <code class=\"code\">\"out\"</code> it is included in with the\n          output data. If set to <code class=\"code\">\"ignore\"</code> then the error output is discarded.\n          If set to <code class=\"code\">\"message\"</code>, then it will be returned as the error message.\n          When the <code class=\"code\">\"pty\"</code> field is set, this field has no effect.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"host\"</code></span></p></td>\n<td><p>The remote host to spawn the process on. If an alternate user or port is\n          required it can be specified as <code class=\"code\">\"user@myhost:port\"</code>. If no host is\n          specified then the correct one will be automatically selected based on the page\n          calling this function.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"environ\"</code></span></p></td>\n<td><p>An optional array that contains strings to be used as\n          additional environment variables for the new process. These are\n          <code class=\"code\">\"NAME=VALUE\"</code> strings.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"pty\"</code></span></p></td>\n<td><p>Launch the process in its own PTY terminal, and send/receive\n          terminal input and output.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"batch\"</code></span></p></td>\n<td><p>Batch data coming from the process in blocks of at least this\n            size. This is not a guarantee. After a short timeout the data will be sent\n            even if the data doesn't match the batch size. Defaults to zero.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"latency\"</code></span></p></td>\n<td><p> The timeout for flushing any cached data in milliseconds.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"superuser\"</code></span></p></td>\n<td>\n<p>Set to <code class=\"code\">\"require\"</code> to spawn the process as root instead of\n            the logged in user. If the currently logged in user is not permitted to become root\n            (eg: via <code class=\"code\">pkexec</code>) then the <code class=\"code\">client</code> will immediately be\n            <a class=\"link\" href=\"cockpit-dbus.html#cockpit-dbus-onclose\" title=\"client.onclose\">closed</a> with a <code class=\"code\">\"access-denied\"</code>\n            problem code.</p>\n<p>Set to <code class=\"code\">\"try\"</code> to try to run the process as root, but if that fails,\n            fall back to an unprivileged process.</p>\n</td>\n</tr>\n</tbody>\n</table></div>\n<p>The spawned process is a\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>\n      that will complete if the process exits successfully, or fail if there's a problem.\n      Some additional methods besides the standard promise methods are documented\n      below.</p>\n<p>The standard output of the process is made available via the spawned process\n      object. Any non-UTF8 output from the process will be coerced into textual form.\n      It is highly recommended that only textual output be produced by the command.\n      The standard error is logged to the journal.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-spawn-script\"></a><h2>cockpit.script()</h2>\n<pre class=\"programlisting\">\nprocess = cockpit.script(script, [args], [options])\n</pre>\n<p>Run a shell script on the system.</p>\n<p>This function <a class=\"link\" href=\"cockpit-spawn.html#cockpit-spawn-spawn\" title=\"cockpit.spawn()\">spawns</a> a Bourne shell script\n      process. The full text of the <code class=\"code\">/bin/sh</code> shell script should be passed in as\n      the first argument. The <code class=\"code\">args</code> can be an array of arguments, not including\n      the executable, which are passed to the script as <code class=\"code\">$1</code>, <code class=\"code\">$2</code> and\n      so on. Shebang options are not used or respected.</p>\n<p>The <code class=\"code\">options</code> is an optional javascript plain object and can include\n      any of the fields listed for the\n      <a class=\"link\" href=\"cockpit-spawn.html#cockpit-spawn-spawn\" title=\"cockpit.spawn()\"><code class=\"code\">cockpit.spawn()</code></a> function.</p>\n<p>The spawned process is a\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>\n      that will complete if the script exits successfully, or fail if there's a problem.\n      Some additional methods besides the standard promise methods are documented\n      below.</p>\n<p>The standard output of the process is made available via the spawned process\n      object. Any non-UTF8 output from the process will be coerced into textual form.\n      It is highly recommended that only textual output be produced by the command.\n      The standard error is logged to the journal by default.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-spawn-done\"></a><h2>process.done()</h2>\n<pre class=\"programlisting\">\nprocess.done(function(data[, message]) { ... })\n</pre>\n<p>This is a standard\n      <a class=\"ulink\" href=\"https://www.promisejs.org/\" target=\"_top\">promise</a>\n      method. It sets up a handler to be called when the process finishes successfully.</p>\n<p>The <code class=\"code\">data</code> argument contains the standard output of the process.\n      If it a string, unless the process was opened in binary mode, in which case the\n      <code class=\"code\">data</code> is an array of bytes. If a\n      <code class=\"code\"><a class=\"link\" href=\"cockpit-spawn.html#cockpit-spawn-stream\" title=\"process.stream()\">process.stream()</a></code>\n      handler is set up, then any standard output data consumed by the handler will not\n      be included in the <code class=\"code\">data</code> argument.</p>\n<p>If the process was spawned with the <code class=\"code\">\"err\"</code> option set to\n      <code class=\"code\">\"message\"</code> then the second argument will contain the standard error\n      output of the process.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-spawn-fail\"></a><h2>process.fail()</h2>\n<pre class=\"programlisting\">\nprocess.fail(function(exception[, data]) { ... })\n</pre>\n<p>This is a standard\n      <a class=\"ulink\" href=\"https://api.jquery.com/category/deferred-object/\" target=\"_top\">jQuery promise</a> method.\n      It sets up a handler to be called when the process fails, terminates or exits.</p>\n<p>The <code class=\"code\">exception</code> object passed to the handler can have the\n      following fields:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">message</code></span></p></td>\n<td><p>A message describing the exception. If the process was spawned with\n            the <code class=\"code\">\"err\"</code> option set to <code class=\"code\">\"message\"</code> then the second argument\n            will contain the standard error output of the process.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">problem</code></span></p></td>\n<td><p>A <a class=\"link\" href=\"cockpit-error.html#cockpit-problems\" title=\"Problem Codes\">problem code</a> string when\n          a problem occurred starting or communicating with the process. This is <code class=\"code\">null</code>\n          if the process exited or was terminated.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">exit_status</code></span></p></td>\n<td><p>The numeric exit status of the process. This is <code class=\"code\">null</code> if\n          the process did not exit.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">exit_signal</code></span></p></td>\n<td><p>A string representing a unix signal that caused the process to terminate.\n          This is <code class=\"code\">null</code> if the process did not terminate because of a signal.</p></td>\n</tr>\n</tbody>\n</table></div>\n<p>If the process actually ran and produced output before failing, it will be available in\n      the <code class=\"code\">data</code> argument. Otherwise this argument will be <code class=\"code\">undefined</code>.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-spawn-always\"></a><h2>process.always()</h2>\n<pre class=\"programlisting\">\nprocess.always(function() { ... })\n</pre>\n<p>This is a standard\n      <a class=\"ulink\" href=\"https://api.jquery.com/category/deferred-object/\" target=\"_top\">jQuery promise</a> method.\n      It sets up a handler to be called when the process completes, whether it exits successfully,\n      fails, terminates, or exits with a failure.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-spawn-stream\"></a><h2>process.stream()</h2>\n<pre class=\"programlisting\">\nprocess.stream(function(data) { ... })\n</pre>\n<p>This sets up a handler to be called when the process has standard output. The\n      handler will be called multiple times. The handler will be called regardless of\n      whether the process ends up exiting successfully or not.</p>\n<p>Only one handler may be registered at a time. Registering an additional handler\n      replaces the previous one. The handler receives either string <code class=\"code\">data</code> or\n      an array of binary bytes as its argument. A stream handler may return a number, which\n      indicates the number of characters or bytes consumed from <code class=\"code\">data</code>. Any data\n      not consumed will be included again the next time the handler is called.</p>\n<p>If a <code class=\"code\">process.stream()</code> handler is set up, then the\n      <code class=\"code\"><a class=\"link\" href=\"cockpit-spawn.html#cockpit-spawn-done\" title=\"process.done()\">process.done()</a></code> handlers will\n      only get any remaining data not consumed by the stream handler.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-spawn-input\"></a><h2>process.input()</h2>\n<pre class=\"programlisting\">\nprocess.input(data, [stream])\n</pre>\n<p>This method writes <code class=\"code\">data</code> to the standard input of the process.\n      If <code class=\"code\">data</code> is <code class=\"code\">null</code> or <code class=\"code\">undefined</code> it is not sent.\n      The <code class=\"code\">data</code> should be a string or an array of bytes if the process was\n      opened in binary mode.</p>\n<p>If <code class=\"code\">stream</code> is set to <code class=\"code\">true</code> then this function may be\n      called again with further input. Otherwise the standard input of the process\n      is closed.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-spawn-close\"></a><h2>process.close()</h2>\n<pre class=\"programlisting\">\nprocess.close([problem])\n</pre>\n<p>Close the process by closing its standard input and output. If <code class=\"code\">problem</code> is\n      specified it should be a standard\n      <a class=\"link\" href=\"cockpit-error.html#cockpit-problems\" title=\"Problem Codes\">problem code</a> string. In this case the\n      process will be terminated with a signal.</p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-util.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.js: Utilities</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"prev\" href=\"cockpit-login.html\" title=\"cockpit.js: User Session\">\n<link rel=\"next\" href=\"cockpit-cache.html\" title=\"cockpit.js: Object Cache\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-login.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"api-base1.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-cache.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-util\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2>cockpit.js: Utilities</h2>\n<p>cockpit.js: Utilities — Various utility functions</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsection\">\n<a name=\"cockpit-format\"></a><h2>cockpit.format()</h2>\n<pre class=\"programlisting\">\nstring = cockpit.format(template, args)\nstring = cockpit.format(template, [arg, ...])\n</pre>\n<p>Format a string interpolating <code class=\"code\">args</code> into <code class=\"code\">template</code> using\n      shell like syntax. The <code class=\"code\">args</code> may be either an array or javascript object.\n      The <code class=\"code\">template</code> can contain fields that look like <code class=\"code\">$name</code> or\n      <code class=\"code\">${name}</code> or <code class=\"code\">$0</code>. Numeric fields are used with array\n      <code class=\"code\">args</code> and start at zero.</p>\n<p>In the second form, multiple <code class=\"code\">arg</code> arguments may be passed directly,\n      and interpolated as as numeric fields in the <code class=\"code\">template</code>.</p>\n<p>All falsy arguments except the numbers <code class=\"code\">0</code> and <code class=\"code\">0.0</code>are\n      replaced by an empty string.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-format-bytes\"></a><h2>cockpit.format_bytes()</h2>\n<pre class=\"programlisting\">\nstring = cockpit.format_bytes(number, [factor])\narray = cockpit.format_bytes(number, [factor, separate])\n</pre>\n<p>Formats <code class=\"code\">number</code> into a displayable <code class=\"code\">string</code> with a suffix, such as\n      <span class=\"emphasis\"><em>KB</em></span> or <span class=\"emphasis\"><em>MB</em></span>. Returns an <code class=\"code\">array</code> of the\n      formatted number and the suffix if <code class=\"code\">separate</code> is set to <code class=\"code\">true</code>.</p>\n<p>If specifying 1000 or 1024 is specified as a <code class=\"code\">factor</code> then an appropriate suffix\n      will be chosen. By default the <code class=\"code\">factor</code> is 1024.  You can pass a string suffix as a\n      <code class=\"code\">factor</code> in which case the resulting number will be formatted with the same suffix.</p>\n<p>If the <code class=\"code\">number</code> is less than the <code class=\"code\">factor</code> or an unknown factor\n      was passed in, then the formatted number is returned without a suffix. If <code class=\"code\">separate</code>\n      is true, returns an array of <code class=\"code\">[formatted_number, suffix]</code> or\n      <code class=\"code\">[formatted_number]</code> if returned without a suffix.</p>\n<p>If <code class=\"code\">number</code> is <code class=\"code\">null</code> or <code class=\"code\">undefined</code> an empty string or\n      an array without a suffix will be returned.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-format-number\"></a><h2>cockpit.format_number()</h2>\n<pre class=\"programlisting\">\nstring = cockpit.format_number(number)\n</pre>\n<p>Formats <code class=\"code\">number</code> into a displayable <code class=\"code\">string</code>. If the number is not\n      an integer, it is rounded to a single decimal place precision. If the number is near zero, but\n      not quite zero it is rounded up or down to a single decimal place.</p>\n<p>If <code class=\"code\">number</code> is <code class=\"code\">null</code> or <code class=\"code\">undefined</code> an empty string\n      will be returned.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-format-bytes-per-sec\"></a><h2>cockpit.format_bytes_per_sec()</h2>\n<pre class=\"programlisting\">\n string = cockpit.format_bytes_per_sec(number, [factor])\n array = cockpit.format_bytes_per_sec(number, [factor, separate])\n</pre>\n<p>Format <code class=\"code\">number</code> of bytes into a displayable speed <code class=\"code\">string</code>.</p>\n<p>If specifying 1000 or 1024 is specified as a <code class=\"code\">factor</code> then an appropriate suffix\n      will be chosen. By default the <code class=\"code\">factor</code> is 1024.  You can pass a string suffix as a\n      <code class=\"code\">factor</code> in which case the resulting number will be formatted with the same suffix.</p>\n<p>If the <code class=\"code\">number</code> is less than the <code class=\"code\">factor</code> or an unknown factor\n      was passed in, then the formatted number is returned without a suffix. If <code class=\"code\">separate</code>\n      is true, returns an array of <code class=\"code\">[formatted_number, suffix]</code> or\n      <code class=\"code\">[formatted_number]</code> if returned without a suffix.</p>\n<p>If <code class=\"code\">number</code> is <code class=\"code\">null</code> or <code class=\"code\">undefined</code> an empty string or array\n      will be returned.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-format-bits-per-sec\"></a><h2>cockpit.format_bits_per_sec()</h2>\n<pre class=\"programlisting\">\n  string = cockpit.format_bits_per_sec(number, [factor])\n array = cockpit.format_bytes_per_sec(number, [factor, separate])\n</pre>\n<p>Format <code class=\"code\">number</code> of bits into a displayable speed <code class=\"code\">string</code>.</p>\n<p>If specifying 1000 or 1024 is specified as a <code class=\"code\">factor</code> then an appropriate suffix\n      will be chosen. By default the <code class=\"code\">factor</code> is 1024.  You can pass a string suffix as a\n      <code class=\"code\">factor</code> in which case the resulting number will be formatted with the same suffix.</p>\n<p>If the <code class=\"code\">number</code> is less than the <code class=\"code\">factor</code> or an unknown factor\n      was passed in, then the formatted number is returned without a suffix. If <code class=\"code\">separate</code>\n      is true, returns an array of <code class=\"code\">[formatted_number, suffix]</code> or\n      <code class=\"code\">[formatted_number]</code> if returned without a suffix.</p>\n<p>If <code class=\"code\">number</code> is <code class=\"code\">null</code> or <code class=\"code\">undefined</code> an empty string or array\n      will be returned.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-info\"></a><h2>cockpit.info</h2>\n<pre class=\"programlisting\">\ncockpit.info[\"version\"]\ncockpit.info[\"build\"]\n</pre>\n<p>This object contains information about cockpit itself. Note that when cockpit is\n      running on multiple servers, this only reflects the server that was connected to.\n      The following fields are defined:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"build\"</code></span></p></td>\n<td><p>A string containing build details.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"version\"</code></span></p></td>\n<td><p>A string containing the cockpit version number. It is almost always\n          incorrect to use this to make a decision in code.</p></td>\n</tr>\n</tbody>\n</table></div>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-event-target\"></a><h2>cockpit.event_target</h2>\n<pre class=\"programlisting\">\ncockpit.event_target(object, [handlers])\n</pre>\n<p>Adds an\n      <a class=\"ulink\" href=\"https://developer.mozilla.org/en-US/docs/Web/API/EventTarget\" target=\"_top\">EventTarget</a>\n      implementation to the <code class=\"code\">object</code>. Optionally store the handlers in <code class=\"code\">handlers</code>\n      if its specified.</p>\n</div>\n<div class=\"refsection\">\n<a name=\"cockpit-extend\"></a><h2>cockpit.extend</h2>\n<pre class=\"programlisting\">\ncockpit.extend(target, src, ...)\n</pre>\n<p>This function is used to copy the values of all enumerable own properties\n      from one or more source objects to a target object. It will return the target object. This\n      is similar to <code class=\"code\">Object.assign()</code>.</p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit-ws.8.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit-ws</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"cockpit-manual.html\" title=\"Manual pages\">\n<link rel=\"prev\" href=\"cockpit.conf.5.html\" title=\"cockpit.conf\">\n<link rel=\"next\" href=\"cockpit-desktop.1.html\" title=\"cockpit-desktop\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit.conf.5.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"cockpit-manual.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-desktop.1.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit-ws.8\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2><span class=\"refentrytitle\">cockpit-ws</span></h2>\n<p>cockpit-ws — Cockpit web service</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsynopsisdiv\">\n<h2>Synopsis</h2>\n<div class=\"cmdsynopsis\"><p><code class=\"command\">cockpit-ws</code>  [<code class=\"option\">--help</code>] [<code class=\"option\">--port</code> <em class=\"replaceable\"><code>PORT</code></em>] [<code class=\"option\">--address</code> <em class=\"replaceable\"><code>ADDRESS</code></em>] [<code class=\"option\">--no-tls</code>] [<code class=\"option\">--for-tls-proxy</code>] [<code class=\"option\">--local-ssh</code>] [<code class=\"option\">--local-session</code> <em class=\"replaceable\"><code>BRIDGE</code></em>]</p></div>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-ws-description\"></a><h2>DESCRIPTION</h2>\n<p>\n      The <span class=\"command\"><strong>cockpit-ws</strong></span> program is the web service\n      component used for communication between the browser application\n      and various configuration tools and services like\n      <span class=\"citerefentry\"><span class=\"refentrytitle\">cockpit-bridge</span>(8)</span>.\n    </p>\n<p>\n      Users or administrators should never need to start this program\n      as it automatically started by\n      <span class=\"citerefentry\"><span class=\"refentrytitle\">systemd</span>(1)</span>\n      on bootup.\n    </p>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-ws-transport\"></a><h2>TRANSPORT SECURITY</h2>\n<p>\n      To specify the TLS certificate the web service should use, simply\n      drop a file with the extension <code class=\"literal\">.cert</code> in the\n      <code class=\"filename\">/etc/cockpit/ws-certs.d</code> directory. If there are\n      multiple files in this directory, then the highest priority one\n      is chosen after sorting.</p>\n<p>The <code class=\"literal\">.cert</code> file should contain at least two\n      OpenSSL style PEM blocks. First one or more <code class=\"literal\">BEGIN CERTIFICATE</code>\n      blocks for the server certificate and intermediate certificate authorities\n      and a last one containing a <code class=\"literal\">BEGIN PRIVATE KEY</code> or similar.\n      The key may not be encrypted.</p>\n<p>If there is no TLS certificate, a self-signed certificate is\n      automatically generated using <span class=\"command\"><strong>openssl</strong></span> and stored in\n      the <code class=\"filename\">0-self-signed.cert</code> file.</p>\n<p>When enrolling into a FreeIPA domain, an SSL certificate is requested from\n      the IPA server and stored in <code class=\"filename\">10-ipa.cert</code>.</p>\n<p>To check which certificate <span class=\"command\"><strong>cockpit-ws</strong></span> will use,\n      run the following command.</p>\n<pre class=\"programlisting\">\n$ sudo remotectl certificate\n</pre>\n<p>If using <code class=\"literal\">certmonger</code> to manage certificates, following command can\n      be used to automatically prepare concatenated <code class=\"literal\">.cert</code> file:</p>\n<pre class=\"programlisting\">\nCERT_FILE=/etc/pki/tls/certs/$(hostname).pem\nKEY_FILE=/etc/pki/tls/private/$(hostname).key\n\ngetcert request -f ${CERT_FILE} -k ${KEY_FILE} -D $(hostname --fqdn) -C \"sed -n w/etc/cockpit/ws-certs.d/50-from-certmonger.cert ${CERT_FILE} ${KEY_FILE}\"\n</pre>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-ws-timeout\"></a><h2>TIMEOUT</h2>\n<p>\n      When started via\n      <span class=\"citerefentry\"><span class=\"refentrytitle\">systemd</span>(1)</span>\n      then <span class=\"command\"><strong>cockpit-ws</strong></span> will exit after 90 seconds\n      if nobody logs in, or after the last user is disconnected.\n    </p>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-ws-options\"></a><h2>OPTIONS</h2>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">--help</code></span></p></td>\n<td><p>\n            Show help options.\n          </p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">--port</code> <em class=\"replaceable\"><code>PORT</code></em></span></p></td>\n<td><p>\n            Serve HTTP requests <em class=\"replaceable\"><code>PORT</code></em> instead of port 9090.\n            Usually Cockpit is started on demand by <span class=\"command\"><strong>systemd</strong></span> socket\n            activation, and this option has no effect. Update the\n            <code class=\"literal\">ListenStream</code> directive <code class=\"filename\">cockpit.socket</code>\n            file in the usual <span class=\"command\"><strong>systemd</strong></span> manner.\n          </p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">--address</code> <em class=\"replaceable\"><code>ADDRESS</code></em></span></p></td>\n<td><p>\n            Bind to address <em class=\"replaceable\"><code>ADDRESS</code></em> instead of binding to\n            all available addresses. Usually Cockpit is started on demand by\n            <span class=\"command\"><strong>systemd</strong></span> socket activation, and this option has no effect.\n            In that case, update the <code class=\"literal\">ListenStream</code> directive in the\n            <code class=\"filename\">cockpit.socket</code> file in the usual <span class=\"command\"><strong>systemd</strong></span> manner.\n          </p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">--no-tls</code></span></p></td>\n<td><p>\n            Don't use TLS.\n          </p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">--for-tls-proxy</code></span></p></td>\n<td>\n<p>\n            Tell <span class=\"command\"><strong>cockpit-ws</strong></span> that it is running behind a local reverse proxy that\n            does the TLS termination. Then Cockpit puts https:// URLs into the default\n            <code class=\"literal\">Content-Security-Policy</code>, and accepts only https:// origins, instead of\n            http: ones by default. However, if <code class=\"literal\">Origins</code> is set in the\n            <span class=\"citerefentry\"><span class=\"refentrytitle\">cockpit.conf</span>(5)</span>\n            configuration file, it will override this default.\n          </p>\n<p>\n            This option implies <code class=\"option\">--no-tls</code>.\n          </p>\n</td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">--local-ssh</code></span></p></td>\n<td><p>\n            Normally <span class=\"command\"><strong>cockpit-ws</strong></span> uses\n            <span class=\"command\"><strong>cockpit-session</strong></span> and PAM to authenticate the user and start a\n            user session. With this option enabled, it will instead authenticate via SSH at\n            <code class=\"literal\">127.0.0.1</code> port <code class=\"literal\">22</code>.\n          </p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">--local-session</code> <em class=\"replaceable\"><code>BRIDGE</code></em></span></p></td>\n<td>\n<p>\n            Skip all authentication and <span class=\"command\"><strong>cockpit-session</strong></span>, and launch the\n            <span class=\"command\"><strong>cockpit-bridge</strong></span> specified in <em class=\"replaceable\"><code>BRIDGE</code></em> in\n            the local session. If the <em class=\"replaceable\"><code>BRIDGE</code></em> is specified as\n            <span class=\"command\"><strong>-</strong></span> then expect an already running bridge that is connected to\n            stdin and stdout of this <span class=\"command\"><strong>cockpit-ws</strong></span> process. This allows the\n            web server to run as any unprivileged user in an already running session.\n          </p>\n<p>\n            This mode implies <code class=\"literal\">--no-tls</code>, thus you need to use http://\n            URLs with this.\n          </p>\n<div class=\"warning\" style=\"margin-left: 0.5in; margin-right: 0.5in;\">\n<h3 class=\"title\">Warning</h3>\n<p>\n              If you use this, you <span class=\"emphasis\"><em>have to isolate the opened TCP port</em></span>\n              somehow (for example in a network namespace), otherwise all other users (or\n              even remote machines if the port is not just listening on localhost) can access\n              the session!\n            </p>\n</div>\n</td>\n</tr>\n</tbody>\n</table></div>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-ws-environment\"></a><h2>ENVIRONMENT</h2>\n<p>\n      The <span class=\"command\"><strong>cockpit-ws</strong></span> process will use the <code class=\"literal\">XDG_CONFIG_DIRS</code>\n      environment variable from the\n      <a class=\"ulink\" href=\"https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html\" target=\"_top\">XDG\n        basedir spec</a> to find its\n      <span class=\"citerefentry\"><span class=\"refentrytitle\">cockpit.conf</span>(5)</span>\n      configuration file.\n    </p>\n<p>\n      In addition the <code class=\"literal\">XDG_DATA_DIRS</code> environment variable from the\n      <a class=\"ulink\" href=\"https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html\" target=\"_top\">XDG\n        basedir spec</a>\n      can be used to override the location to serve static files from. These are the files that\n      are served to a non-logged in user.\n    </p>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-ws-bugs\"></a><h2>BUGS</h2>\n<p>\n      Please send bug reports to either the distribution bug tracker or the\n      <a class=\"ulink\" href=\"https://github.com/cockpit-project/cockpit/issues/new\" target=\"_top\">upstream bug tracker</a>.\n    </p>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-ws-author\"></a><h2>AUTHOR</h2>\n<p>Cockpit has been written by many\n      <a class=\"ulink\" href=\"https://github.com/cockpit-project/cockpit/\" target=\"_top\">contributors</a>.</p>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-ws-also\"></a><h2>SEE ALSO</h2>\n<p>\n      <span class=\"citerefentry\"><span class=\"refentrytitle\">cockpit.conf</span>(5)</span>\n      ,\n      <span class=\"citerefentry\"><span class=\"refentrytitle\">systemd</span>(1)</span>\n    </p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/cockpit.conf.5.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>cockpit.conf</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"cockpit-manual.html\" title=\"Manual pages\">\n<link rel=\"prev\" href=\"cockpit-manual.html\" title=\"Manual pages\">\n<link rel=\"next\" href=\"cockpit-ws.8.html\" title=\"cockpit-ws\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-manual.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"cockpit-manual.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-ws.8.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"cockpit.conf.5\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2><span class=\"refentrytitle\">cockpit.conf</span></h2>\n<p>cockpit.conf — Cockpit configuration file</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsect1\">\n<a name=\"cockpit-conf-description\"></a><h2>DESCRIPTION</h2>\n<p>\n    Cockpit can be configured via /etc/cockpit/cockpit.conf.  That file has a INI\n    file syntax and thus contains key / value pairs, grouped into topical groups. See the\n    examples below for details..\n  </p>\n<p>Note: The port that cockpit listens on cannot be changed in this file. To change\n    the port change the systemd <code class=\"filename\">cockpit.socket</code> file.</p>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-conf-webservice\"></a><h2>WebService</h2>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">Origins</code></span></p></td>\n<td>\n<p>By default cockpit will not accept crossdomain websocket connections. Use this\n                  setting to allow access from alternate domains. Origins should include scheme, host\n                  and port, if necessary.</p>\n<div class=\"informalexample\"><pre class=\"programlisting\">\n[WebService]\nOrigins = https://somedomain1.com https://somedomain2.com:9090\n</pre></div>\n</td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">ProtocolHeader</code></span></p></td>\n<td>\n<p>Configure cockpit to look at the contents of this header to determine if a connection\n                  is using tls. This should only be used when cockpit is behind a reverse proxy, and care\n                  should be taken to make sure that incoming requests cannot set this header.</p>\n<div class=\"informalexample\"><pre class=\"programlisting\">\n[WebService]\nProtocolHeader = X-Forwarded-Proto\n</pre></div>\n</td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">LoginTitle</code></span></p></td>\n<td><p>Set the browser title for the login screen.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">LoginTo</code></span></p></td>\n<td><p>When set to <code class=\"literal\">true</code> the <span class=\"emphasis\"><em>Connect to</em></span> option\n            on the login screen is visible and allows logging into another server. If this\n            option is not specified then it will be automatically detected based on whether\n            the <span class=\"command\"><strong>cockpit-ssh</strong></span> process is available or not.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">RequireHost</code></span></p></td>\n<td><p>When set to <code class=\"literal\">true</code> cockpit will require users to use the\n            <span class=\"emphasis\"><em>Connect to</em></span> option to specify the host to log into.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">MaxStartups</code></span></p></td>\n<td>\n<p>Same as the <span class=\"command\"><strong>sshd</strong></span> configuration option by the same name.\n            Specifies the maximum number of concurrent login attempts\n            allowed. Additional connections will be dropped until authentication\n            succeeds or the connections are closed. Defaults to 10.</p>\n<p>Alternatively, random early drop can be enabled by specifying the\n             three colon separated values <code class=\"literal\">start:rate:full</code> (e.g.\n             \"10:30:60\"). Cockpit will start refusing authentication attempts with a\n             probability of <code class=\"literal\">rate/100</code> (30%) if there are currently\n             <code class=\"literal\">start</code> (10) unauthenticated connections.  The probability\n             increases linearly and all connection attempts are refused if the\n             number of unauthenticated connections reaches <code class=\"literal\">full</code> (60).</p>\n</td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">AllowUnencrypted</code></span></p></td>\n<td><p>If true, cockpit will accept unencrypted HTTP connections. Otherwise, it\n            redirects all HTTP connections to HTTPS. Exceptions are connections from\n            localhost and for certain URLs (like <code class=\"code\">/ping</code>). Defaults to\n            false.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">UrlRoot</code></span></p></td>\n<td><p>The root URL where you will be serving cockpit. When provided cockpit will expect all\n          requests to be prefixed with the given url. This is mostly useful when you are using\n          cockpit behind a reverse proxy, such as nginx. <code class=\"code\">/cockpit/</code> and <code class=\"code\">/cockpit+</code>\n          are reserved and should not be used. For example <code class=\"code\">/cockpit-new/</code> is ok.\n          <code class=\"code\">/cockpit/</code> and <code class=\"code\">/cockpit+new/</code> are not.</p></td>\n</tr>\n</tbody>\n</table></div>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-conf-log\"></a><h2>Log</h2>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody><tr>\n<td><p><span class=\"term\"><code class=\"option\">Fatal</code></span></p></td>\n<td><p>The kind of log messages in the bridge to treat as fatal. Separate multiple values\n            with spaces. Relevant values are: <code class=\"code\">criticals</code> and <code class=\"code\">warnings</code>.</p></td>\n</tr></tbody>\n</table></div>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-conf-oauth\"></a><h2>OAuth</h2>\n<p>Cockpit can be configured to support the <a class=\"ulink\" href=\"https://tools.ietf.org/html/rfc6749#section-4.2\" target=\"_top\">\n        implicit grant</a> OAuth authorization flow. When successful the resulting oauth\n        token will be passed to cockpit-ws using the <code class=\"literal\">Bearer</code> auth-scheme.\n        For a login to be successful, cockpit will also need a to be configured to verify\n        and allow <code class=\"literal\">Bearer</code> tokens.</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">URL</code></span></p></td>\n<td><p>This is the url that cockpit will redirect the users browser to when it needs\n          to obtain an oauth token. Cockpit will add a redirect_uri parameter to the url with\n          the location of where the oauth provider should redirect to once a token has been\n          obtained.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">ErrorParam</code></span></p></td>\n<td><p>When a oauth provider redirects a user back to cockpit, look for this parameter\n          in the querystring or fragment portion of the url to find a error message. When not\n          provided it will default to <code class=\"literal\">error_description</code></p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">TokenParam</code></span></p></td>\n<td><p>When a oauth provider redirects a user back to cockpit, look for this parameter\n          in the querystring or fragment portion of the url to find the access token. When not\n          provided it will default to <code class=\"literal\">access_token</code></p></td>\n</tr>\n</tbody>\n</table></div>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-conf-bugs\"></a><h2>BUGS</h2>\n<p>\n      Please send bug reports to either the distribution bug tracker or the\n      <a class=\"ulink\" href=\"https://github.com/cockpit-project/cockpit/issues/new\" target=\"_top\">upstream bug tracker</a>.\n    </p>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-conf-author\"></a><h2>AUTHOR</h2>\n<p>Cockpit has been written by many\n      <a class=\"ulink\" href=\"https://github.com/cockpit-project/cockpit/\" target=\"_top\">contributors</a>.</p>\n</div>\n<div class=\"refsect1\">\n<a name=\"cockpit-conf-also\"></a><h2>SEE ALSO</h2>\n<p>\n      <span class=\"citerefentry\"><span class=\"refentrytitle\">cockpit-ws</span>(8)</span>\n    </p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/development.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Part III. Developer Guide</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"prev\" href=\"feature-ovirtvirtualmachines.html\" title=\"oVirt Virtual Machines\">\n<link rel=\"next\" href=\"embedding.html\" title=\"Embedding and Integrating Cockpit\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-ovirtvirtualmachines.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td> </td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"embedding.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"part\">\n<div class=\"titlepage\"><div><div><h1 class=\"title\">\n<a name=\"development\"></a>Part III. Developer Guide</h1></div></div></div>\n<div class=\"toc\">\n<p><b>Table of Contents</b></p>\n<dl class=\"toc\">\n<dt><span class=\"chapter\"><a href=\"embedding.html\">Embedding and Integrating Cockpit</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"embedding.html#embedding-full\">Embedding the Cockpit Interface</a></span></dt>\n<dt><span class=\"section\"><a href=\"embedding.html#embedding-components\">Integrating Cockpit Components into Web Applications</a></span></dt>\n<dt><span class=\"section\"><a href=\"embedding.html#embedding-deep\">Deep Integration</a></span></dt>\n<dt><span class=\"section\"><a href=\"embedding.html#embedding-cors\">Pinging Cockpit</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"packages.html\">Cockpit Packages</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"packages.html#package-layout\">Layout of Package Files</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-manifest\">Package Manifest</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-links\">Package Links and Paths</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-minified\">Content Negotiation</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-api\">Using Cockpit API</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-bridges\">Bridges for specific tasks</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-replace\">Replacing an existing package</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"urls.html\">Cockpit URLs</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"urls.html#urls-components\">Component URLs</a></span></dt>\n<dt><span class=\"section\"><a href=\"urls.html#urls-visible\">Visible URLs</a></span></dt>\n</dl></dd>\n<dt><span class=\"reference\"><a href=\"api-base1.html\">API: base1</a></span></dt>\n<dd><dl>\n<dt>\n<span class=\"refentrytitle\"><a href=\"api-cockpit.html\">cockpit.js</a></span><span class=\"refpurpose\"> — Basic cockpit API to interact with the system</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-dbus.html\">cockpit.js: DBus Client</a></span><span class=\"refpurpose\"> — DBus API communication</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-file.html\">cockpit.js: File Access</a></span><span class=\"refpurpose\"> — Reading, writing, and watching files.</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-http.html\">cockpit.js: HTTP Client</a></span><span class=\"refpurpose\"> — HTTP and REST API communication</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-spawn.html\">cockpit.js: Spawning Processes</a></span><span class=\"refpurpose\"> — Spawning processes or scripts</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-metrics.html\">cockpit.js: Metrics</a></span><span class=\"refpurpose\"> — Reading and streaming metric data</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-series-data.html\">cockpit.js: Series Data</a></span><span class=\"refpurpose\"> — Representing series data</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-channels.html\">cockpit.js: Raw Channels</a></span><span class=\"refpurpose\"> — Raw communication channels</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-location.html\">cockpit.js: Page Location and Jumping</a></span><span class=\"refpurpose\"> — Page location and navigation between components</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-locale.html\">cockpit.js: Localization</a></span><span class=\"refpurpose\"> — Localization and translations</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-error.html\">cockpit.js: Errors</a></span><span class=\"refpurpose\"> — Problem codes and messages</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-login.html\">cockpit.js: User Session</a></span><span class=\"refpurpose\"> — User information and login session state</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-util.html\">cockpit.js: Utilities</a></span><span class=\"refpurpose\"> — Various utility functions</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-cache.html\">cockpit.js: Object Cache</a></span><span class=\"refpurpose\"> — Caching and sharing data</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-manifest.html\">cockpit.js: Manifests</a></span><span class=\"refpurpose\"> — Manifest info</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"api-base1-patternfly.html\">patternfly.css</a></span><span class=\"refpurpose\"> — Patternfly standard style sheets</span>\n</dt>\n</dl></dd>\n<dt><span class=\"reference\"><a href=\"api-docker.html\">API: docker</a></span></dt>\n<dd><dl><dt>\n<span class=\"refentrytitle\"><a href=\"api-console-html.html\">console.html</a></span><span class=\"refpurpose\"> — Container console component</span>\n</dt></dl></dd>\n<dt><span class=\"reference\"><a href=\"api-shell.html\">API: shell</a></span></dt>\n<dd><dl><dt>\n<span class=\"refentrytitle\"><a href=\"api-shell-html.html\">index.html</a></span><span class=\"refpurpose\"> — Main cockpit shell, for a single machine</span>\n</dt></dl></dd>\n<dt><span class=\"reference\"><a href=\"api-system.html\">API: system</a></span></dt>\n<dd><dl>\n<dt>\n<span class=\"refentrytitle\"><a href=\"api-logs-html.html\">logs.html</a></span><span class=\"refpurpose\"> — System log component</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"api-terminal-html.html\">terminal.html</a></span><span class=\"refpurpose\"> — Server terminal component</span>\n</dt>\n</dl></dd>\n</dl>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/embedding.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Embedding and Integrating Cockpit</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"development.html\" title=\"Part III. Developer Guide\">\n<link rel=\"prev\" href=\"development.html\" title=\"Part III. Developer Guide\">\n<link rel=\"next\" href=\"packages.html\" title=\"Cockpit Packages\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"development.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"development.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"packages.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"embedding\"></a>Embedding and Integrating Cockpit</h2></div></div></div>\n<div class=\"toc\"><dl class=\"toc\">\n<dt><span class=\"section\"><a href=\"embedding.html#embedding-full\">Embedding the Cockpit Interface</a></span></dt>\n<dt><span class=\"section\"><a href=\"embedding.html#embedding-components\">Integrating Cockpit Components into Web Applications</a></span></dt>\n<dt><span class=\"section\"><a href=\"embedding.html#embedding-deep\">Deep Integration</a></span></dt>\n<dt><span class=\"section\"><a href=\"embedding.html#embedding-cors\">Pinging Cockpit</a></span></dt>\n</dl></div>\n<p>Cockpit can be embedded in other web applications either as a whole or specific\n    Cockpit components can be integrated.</p>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"embedding-full\"></a>Embedding the Cockpit Interface</h2></div></div></div>\n<p>Cockpit can be embedded into a larger web page as a frame. To embed\n      the entire Cockpit Window use the URI:\n      <code class=\"code\">https://server.example.com:9090/</code></p>\n<pre class=\"programlisting\">\n&lt;html&gt;\n  &lt;head&gt;\n    &lt;title&gt;Embedded Cockpit&lt;/title&gt;\n  &lt;/head&gt;\n  &lt;body&gt;\n    This is Cockpit.\n    &lt;br/&gt;\n    &lt;iframe width=\"800px\" height=\"600px\"\n            src=\"https://server.example.com:9090/\"/&gt;\n  &lt;/body&gt;\n&lt;/html&gt;\n</pre>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"embedding-components\"></a>Integrating Cockpit Components into Web Applications</h2></div></div></div>\n<p>Instead of embedding the entirety of Cockpit, you can integrate specific components.\n      Only those components explicitly documented as API should be integrated. Other components\n      can and will change regularly.</p>\n<p>The component will load from the server in question and a WebSocket connection\n      will be established with the server to relay the component's message stream.</p>\n<p>Cockpit components are HTML files contained in\n      <a class=\"link\" href=\"packages.html\" title=\"Cockpit Packages\">packages</a>. These can be placed in an iframe or web browser\n      window. Each documented and stable component has a well-known URL and these are documented\n      in the <a class=\"link\" href=\"development.html\" title=\"Part III. Developer Guide\">API reference</a>. Each component URL begins with the string\n      <code class=\"code\">/cockpit/@localhost/</code> followed a package name, and then the component itself.</p>\n<p>For example the\n      <a class=\"link\" href=\"api-terminal-html.html\" title=\"terminal.html\">terminal.html</a> in the\n      <a class=\"link\" href=\"api-system.html\" title=\"API: system\">system</a> package, has this URL:\n      <code class=\"code\">/cockpit/@localhost/system/terminal.html</code></p>\n<pre class=\"programlisting\">\n&lt;html&gt;\n  &lt;head&gt;\n    &lt;title&gt;Embedded Terminal&lt;/title&gt;\n  &lt;/head&gt;\n  &lt;body&gt;\n    This is a terminal.\n    &lt;br/&gt;\n    &lt;iframe width=\"800px\" height=\"600px\"\n      src=\"https://server.example.com:9090/cockpit/@localhost/system/terminal.html\"/&gt;\n  &lt;/body&gt;\n&lt;/html&gt;\n</pre>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"embedding-deep\"></a>Deep Integration</h2></div></div></div>\n<p>Most often <a class=\"link\" href=\"embedding.html#embedding-components\" title=\"Integrating Cockpit Components into Web Applications\">simple integration</a> will be used\n      to bring Cockpit components into web applications. However it is also possible to do deep\n      integration for embedders who wish to perform non-standard authentication with the server,\n      and relay the component's message stream to the server themselves.</p>\n<div class=\"warning\" style=\"margin-left: 0.5in; margin-right: 0.5in;\">\n<h3 class=\"title\">Warning</h3>\n<p>Deep integration capability is in heavy flux and is not yet documented.</p>\n</div>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"embedding-cors\"></a>Pinging Cockpit</h2></div></div></div>\n<p>When embedding Cockpit or integrating Cockpit components, it may be necessary to check\n      whether Cockpit is available on a server before proceeding.</p>\n<p>To do this perform a <code class=\"code\">/ping</code> request to Cockpit. This is a simple HTTP\n      GET request. It returns the following:</p>\n<pre class=\"programlisting\">\nGET: https://server.example.com:9090/ping\n200 OK: { \"service\": \"cockpit\" }\n</pre>\n<p>The <code class=\"code\">/ping</code> request allows\n      <a class=\"ulink\" href=\"https://en.wikipedia.org/wiki/Cross-origin_resource_sharing\" target=\"_top\">Cross Origin Resource Sharing</a>\n      headers and as such can be performed from Javascript code with any origin. The request can also be\n      made via plain HTTP without SSL. It is by design that no further information is present in the\n      response.</p>\n<p>A complete example of using <code class=\"code\">/ping</code> is available in the Cockpit sources in the\n      <code class=\"code\">/examples/ping-server/</code> directory.</p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-docker.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Docker</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-journal.html\" title=\"Journal\">\n<link rel=\"next\" href=\"feature-networkmanager.html\" title=\"NetworkManager\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-journal.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-networkmanager.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-docker\"></a>Docker</h2></div></div></div>\n<p>Cockpit can manage containers via <a class=\"ulink\" href=\"https://www.docker.com/\" target=\"_top\">Docker</a>.\n    This functionality is present in the Cockpit <span class=\"emphasis\"><em>docker</em></span> package.</p>\n<p>Cockpit communicates with the Docker daemon via its API via the\n    <code class=\"filename\">/var/run/docker.sock</code> unix socket. The Docker API\n    is root equivalent, and on a properly configured system, only <code class=\"code\">root</code>\n    can access the Docker API. If the currently logged in user is not <code class=\"code\">root</code>\n    then Cockpit will try to\n    <a class=\"link\" href=\"privileges.html\" title=\"Privileges and Permissions\">escalate the user's privileges</a> via Polkit\n    or sudo before connecting to the socket.</p>\n<p>Alternatively one may\n    <a class=\"ulink\" href=\"https://docs.docker.com/engine/installation/linux/rhel/#/create-a-docker-group\" target=\"_top\">create a <code class=\"code\">docker</code> unix group</a>. Anyone in that <code class=\"code\">docker</code> group can then access\n    the Docker API, and gain root privileges on the system. This\n    <a class=\"ulink\" href=\"https://docs.docker.com/engine/security/security/#docker-daemon-attack-surface\" target=\"_top\">impacts system security</a>\n    and is not recommended for general usage.</p>\n<p>Similar container functionality is available on the command line via the\n    <code class=\"filename\">docker</code> tool:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>sudo docker run -ti fedora /bin/bash</strong></span>\n[root@57625bc8787e /]#\n</pre>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-firewall.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Firewall</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-networkmanager.html\" title=\"NetworkManager\">\n<link rel=\"next\" href=\"feature-storaged.html\" title=\"storaged\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-networkmanager.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-storaged.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-firewall\"></a>Firewall</h2></div></div></div>\n<p>Cockpit uses <a class=\"ulink\" href=\"https://www.firewalld.org\" target=\"_top\">firewalld</a> to\n    interact with the system's firewall. No firewall configuration UI will be\n    shown if firewalld is not installed.</p>\n<p>Firewalld controls access to its APIs via PolicyKit. The user logged\n    into Cockpit needs to have the appropriate permissions to view or modify\n    the settings.</p>\n<p>Cockpit can currently only show, add, and remove predefined firewalld\n    services in the default zone.</p>\n<p>To perform similar tasks from the command line, use\n    <a class=\"ulink\" href=\"https://www.firewalld.org/documentation/man-pages/firewall-cmd.html\" target=\"_top\">firewalld-cmd</a>.\n    For example, to get the same list of allowed services that Cockpit\n    displays:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>sudo firewall-cmd --list-services</strong></span>\ndhcpv6-client samba-client mdns ssh cockpit\n</pre>\n<p>To enable an additional service, use:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>firewall-cmd --add-service pop3</strong></span>\nsuccess\n</pre>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-journal.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Journal</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-systemd.html\" title=\"systemd\">\n<link rel=\"next\" href=\"feature-docker.html\" title=\"Docker\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-systemd.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-docker.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-journal\"></a>Journal</h2></div></div></div>\n<p>The systemd journal provides Cockpit with indexed log data. This log data\n    is found on the Journal page, as well as in various other places when configuring\n    services, storage, networking etc.</p>\n<p>Cockpit accesses Journal data via the\n    <a class=\"ulink\" href=\"https://www.freedesktop.org/software/systemd/man/journalctl.html\" target=\"_top\"><code class=\"code\">journalctl</code></a>\n    command. Similar tasks can be performed at the command line:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>sudo journalctl -f -u docker</strong></span>\n...\n</pre>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-kubernetes.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Kubernetes</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-subscription.html\" title=\"Subscription Manager\">\n<link rel=\"next\" href=\"feature-machines.html\" title=\"Multiple Machines\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-subscription.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-machines.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-kubernetes\"></a>Kubernetes</h2></div></div></div>\n<div class=\"toc\"><dl class=\"toc\">\n<dt><span class=\"section\"><a href=\"feature-kubernetes.html#feature-kubernetes-package\">Used in a standard Cockpit session</a></span></dt>\n<dt><span class=\"section\"><a href=\"feature-kubernetes.html#feature-kubernetes-pod\">Used as a Kubernetes Pod</a></span></dt>\n<dt><span class=\"section\"><a href=\"feature-kubernetes.html#feature-openshift-pod\">Used as an Openshift Pod</a></span></dt>\n</dl></div>\n<p>Cockpit has a dashboard that interacts with a\n    <a class=\"ulink\" href=\"https://kubernetes.io/\" target=\"_top\">Kubernetes cluster</a> or an\n    <a class=\"ulink\" href=\"https://enterprise.openshift.com/\" target=\"_top\">Openshift v3 cluster</a>. This\n    functionality is in the Cockpit <span class=\"emphasis\"><em>kubernetes</em></span> package.</p>\n<p>The dashboard can either be deployed on kubernetes as a\n    <a class=\"ulink\" href=\"https://kubernetes.io/docs/user-guide/pods/\" target=\"_top\">container in a pod</a> or used\n    via a normal authenticated Cockpit session. Cockpit communicates with Kubernetes via its\n    REST API.</p>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"feature-kubernetes-package\"></a>Used in a standard Cockpit session</h2></div></div></div>\n<p>When the Kubernetes dashboard is used in a standard Cockpit login session, usually some\n      form of authentication is necessary to access the Kubernetes REST API.\n      Like the <code class=\"filename\">kubectl</code> and <code class=\"filename\">oc</code> commands, Cockpit uses\n      the authentication and server information in the <code class=\"code\">~/.kube/config</code> file for\n      the logged in user.</p>\n<p>If a user is able to use <code class=\"code\">kubectl</code> successfully when at their shell terminal,\n      then that same user will able to use Kubernetes dashboard when logged into Cockpit:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>kubectl get pods</strong></span>\nNAME                      READY     STATUS    RESTARTS   AGE\ndocker-registry-1-l4pyh   1/1       Running   10         23d\n...\n</pre>\n<p>When running Openshift one can use the <code class=\"code\">oc login</code> command to configure the\n      <code class=\"code\">~/.kube/config</code> file correctly. This in turn allows Cockpit to use that\n      login information.</p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"feature-kubernetes-pod\"></a>Used as a Kubernetes Pod</h2></div></div></div>\n<p>The Kubernetes dashboard can be deployed as a pod on Kubernetes requiring users\n      to log in using the standard standard authentication configured for access to its API.</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>wget https://raw.githubusercontent.com/cockpit-project/cockpit/master/containers/kubernetes-cockpit.json</strong></span>\n$ <span class=\"command\"><strong>kubectl create -f kubernetes-cockpit.json</strong></span>\n</pre>\n<p>This pod can be used on kubernetes that is configured with basic authentication. By\n      default the pod tries to access the kubernetes API securely and expects that the kubernetes\n      API server has been deployed with a CA, certificate files and service account key. In order\n      to change this behavior, edit the <code class=\"filename\">kubernetes-cockpit.json</code> and change the\n      <code class=\"literal\">KUBE_INSECURE</code> environment variable to <code class=\"literal\">true</code>.</p>\n<p>You can retrieve the address where you can access the dashboard via:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>kubectl get service kubernetes-cockpit</strong></span>\n</pre>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"feature-openshift-pod\"></a>Used as an Openshift Pod</h2></div></div></div>\n<p>The Kubernetes dashboard can be deployed as a pod on Openshift, and use Openshift\n      OAuth authentication. Running software on Openshift requires forethought, planning and\n      configuration. In particular, in order to run the admin interface as a pod you need\n      to first decide the host name that it will be accessible at. This is the host name part\n      of its URL.</p>\n<p>Next use the following commands to deploy the registry pod and service. You'll need\n      to have admin access to the Openshift cluster, as an OAuth client needs to be created.\n      Replace the <code class=\"literal\">XXX</code> with the host name you want to make the registry\n      accessible at. In addition replace <code class=\"literal\">YYY</code> with the host name of the\n      Openshift API server.</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>wget https://raw.githubusercontent.com/cockpit-project/cockpit/master/containers/openshift-cockpit.template</strong></span>\n$ <span class=\"command\"><strong>oc process -f openshift-cockpit.template -p COCKPIT_KUBE_URL=https://XXX -p OPENSHIFT_OAUTH_PROVIDER_URL=https://YYY:8443 | oc create -f -</strong></span>\n</pre>\n<p>You can retrieve the address where you can access the dashboard via:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>oc get service openshift-cockpit</strong></span>\n</pre>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-machines.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Multiple Machines</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-kubernetes.html\" title=\"Kubernetes\">\n<link rel=\"next\" href=\"feature-selinux.html\" title=\"SELinux Policy\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-kubernetes.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-selinux.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-machines\"></a>Multiple Machines</h2></div></div></div>\n<p>Cockpit can connect to multiple machines from a single Cockpit session.\n    These are listed on the <span class=\"emphasis\"><em>Machines</em></span> dashboard.</p>\n<p>These additional machines are accessed via SSH from the machine that\n    the first machine connected to, and are\n    <a class=\"link\" href=\"authentication.html\" title=\"Cockpit Authentication\">authenticated</a> with the logged in\n    user's password and/or SSH keys.</p>\n<p>Using SSH keys is only supported when the system has the\n    necessary APIs in libssh.</p>\n<p>SSH host keys are stored in\n    <code class=\"filename\">/etc/ssh/ssh_known_hosts</code>.</p>\n<p>The machine data is stored in\n    <code class=\"filename\">/etc/cockpit/machines.d/*.json</code>.  Settings in\n    lexicographically later files amend or override settings in earlier ones.\n    Cockpit itself writes into <code class=\"filename\">99-webui.json</code>; packages or\n    admins who want to pre-configure machines should ship files like\n    <code class=\"filename\">05-mymachine.json</code> so that changes from the web\n    interface override the pre-configured files.</p>\n<p>Each JSON file contains an object that maps machine IDs to objects that\n    define the properties of that machine. The ID can be a human readable name\n    or an IP address or any other unique value, and is shown in the web\n    interface until conneting to it the first time, at which point the web\n    interface will show the machine's host name.</p>\n<p>The following properties are recognized:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"address\"</code></span></p></td>\n<td><p><span class=\"emphasis\"><em>(string, mandatory)</em></span> IP address or\n          DNS name of the machine</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"visible\"</code></span></p></td>\n<td><p><span class=\"emphasis\"><em>(boolean, optional)</em></span> If\n          <code class=\"code\">true</code>, the machine will be displayed and\n          available for managing with Cockpit. If <code class=\"code\">false</code> (the\n          default), it will not be displayed, but still taken into account for\n          type-ahead search when adding new machines in the web\n          interface.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"user\"</code></span></p></td>\n<td><p><span class=\"emphasis\"><em>(string, optional)</em></span> User name on the remote machine.\n          When not given, Cockpit will default to the user name that was being\n          used to log into Cockpit itself.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"port\"</code></span></p></td>\n<td><p><span class=\"emphasis\"><em>(integer, optional)</em></span> ssh port of the\n          remote machine. When not given, the default port 22 is used.\n          </p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"code\">\"color\"</code></span></p></td>\n<td><p><span class=\"emphasis\"><em>(string, optional)</em></span> Color to\n          assign to the machine label in the web interface. This can be either given as\n          <code class=\"code\">rgb(r_value, g_value, b_value)</code> with each value being an\n          integer between 0 and 255, or as a color name like <code class=\"code\">yellow</code>.\n          When not given, Cockpit will assign an unused color automatically.\n          </p></td>\n</tr>\n</tbody>\n</table></div>\n<p>Example:</p>\n<pre class=\"programlisting\">\n{\n    \"web server\": {\n        \"address\": \"192.168.2.4\",\n        \"visible\": true,\n        \"color\": \"rgb(100, 200, 0)\",\n        \"user\": \"admin\"\n    },\n    \"192.168.2.1\": {\n        \"address\": \"192.168.2.1\",\n        \"port\": 2222,\n        \"visible\": true,\n        \"color\": \"green\"\n    }\n}</pre>\n<p>There is currently no command line interface for adding and/or removing\n    machines from the dashboard.</p>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-networkmanager.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>NetworkManager</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-docker.html\" title=\"Docker\">\n<link rel=\"next\" href=\"feature-firewall.html\" title=\"Firewall\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-docker.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-firewall.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-networkmanager\"></a>NetworkManager</h2></div></div></div>\n<p>If available on the system, Cockpit uses\n    <a class=\"ulink\" href=\"https://wiki.gnome.org/Projects/NetworkManager\" target=\"_top\">NetworkManager</a>\n    and the DBus APIs it provides to interact with the system's network configuration.</p>\n<p>For non root users, NetworkManager controls access to its APIs via\n    <a class=\"link\" href=\"privileges.html\" title=\"Privileges and Permissions\">Policy Kit</a> and a user logged into Cockpit will have\n    the same permissions as they do from the command line.</p>\n<p>To perform similar tasks from the command line, use the\n    <a class=\"ulink\" href=\"https://fedoraproject.org/wiki/Networking/CLI\" target=\"_top\">nmcli</a> command:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>nmcli general status</strong></span>\nSTATE      CONNECTIVITY  WIFI-HW  WIFI     WWAN-HW  WWAN\nconnected  full          enabled  enabled  enabled  enabled\n</pre>\n<p>Devices marked as \"not managed\" with the <code class=\"code\">NM_CONTROLLED=no</code> setting\n    will not be displayed in the interface.</p>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-ovirtvirtualmachines.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>oVirt Virtual Machines</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-virtualmachines.html\" title=\"Virtual Machines\">\n<link rel=\"next\" href=\"development.html\" title=\"Part III. Developer Guide\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-virtualmachines.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"development.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-ovirtvirtualmachines\"></a>oVirt Virtual Machines</h2></div></div></div>\n<p>Cockpit can connect to <a class=\"ulink\" href=\"https://ovirt.org/\" target=\"_top\">oVirt</a> REST API to extend\n        <a class=\"link\" href=\"feature-virtualmachines.html\" title=\"Virtual Machines\">Virtual Machines</a> for oVirt-specifics, namely\n        </p>\n<div class=\"itemizedlist\"><ul class=\"itemizedlist\" style=\"list-style-type: disc; \">\n<li class=\"listitem\"><p>Active operations</p></li>\n<li class=\"listitem\"><p>Extended virtual machine's details</p></li>\n<li class=\"listitem\"><p>Migration</p></li>\n<li class=\"listitem\"><p>VDSM configuration</p></li>\n</ul></div>\n<p>\n    </p>\n<p>Required oVirt version: <span class=\"emphasis\"><em>4.1.0</em></span></p>\n<p>The machine running Cockpit must be configured as a <span class=\"emphasis\"><em>host within the oVirt cluster.</em></span></p>\n<p>CORS (Cross Origin Resource Sharing) must be enabled on oVirt engine (not done by default):\n        </p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>ssh root@[ENGINE_FQDN]</strong></span> # log as `root` user in the oVirt engine machine\n# <span class=\"command\"><strong>engine-config -s CORSSupport=true</strong></span> # to turn on the CORS support for REST API\n# <span class=\"command\"><strong>engine-config -s CORSAllowDefaultOrigins=true</strong></span> # to allow CORS for all configured hosts\n# <span class=\"command\"><strong>systemctl restart ovirt-engine</strong></span> # to take effect\n        </pre>\n<p>\n    </p>\n<p>The <span class=\"emphasis\"><em>URL of oVirt</em></span> (or RHV - Red Hat Virtualization) API server must be manually provided,\n        since it can't be determined automatically from a host.</p>\n<p>To do so, please <span class=\"emphasis\"><em>either</em></span>\n        </p>\n<div class=\"itemizedlist\"><ul class=\"itemizedlist\" style=\"list-style-type: disc; \">\n<li class=\"listitem\"><p>log into Cockpit as <span class=\"emphasis\"><em>root</em></span></p></li>\n<li class=\"listitem\"><p>visit <span class=\"emphasis\"><em>Virtual Machines</em></span> page</p></li>\n<li class=\"listitem\"><p>provide <span class=\"emphasis\"><em>oVirt's engine URL</em></span> within the shown dialog</p></li>\n</ul></div>\n<p>\n        <span class=\"emphasis\"><em>or</em></span>\n        </p>\n<div class=\"itemizedlist\"><ul class=\"itemizedlist\" style=\"list-style-type: disc; \"><li class=\"listitem\">\n<p>run as <span class=\"emphasis\"><em>root</em></span> in shell:</p>\n<pre class=\"programlisting\">\n# <span class=\"command\"><strong>/usr/share/cockpit/ovirt/install.sh https://[FQDN]/ovirt-engine</strong></span>\n                </pre>\n</li></ul></div>\n<p>\n    </p>\n<p>By any of the actions above, following files are generated:\n        </p>\n<div class=\"itemizedlist\"><ul class=\"itemizedlist\" style=\"list-style-type: disc; \">\n<li class=\"listitem\"><p>/etc/cockpit/machines-ovirt.config - feel free to adjust</p></li>\n<li class=\"listitem\"><p>/usr/share/cockpit/ovirt/override.json - to ease Content Security Policy towards oVirt's REST API</p></li>\n</ul></div>\n<p>\n    </p>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-packagekit.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Package Updates</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-sosreport.html\" title=\"SOS Report\">\n<link rel=\"next\" href=\"feature-virtualmachines.html\" title=\"Virtual Machines\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-sosreport.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-virtualmachines.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-packagekit\"></a>Package Updates</h2></div></div></div>\n<p>Cockpit uses the <a class=\"ulink\" href=\"https://www.freedesktop.org/software/PackageKit/gtk-doc/api-reference.html\" target=\"_top\">PackageKit</a>\n    D-Bus API to get information about available package updates and to apply them, in an Operating System independent manner.</p>\n<p>To perform similar tasks from the command line, use the\n    <a class=\"ulink\" href=\"https://www.freedesktop.org/software/PackageKit/pk-using.html\" target=\"_top\">pkcon</a> command:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>pkcon refresh</strong></span>\n\n$ <span class=\"command\"><strong>pkcon get-updates</strong></span>\nAvailable  sudo-1.8.20p2-1.fc26.x86_64 (updates-testing)\n    Allows restricted root access for specified users\nAvailable  vim-filesystem-2:8.0.617-1.fc26.x86_64 (updates-testing)\n    VIM filesystem layout\nAvailable  vim-minimal-2:8.0.617-1.fc26.x86_64 (updates-testing)\n    A minimal version of the VIM editor\n\n$ <span class=\"command\"><strong>pkcon get-update-detail sudo</strong></span>\nDetails about the update:6.x86_64 [fedora]\n Package: sudo-1.8.20p2-1.fc26.x86_64\n Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1452941\n Update text: - update to 1.8.20p2\n    - added sudo package to dnf/yum protected packages\n\n$ <span class=\"command\"><strong>pkcon update</strong></span>\nThe following packages have to be updated:\n sudo-1.8.20p2-1.fc26.x86_64\tAllows restricted root access for specified users\n vim-filesystem-2:8.0.617-1.fc26.x86_64\tVIM filesystem layout\n vim-minimal-2:8.0.617-1.fc26.x86_64\tA minimal version of the VIM editor\nProceed with changes? [N/y] y\n[...]\n</pre>\n<p>Of course you can also use your Operating System specific commands for that, such as\n  <span class=\"command\"><strong>dnf updateinfo info</strong></span> on Fedora or\n  <span class=\"command\"><strong>sudo apt upgrade</strong></span> on Debian.</p>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-pcp.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>PCP</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-terminal.html\" title=\"Terminal\">\n<link rel=\"next\" href=\"feature-subscription.html\" title=\"Subscription Manager\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-terminal.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-subscription.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-pcp\"></a>PCP</h2></div></div></div>\n<p>If available, Cockpit uses the\n    <a class=\"ulink\" href=\"https://pcp.io/\" target=\"_top\">Performance Co-Pilot</a> framework to\n    gather metrics data about the system. This data is used to display graphs.\n    Cockpit can use the PCP logging feature to display archived data about the\n    system from a different point in time. If PCP is not available, then Cockpit\n    gathers the metrics data itself, but archival features are not available.</p>\n<p>Whether or not metrics are archived depends on whether the\n    <code class=\"code\">pmlogger.service</code> and <code class=\"code\">pmcd.service</code> systemd units\n    are running or not.  The \"Store Performance Data\" button in Cockpit\n    will enable and start these services.</p>\n<p>To see similar metrics data from the command line, you can use tools like\n    <a class=\"ulink\" href=\"https://pcp.io/books/PCP_UAG/html/LE38515-PARENT.html#LE91266-PARENT\" target=\"_top\"><code class=\"code\">pmstat</code></a>\n    or <a class=\"ulink\" href=\"https://pcp.io/books/PCP_UAG/html/LE60452-PARENT.html\" target=\"_top\"><code class=\"code\">pminfo</code></a>:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>pmstat</strong></span>\n@ Sat Sep 26 15:30:10 2015\n loadavg                      memory      swap        io    system         cpu\n   1 min   swpd   free   buff  cache   pi   po   bi   bo   in   cs  us  sy  id\n    4.19      0 20710m 605148  6450m    0    0    0 2548 5688  14K  19   3  76\n...\n</pre>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-realmd.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>realmd</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-users.html\" title=\"User Tools\">\n<link rel=\"next\" href=\"feature-terminal.html\" title=\"Terminal\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-users.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-terminal.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-realmd\"></a>realmd</h2></div></div></div>\n<p>If available on the system, Cockpit uses\n    <a class=\"ulink\" href=\"https://www.freedesktop.org/software/realmd/\" target=\"_top\">realmd</a>\n    and the DBus APIs it provides to configure the system's Active Directory\n    or IPA domain membership.</p>\n<p>Not all systems can join all kinds of domains.  This depends\n    on the availability of the necessary client software.</p>\n<p>For non root users, realmd controls access to its APIs via\n    <a class=\"link\" href=\"privileges.html\" title=\"Privileges and Permissions\">Policy Kit</a> and a user logged into Cockpit will have\n    the same permissions as they do from the command line.</p>\n<p>To perform similar tasks from the command line, use the\n    <a class=\"ulink\" href=\"https://www.freedesktop.org/software/realmd/docs/realm.html\" target=\"_top\">realm</a> command:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>realm join example.com</strong></span>\nPassword for Administrator:\n</pre>\n<p>\n    <a class=\"ulink\" href=\"http://www.freedesktop.org/software/realmd/\" target=\"_top\">realmd</a>\n    sets up domain-qualified user names by default, i. e. login user names look like\n    \"<code class=\"code\">user@example.com</code>\". For using unqualified names (just\n    \"<code class=\"code\">user</code>\"), set the <code class=\"code\">fully-qualified-names</code> option in\n    <a class=\"ulink\" href=\"https://www.freedesktop.org/software/realmd/docs/realmd-conf.html\" target=\"_top\">/etc/realmd.conf</a>\n    before joining a domain.</p>\n<p>Cockpit requests an SSL certificate from the IPA server for\n    <span class=\"command\"><strong>cockpit-ws</strong></span> with the\n    <a class=\"ulink\" href=\"https://www.freeipa.org/page/Certmonger\" target=\"_top\">ipa-getcert</a> command.</p>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-selinux.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>SELinux Policy</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-machines.html\" title=\"Multiple Machines\">\n<link rel=\"next\" href=\"feature-tuned.html\" title=\"Tuned Profiles\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-machines.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-tuned.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-selinux\"></a>SELinux Policy</h2></div></div></div>\n<p>If present on the system Cockpit can set the SELinux mode to enforcing or permissive.\n    It can also use <code class=\"code\">setroubleshootd</code> to show audit issues and apply suggested\n    fixes.</p>\n<p>To perform similar tasks from the command line use the <code class=\"code\">setenforce</code> and\n    <code class=\"code\">sealert</code> tools.</p>\n<p>To clear out all the information that <code class=\"code\">setroubleshootd</code> tracks, you\n    can use a commands like:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>sudo killall setroubleshootd</strong></span>\n$ <span class=\"command\"><strong>sudo rm -rf /var/lib/setroubleshoot/*</strong></span>\n</pre>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-sosreport.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>SOS Report</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-tuned.html\" title=\"Tuned Profiles\">\n<link rel=\"next\" href=\"feature-packagekit.html\" title=\"Package Updates\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-tuned.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-packagekit.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-sosreport\"></a>SOS Report</h2></div></div></div>\n<p>If present on the system Cockpit can use <code class=\"code\">sosreport</code> to collect system configuration and diagnostic information.</p>\n<p>If <code class=\"code\">sosreport</code> is not found on an Atomic system, cockpit will attempt to run <code class=\"code\">sosreport</code> in the <code class=\"code\">rhel7/support-tools</code> docker container.</p>\n<p>\n    To perform similar tasks from the command line, use the <code class=\"code\">sosreport</code> command.</p>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-storaged.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>storaged</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-firewall.html\" title=\"Firewall\">\n<link rel=\"next\" href=\"feature-users.html\" title=\"User Tools\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-firewall.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-users.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-storaged\"></a>storaged</h2></div></div></div>\n<p>If available on the system, Cockpit uses <a class=\"ulink\" href=\"https://github.com/storaged-project/storaged/\" target=\"_top\"><code class=\"code\">storaged</code></a>\n    to configure and monitor storage, disks, mounts etc. on the\n    system. This functionality is present in the Cockpit\n    <span class=\"emphasis\"><em>storaged</em></span> package.</p>\n<p>The <code class=\"code\">storaged</code> project is originally based on a project called\n    <a class=\"ulink\" href=\"https://www.freedesktop.org/wiki/Software/udisks/\" target=\"_top\"><code class=\"code\">udisks</code></a>\n    and added support for many more features such as\n    <a class=\"ulink\" href=\"https://en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)\" target=\"_top\">LVM</a>,\n    <a class=\"ulink\" href=\"https://en.wikipedia.org/wiki/ISCSI\" target=\"_top\">iSCSI</a>,\n    <a class=\"ulink\" href=\"https://en.wikipedia.org/wiki/Linux_DM_Multipath\" target=\"_top\">Multipath</a>, and\n    <a class=\"ulink\" href=\"https://btrfs.wiki.kernel.org/index.php/Main_Page\" target=\"_top\">BTRFS</a>.\n    The same tools and backwards compatible API are available between <code class=\"code\">storaged</code>\n    and <code class=\"code\">udisks</code> the projects. Cockpit can use <code class=\"code\">udisks</code> but disables\n    many of it's storage related features, including updating <code class=\"code\">/etc/fstab</code>\n    and <code class=\"code\">/etc/crypttab</code> for stability reasons.</p>\n<p>For non root users, storaged controls access to its APIs via\n    <a class=\"link\" href=\"privileges.html\" title=\"Privileges and Permissions\">Policy Kit</a> and a user logged into Cockpit will have\n    the same permissions as they do from the command line.</p>\n<p>To perform similar tasks from the command line, use the <code class=\"code\">storagedctl</code> command:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>udisksctl dump</strong></span>\n...\n</pre>\n<p>To perform LVM tasks, you may use the various LVM commands, such as\n    <code class=\"code\">vgcreate</code>, <code class=\"code\">lvresize</code> and so on. Cockpit will detect such changes\n    made at the command line.</p>\n<p>Cockpit recognizes devices with multiple paths and can start\n    the <code class=\"code\">multipathd</code> service in case it is not running.  On\n    the command line, you can control multipath features with the\n    <code class=\"code\">mpathconf</code>, <code class=\"code\">multipathd</code>, and\n    <code class=\"code\">multipath</code> commands.</p>\n<p>To manage iSCSI initiators from the command line, you can use\n    <code class=\"code\">iscsiadm</code> and related tools.</p>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-subscription.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Subscription Manager</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-pcp.html\" title=\"PCP\">\n<link rel=\"next\" href=\"feature-kubernetes.html\" title=\"Kubernetes\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-pcp.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-kubernetes.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-subscription\"></a>Subscription Manager</h2></div></div></div>\n<p>Cockpit can use\n    <a class=\"ulink\" href=\"https://www.candlepinproject.org/\" target=\"_top\">Subscription Manager</a> to join the\n    attach the machine to a subscription, if the operating system (such as RHEL) requires this. This\n    functionality is in the Cockpit <span class=\"emphasis\"><em>subscriptions</em></span> package.</p>\n<p>Subscription Manager limits its use to root only. Therefore if a non-root user\n    is logged into Cockpit, Cockpit tries to <a class=\"link\" href=\"privileges.html\" title=\"Privileges and Permissions\">escalate privileges</a>\n    to root in order to access subscription information or make changes.</p>\n<p>To perform similar tasks from the command line, use the\n    <a class=\"ulink\" href=\"https://linux.die.net/man/8/subscription-manager\" target=\"_top\"><code class=\"code\">subscription-manager</code></a>\n    tool:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>sudo subscription-manager status</strong></span>\n+-------------------------------------------+\n   System Status Details\n+-------------------------------------------+\n...\n</pre>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-systemd.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>systemd</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"next\" href=\"feature-journal.html\" title=\"Journal\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"features.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-journal.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-systemd\"></a>systemd</h2></div></div></div>\n<p>Cockpit uses\n    <a class=\"ulink\" href=\"https://www.freedesktop.org/wiki/Software/systemd/\" target=\"_top\">systemd</a>\n    and the DBus APIs it provides to configure and monitor core aspects of the system.\n    Use of alternate system APIs are not currently implemented.</p>\n<p>For non root users, systemd controls access to its APIs via\n    <a class=\"link\" href=\"privileges.html\" title=\"Privileges and Permissions\">Policy Kit</a> and a user logged into Cockpit will have\n    the same permissions as they do from the command line.</p>\n<p>Cockpit retrieves information about the host and changes the hostname via the\n    <code class=\"code\">hostnamed</code> daemon. To perform similar tasks from the command line use the\n    <a class=\"ulink\" href=\"https://www.freedesktop.org/software/systemd/man/hostnamectl.html\" target=\"_top\"><code class=\"code\">hostnamectl</code></a>\n    command:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>hostnamectl</strong></span>\n   Static hostname: pink.example.com\n   Pretty hostname: Pink\n         Icon name: computer-desktop\n           Chassis: desktop\n        Machine ID: ef00b79be229463cbb844c3e715de96c\n           Boot ID: 934983d64d34465cb5a8383b5a89ad8c\n  Operating System: Fedora 22 (Twenty Two)\n       CPE OS Name: cpe:/o:fedoraproject:fedora:22\n            Kernel: Linux 4.0.4-301.fc22.x86_64\n      Architecture: x86-64\n</pre>\n<p>Cockpit configures the system time and time zone via the <code class=\"code\">timedated</code> daemon.\n    To perform similar tasks from the command line use the\n    <a class=\"ulink\" href=\"https://www.freedesktop.org/software/systemd/man/timedatectl.html\" target=\"_top\"><code class=\"code\">timedatectl</code></a>\n    command:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>timedatectl list-timezones</strong></span>\nAfrica/Abidjan\nAfrica/Accra\nAfrica/Addis_Ababa\nAfrica/Algiers\n...\n</pre>\n<p>Cockpit can manage the list of NTP servers used by\n    <code class=\"code\">systemd-timesyncd</code> by putting its own file into\n    <code class=\"code\">/etc/systemd/timesyncd.conf.d/</code>.  Note that\n    <code class=\"code\">systemd-timesyncd</code> is not always enabled, depending on\n    the configuration of the machine.  In that case, Cockpit disabled the\n    UI for managing the list of NTP servers. In some cases use of\n    <code class=\"code\">ntpd</code> can cause the <code class=\"code\">timedated</code> daemon to\n    behave inconsistently with regards to time synchronization.</p>\n<p>Cockpit restarts or powers down the machine by using the\n    <a class=\"ulink\" href=\"https://www.freedesktop.org/software/systemd/man/shutdown.html\" target=\"_top\"><code class=\"code\">shutdown</code></a>\n    command. To perform similar tasks from the command line, run it directly:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>sudo shutdown +15</strong></span>\nShutdown scheduled for Sa 2015-09-26 15:49:40 CEST, use 'shutdown -c' to cancel.\n</pre>\n<p>Cockpit manages system services and sockets via systemd. To perform similar tasks from the\n    command line use the\n    <a class=\"ulink\" href=\"https://www.freedesktop.org/software/systemd/man/systemctl.html\" target=\"_top\"><code class=\"code\">systemctl</code></a>\n    command:</p>\n<pre class=\"programlisting\">\n$ <span class=\"command\"><strong>systemctl status cockpit</strong></span>\n● cockpit.service - Cockpit Web Service\n   Loaded: loaded (/usr/lib/systemd/system/cockpit.service; static; vendor preset: disabled)\n  Drop-In: /etc/systemd/system/cockpit.service.d\n           └─debug.conf\n   Active: active (running) since Sa 2015-09-26 13:28:02 CEST; 2h 7min ago\n     Docs: man:cockpit-ws(8)\n Main PID: 6957 (cockpit-ws)\n   Memory: 1.8M\n   CGroup: /system.slice/cockpit.service\n           ├─ 6957 /usr/libexec/cockpit-ws\n           └─29598 /usr/bin/ssh-agent\n</pre>\n<p>In order to customize who can perform various actions in system,\n    <a class=\"link\" href=\"privileges.html#privileges-polkit\" title=\"Customizing Polkit Privileges\">create polkit rules</a> with the following\n    actions and details:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">org.freedesktop.systemd1.manage-units</code></span></p></td>\n<td><p>Permission to manage system services or other units.\n        Details available: <code class=\"code\">unit</code>, <code class=\"code\">verb</code></p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">org.freedesktop.systemd1.manage-unit-files</code></span></p></td>\n<td><p>Permission to manage system services or other unit files.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">org.freedesktop.systemd1.reload-daemon</code></span></p></td>\n<td><p>Permission to reload the systemd state.</p></td>\n</tr>\n</tbody>\n</table></div>\n<p>For example, placing the following polkit rule to\n    <code class=\"filename\">/etc/polkit-1.rules.d/10-http.rule</code> allows all users in the\n    <code class=\"code\">operators</code> group start, stop, and restart the Apache HTTP service:</p>\n<pre class=\"programlisting\">\npolkit.addRule(function(action, subject) {\n    if (action.id == \"org.freedesktop.systemd1.manage-units\") {\n        if (subject.isInGroup(\"operators\") &amp;&amp; action.lookup(\"unit\") == \"httpd.service\") {\n            var verb = action.lookup(\"verb\");\n            if (verb == \"start\" || verb == \"stop\" || verb == \"restart\") {\n                return polkit.Result.YES;\n            }\n        }\n    }\n});\n</pre>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-terminal.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Terminal</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-realmd.html\" title=\"realmd\">\n<link rel=\"next\" href=\"feature-pcp.html\" title=\"PCP\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-realmd.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-pcp.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-terminal\"></a>Terminal</h2></div></div></div>\n<p>Cockpit provides a standard shell in a terminal. This shell and the\n    processes running in it have the <a class=\"link\" href=\"privileges.html\" title=\"Privileges and Permissions\">same privileges</a>\n    as if the user had logged in via SSH.</p>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-tuned.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Tuned Profiles</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-selinux.html\" title=\"SELinux Policy\">\n<link rel=\"next\" href=\"feature-sosreport.html\" title=\"SOS Report\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-selinux.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-sosreport.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-tuned\"></a>Tuned Profiles</h2></div></div></div>\n<p>If present on the system Cockpit can use Tuned and the DBUS API it provides to set system performance profiles.\n    To perform similar tasks from the command line, use the <code class=\"code\">tuned-adm</code> command.</p>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-users.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>User Tools</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-storaged.html\" title=\"storaged\">\n<link rel=\"next\" href=\"feature-realmd.html\" title=\"realmd\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-storaged.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-realmd.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-users\"></a>User Tools</h2></div></div></div>\n<p>Cockpit uses the usual tools to create and modify local user accounts.\n    Examples are <code class=\"code\">useradd</code>, <code class=\"code\">usermod</code> and <code class=\"code\">passwd</code>.\n    These same tools are available for use on the command line.</p>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/feature-virtualmachines.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Virtual Machines</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"prev\" href=\"feature-packagekit.html\" title=\"Package Updates\">\n<link rel=\"next\" href=\"feature-ovirtvirtualmachines.html\" title=\"oVirt Virtual Machines\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"feature-packagekit.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"features.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-ovirtvirtualmachines.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"feature-virtualmachines\"></a>Virtual Machines</h2></div></div></div>\n<div class=\"toc\"><dl class=\"toc\">\n<dt><span class=\"section\"><a href=\"feature-virtualmachines.html#feature-virtualmachines-nestedvirtualization\">Nested Virtualization</a></span></dt>\n<dt><span class=\"section\"><a href=\"feature-virtualmachines.html#feature-virtualmachines-systemaccess\">Managing VMs on system connection</a></span></dt>\n<dt><span class=\"section\"><a href=\"feature-virtualmachines.html#feature-virtualmachines-extending\">Extensions</a></span></dt>\n</dl></div>\n<p>Cockpit can manage virtual machines running on the host.\n        These can be accessed from menu via <span class=\"emphasis\"><em>Virtual Machines</em></span></p>\n<p>Primary datasource is <a class=\"ulink\" href=\"https://www.qemu.org/\" target=\"_top\">QEMU</a> / <a class=\"ulink\" href=\"https://libvirt.org/\" target=\"_top\">Libvirt</a>,\n        access to Libvirtd is wrapped either by the <a class=\"ulink\" href=\"https://libvirt.org/virshcmdref.html\" target=\"_top\">virsh</a> tool or\n        <a class=\"ulink\" href=\"https://libvirt.org/dbus.html\" target=\"_top\">libvirt D-Bus API bindings</a>, depending if the latter is installed on\n        the system. If libvirt-dbus package is not available in your distribution's software repositories you can follow the instructions\n        <a class=\"ulink\" href=\"https://github.com/libvirt/libvirt-dbus/blob/master/README.md\" target=\"_top\">here</a> to install from sources.\n    </p>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"feature-virtualmachines-nestedvirtualization\"></a>Nested Virtualization</h2></div></div></div>\n<p>\n        In order to run <span class=\"emphasis\"><em>cockpit-machines</em></span> plugin inside a virtual machine\n        or run the tests for this component, you'll need nested KVM virtualization enabled\n        (refer <code class=\"code\">test/verify/nested-kvm</code> or\n        <a class=\"ulink\" href=\"https://fedoraproject.org/wiki/How_to_enable_nested_virtualization_in_KVM\" target=\"_top\">\n            How to enable nested virtualization in KVM</a> to get more information).\n    </p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"feature-virtualmachines-systemaccess\"></a>Managing VMs on system connection</h2></div></div></div>\n<p>\n        In order to manipulate as unprivileged user VMs on system connection through\n        <span class=\"emphasis\"><em>cockpit-machines</em></span> plugin using libvirt D-Bus provider you need to follow\n        the instructions specified <a class=\"ulink\" href=\"https://libvirt.org/dbus.html#usage\" target=\"_top\">here</a>.\n    </p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"feature-virtualmachines-extending\"></a>Extensions</h2></div></div></div>\n<p>\n            Base package <span class=\"emphasis\"><em>cockpit-machines</em></span> for management of virtual machines is based on Libvirt and\n            can be farther extended for features of higher level management applications (like oVirt) via concept\n            of providers (i.e. <a class=\"link\" href=\"feature-ovirtvirtualmachines.html\" title=\"oVirt Virtual Machines\">oVirt Virtual Machines</a>).\n        </p>\n<p>\n            Both <span class=\"emphasis\"><em>cockpit-machines-ovirt</em></span> and <span class=\"emphasis\"><em>cockpit-machines</em></span> RPM packages can be\n            installed together but only one of them can be loaded at a time depending on the <span class=\"emphasis\"><em>priority</em></span>\n            attribute set in <span class=\"emphasis\"><em>manifest.json</em></span> files.\n        </p>\n<p>\n            By default, <span class=\"emphasis\"><em>cockpit-machines-ovirt</em></span> takes precedence over <span class=\"emphasis\"><em>cockpit-machines</em></span>.\n        </p>\n<p>\n            New features for <span class=\"emphasis\"><em>cockpit-machines</em></span> should be only implemented for the componenent\n            using libvirt D-Bus.\n        </p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/features.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Part II. Feature Internals</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"prev\" href=\"privileges.html\" title=\"Privileges and Permissions\">\n<link rel=\"next\" href=\"feature-systemd.html\" title=\"systemd\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"privileges.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td> </td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"feature-systemd.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"part\">\n<div class=\"titlepage\"><div><div><h1 class=\"title\">\n<a name=\"features\"></a>Part II. Feature Internals</h1></div></div></div>\n<div class=\"toc\">\n<p><b>Table of Contents</b></p>\n<dl class=\"toc\">\n<dt><span class=\"chapter\"><a href=\"feature-systemd.html\">systemd</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-journal.html\">Journal</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-docker.html\">Docker</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-networkmanager.html\">NetworkManager</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-firewall.html\">Firewall</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-storaged.html\">storaged</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-users.html\">User Tools</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-realmd.html\">realmd</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-terminal.html\">Terminal</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-pcp.html\">PCP</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-subscription.html\">Subscription Manager</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-kubernetes.html\">Kubernetes</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"feature-kubernetes.html#feature-kubernetes-package\">Used in a standard Cockpit session</a></span></dt>\n<dt><span class=\"section\"><a href=\"feature-kubernetes.html#feature-kubernetes-pod\">Used as a Kubernetes Pod</a></span></dt>\n<dt><span class=\"section\"><a href=\"feature-kubernetes.html#feature-openshift-pod\">Used as an Openshift Pod</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"feature-machines.html\">Multiple Machines</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-selinux.html\">SELinux Policy</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-tuned.html\">Tuned Profiles</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-sosreport.html\">SOS Report</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-packagekit.html\">Package Updates</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-virtualmachines.html\">Virtual Machines</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"feature-virtualmachines.html#feature-virtualmachines-nestedvirtualization\">Nested Virtualization</a></span></dt>\n<dt><span class=\"section\"><a href=\"feature-virtualmachines.html#feature-virtualmachines-systemaccess\">Managing VMs on system connection</a></span></dt>\n<dt><span class=\"section\"><a href=\"feature-virtualmachines.html#feature-virtualmachines-extending\">Extensions</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"feature-ovirtvirtualmachines.html\">oVirt Virtual Machines</a></span></dt>\n</dl>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/gtk-doc.css",
    "content": ".synopsis, .classsynopsis\n{\n  /* tango:aluminium 1/2 */\n  background: #eeeeec;\n  border: solid 1px #d3d7cf;\n  padding: 0.5em;\n}\n.programlisting\n{\n  /* tango:sky blue 0/1 */\n  background: #e6f3ff;\n  border: solid 1px #729fcf;\n  padding: 0.5em;\n}\n.variablelist\n{\n  padding: 4px;\n  margin-left: 3em;\n}\n.variablelist td:first-child\n{\n  vertical-align: top;\n}\n\n@media screen {\n  sup a.footnote\n  {\n    position: relative;\n    top: 0em ! important;\n  }\n  /* this is needed so that the local anchors are displayed below the naviagtion */\n  div.footnote a[name], div.refnamediv a[name], div.refsect1 a[name], div.refsect2 a[name], div.index a[name], div.glossary a[name], div.sect1 a[name]\n  {\n    display: inline-block;\n    position: relative;\n    top:-5em;\n  }\n  /* this seems to be a bug in the xsl style sheets when generating indexes */\n  div.index div.index\n  {\n    top: 0em;\n  }\n  /* make space for the fixed navigation bar and add space at the bottom so that\n   * link targets appear somewhat close to top\n   */\n  body\n  {\n    padding-top: 3.2em;\n    padding-bottom: 20em;\n  }\n  /* style and size the navigation bar */\n  table.navigation#top\n  {\n    position: fixed;\n    /* tango:scarlet red 0/1 */\n    background: #ffe6e6;\n    border: solid 1px #ef2929;\n    margin-top: 0;\n    margin-bottom: 0;\n    top: 0;\n    left: 0;\n    height: 3em;\n    z-index: 10;\n  }\n  .navigation a, .navigation a:visited\n  {\n    /* tango:scarlet red 3 */\n    color: #a40000;\n  }\n  .navigation a:hover\n  {\n    /* tango:scarlet red 1 */\n    color: #ef2929;\n  }\n  td.shortcuts\n  {\n    /* tango:scarlet red 1 */\n    color: #ef2929;\n    font-size: 80%;\n    white-space: nowrap;\n  }\n}\n@media print {\n  table.navigation {\n    visibility: collapse;\n    display: none;\n  }\n  div.titlepage table.navigation {\n    visibility: visible;\n    display: table;\n    /* tango:scarlet red 0/1 */\n    background: #ffe6e6;\n    border: solid 1px #ef2929;\n    margin-top: 0;\n    margin-bottom: 0;\n    top: 0;\n    left: 0;\n    height: 3em;\n  }\n}\n\n.navigation .title\n{\n  font-size: 200%;\n}\n\ndiv.gallery-float\n{\n  float: left;\n  padding: 10px;\n}\ndiv.gallery-float img\n{\n  border-style: none;\n}\ndiv.gallery-spacer\n{\n  clear: both;\n}\n\na, a:visited\n{\n  text-decoration: none;\n  /* tango:sky blue 2 */\n  color: #3465a4;\n}\na:hover\n{\n  text-decoration: underline;\n  /* tango:sky blue 1 */\n  color: #729fcf;\n}\n\ndiv.table table\n{\n  border-collapse: collapse;\n  border-spacing: 0px;\n  /* tango:aluminium 3 */\n  border: solid 1px #babdb6;\n}\n\ndiv.table table td, div.table table th\n{\n  /* tango:aluminium 3 */\n  border: solid 1px #babdb6;\n  padding: 3px;\n  vertical-align: top;\n}\n\ndiv.table table th\n{\n  /* tango:aluminium 2 */\n  background-color: #d3d7cf;\n}\n\nhr\n{\n  /* tango:aluminium 3 */\n  color: #babdb6;\n  background: #babdb6;\n  border: none 0px;\n  height: 1px;\n  clear: both;\n}\n\n.footer\n{\n  padding-top: 3.5em;\n  /* tango:aluminium 3 */\n  color: #babdb6;\n  text-align: center;\n  font-size: 80%;\n}\n\n.warning\n{\n  /* tango:orange 0/1 */\n  background: #ffeed9;\n  border-color: #ffb04f;\n}\n.note\n{\n  /* tango:chameleon 0/0.5 */\n  background: #d8ffb2;\n  border-color: #abf562;\n}\n.note, .warning\n{\n  padding: 0.5em;\n  border-width: 1px;\n  border-style: solid;\n}\n.note h3, .warning h3\n{\n  margin-top: 0.0em\n}\n.note p, .warning p\n{\n  margin-bottom: 0.0em\n}\n\n/* blob links */\nh2 .extralinks, h3 .extralinks\n{\n  float: right;\n  /* tango:aluminium 3 */\n  color: #babdb6;\n  font-size: 80%;\n  font-weight: normal;\n}\n\n.annotation\n{\n  /* tango:aluminium 5 */\n  color: #555753;\n  font-size: 80%;\n  font-weight: normal;\n}\n\n/* code listings */\n\n.listing_code .programlisting .cbracket   { color: #a40000; } /* tango: scarlet red 3 */\n.listing_code .programlisting .comment    { color: #a1a39d; } /* tango: aluminium 4 */\n.listing_code .programlisting .function   { color: #000000; font-weight: bold; }\n.listing_code .programlisting .function a { color: #11326b; font-weight: bold; } /* tango: sky blue 4 */\n.listing_code .programlisting .keyword    { color: #4e9a06; } /* tango: chameleon 3  */\n.listing_code .programlisting .linenum    { color: #babdb6; } /* tango: aluminium 3 */\n.listing_code .programlisting .normal     { color: #000000; }\n.listing_code .programlisting .number     { color: #75507b; } /* tango: plum 2 */\n.listing_code .programlisting .preproc    { color: #204a87; } /* tango: sky blue 3  */\n.listing_code .programlisting .string     { color: #c17d11; } /* tango: chocolate 2 */\n.listing_code .programlisting .type       { color: #000000; }\n.listing_code .programlisting .type a     { color: #11326b; } /* tango: sky blue 4 */\n.listing_code .programlisting .symbol     { color: #ce5c00; } /* tango: orange 3 */\n\n.listing_frame {\n  /* tango:sky blue 1 */\n  border: solid 1px #729fcf;\n  padding: 0px;\n}\n\n.listing_lines, .listing_code {\n  margin-top: 0px;\n  margin-bottom: 0px;\n  padding: 0.5em;\n}\n.listing_lines {\n  /* tango:sky blue 0.5 */\n  background: #a6c5e3;\n  /* tango:aluminium 6 */\n  color: #2e3436;\n}\n.listing_code {\n  /* tango:sky blue 0 */\n  background: #e6f3ff;\n}\n.listing_code .programlisting {\n  /* override from previous */\n  border: none 0px;\n  padding: 0px;\n}\n.listing_lines pre, .listing_code pre {\n  margin: 0px;\n}\n"
  },
  {
    "path": "guide/195/guide.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Part I. Deployment Guide</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"prev\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"next\" href=\"cockpit-manual.html\" title=\"Manual pages\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"index.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td> </td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-manual.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"part\">\n<div class=\"titlepage\"><div><div><h1 class=\"title\">\n<a name=\"guide\"></a>Part I. Deployment Guide</h1></div></div></div>\n<div class=\"toc\">\n<p><b>Table of Contents</b></p>\n<dl class=\"toc\">\n<dt><span class=\"chapter\"><a href=\"cockpit-manual.html\">Manual pages</a></span></dt>\n<dd><dl>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit.conf.5.html\">cockpit.conf</a></span><span class=\"refpurpose\"> — Cockpit configuration file</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-ws.8.html\">cockpit-ws</a></span><span class=\"refpurpose\"> — Cockpit web service</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-desktop.1.html\">cockpit-desktop</a></span><span class=\"refpurpose\"> — Cockpit Desktop integration</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"remotectl.8.html\">remotectl</a></span><span class=\"refpurpose\"> — Remote Access Configuration</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-bridge.1.html\">cockpit-bridge</a></span><span class=\"refpurpose\"> — Cockpit Host Bridge</span>\n</dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"https.html\">SSL/TLS Usage</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"https.html#https-required\">HTTPS Requirement</a></span></dt>\n<dt><span class=\"section\"><a href=\"https.html#https-certificates\">Certificates</a></span></dt>\n<dt><span class=\"section\"><a href=\"https.html#https-compat\">SSL Versions and Ciphers</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"listen.html\">TCP Port and Address</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"listen.html#listen-systemd\">Cockpit systemd Socket</a></span></dt>\n<dt><span class=\"section\"><a href=\"listen.html#listen-selinux\">SELinux Port</a></span></dt>\n<dt><span class=\"section\"><a href=\"listen.html#listen-firewalld\">Firewalld Port</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"startup.html\">Start up</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"startup.html#startup-shutdown\">Process exit</a></span></dt>\n<dt><span class=\"section\"><a href=\"startup.html#startup-boot\">Boot start up</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"authentication.html\">Cockpit Authentication</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"authentication.html#initial-auth\">Primary server authentication</a></span></dt>\n<dt><span class=\"section\"><a href=\"authentication.html#secondary-auth\">Secondary server authentication</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"authentication.html#password\">Password</a></span></dt>\n<dt><span class=\"section\"><a href=\"authentication.html#kerberos\">Kerberos</a></span></dt>\n<dt><span class=\"section\"><a href=\"authentication.html#public-key\">Public key</a></span></dt>\n</dl></dd>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"sso.html\">Single Sign On</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"sso.html#sso-server\">Server Requirements</a></span></dt>\n<dt><span class=\"section\"><a href=\"sso.html#sso-client\">Client Requirements</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"privileges.html\">Privileges and Permissions</a></span></dt>\n<dd><dl><dt><span class=\"section\"><a href=\"privileges.html#privileges-polkit\">Customizing Polkit Privileges</a></span></dt></dl></dd>\n</dl>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/https.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>SSL/TLS Usage</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"guide.html\" title=\"Part I. Deployment Guide\">\n<link rel=\"prev\" href=\"cockpit-bridge.1.html\" title=\"cockpit-bridge\">\n<link rel=\"next\" href=\"listen.html\" title=\"TCP Port and Address\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-bridge.1.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"guide.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"listen.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"https\"></a>SSL/TLS Usage</h2></div></div></div>\n<div class=\"toc\"><dl class=\"toc\">\n<dt><span class=\"section\"><a href=\"https.html#https-required\">HTTPS Requirement</a></span></dt>\n<dt><span class=\"section\"><a href=\"https.html#https-certificates\">Certificates</a></span></dt>\n<dt><span class=\"section\"><a href=\"https.html#https-compat\">SSL Versions and Ciphers</a></span></dt>\n</dl></div>\n<p>Cockpit usually requires that web browsers communicate with it using HTTPS,\n    for security reasons.</p>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"https-required\"></a>HTTPS Requirement</h2></div></div></div>\n<p>Cockpit listens for both HTTP and HTTPS connections on the same port, by\n      default 9090. If an HTTP connection is made, Cockpit will redirect that\n      connection to HTTPS. There are some exceptions:</p>\n<div class=\"itemizedlist\"><ul class=\"itemizedlist\" style=\"list-style-type: disc; \">\n<li class=\"listitem\"><p>If an HTTP connection comes from <code class=\"code\">127.0.0.0/8</code>, then\n        Cockpit will allow communication without redirecting to HTTPS.</p></li>\n<li class=\"listitem\"><p>Certain URLs, like <code class=\"code\">/ping</code> are not required to use\n        HTTPS.</p></li>\n</ul></div>\n<p>This behavior can be overridden by setting the\n      <code class=\"code\">AllowUnencrypted</code> option in <code class=\"code\">cockpit.conf</code>.</p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"https-certificates\"></a>Certificates</h2></div></div></div>\n<p>Cockpit will load a certificate from the <code class=\"code\">/etc/cockpit/ws-certs.d</code>\n      directory. It will use the last file with a <code class=\"code\">.cert</code> extension in\n      alphabetical order. The <code class=\"literal\">.cert</code> file should contain at least two\n      OpenSSL style PEM blocks. First one or more <code class=\"literal\">BEGIN CERTIFICATE</code>\n      blocks for the server certificate and the intermediate certificate authorities\n      and a last one containing a <code class=\"literal\">BEGIN PRIVATE KEY</code> or similar.\n      The key may not be encrypted. For example:</p>\n<pre class=\"programlisting\">\n-----BEGIN CERTIFICATE-----\nMIIDUzCCAjugAwIBAgIJAPXW+CuNYS6QMA0GCSqGSIb3DQEBCwUAMD8xKTAnBgNV\nBAoMIGI0OGE2NGNkNmMwNTQ1YThhZTgxOTEzZDE5YmJjMmRjMRIwEAYDVQQDDAls\n...\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIIDUzCCAjugAwIBAgIJAPXW+CuNYS6QMA0GCSqGSIb3DQEBCwUAMD8xKTAnBgNV\nBAoMIGI0OGE2NGNkNmMwNTQ1YThhZTgxOTEzZDE5YmJjMmRjMRIwEAYDVQQDDAls\n...\n-----END CERTIFICATE-----\n-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCyOJ5garOYw0sm\n8TBCDSqQ/H1awGMzDYdB11xuHHsxYS2VepPMzMzryHR137I4dGFLhvdTvJUH8lUS\n...\n-----END PRIVATE KEY-----\n</pre>\n<p>If no certificate is found, a self-signed certificate is created and\n      stored in the <code class=\"filename\">0-self-signed.cert</code> file. On some\n      platforms, Cockpit will also generate a ca.crt in that directory, which\n      may be safely imported into client browsers.</p>\n<p>To check which certificate <code class=\"code\">cockpit-ws</code> will use run\n      the following command.</p>\n<pre class=\"programlisting\">\n$ sudo remotectl certificate\n</pre>\n<p>If using <code class=\"code\">certmonger</code> to manage certificates, following command can\n    be used to automatically prepare concatenated .cert file:</p>\n<pre class=\"programlisting\">\nCERT_FILE=/etc/pki/tls/certs/$(hostname).pem\nKEY_FILE=/etc/pki/tls/private/$(hostname).key\n\ngetcert request -f ${CERT_FILE} -k ${KEY_FILE} -D $(hostname --fqdn) -C \"sed -n w/etc/cockpit/ws-certs.d/50-from-certmonger.cert ${CERT_FILE} ${KEY_FILE}\"\n    </pre>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"https-compat\"></a>SSL Versions and Ciphers</h2></div></div></div>\n<p>By default Cockpit will only use modern secure ciphers and versions of TLS.\n      In particular SSL v3.0 is disabled by default, as well as the RC4 cipher.</p>\n<p>If you wish to enable these legacy protocols and algorithms you can do so\n      by passing an environment variable to cockpit-ws. Place the following in the\n      <code class=\"code\">/etc/systemd/system/cockpit.service.d/ssl.conf</code> file. Create the\n      file and directories in that path which don't already exist.</p>\n<pre class=\"programlisting\">\n[Service]\nEnvironment=G_TLS_GNUTLS_PRIORITY=NORMAL:%COMPAT\n</pre>\n<p>The environment variable value is a\n      <a class=\"ulink\" href=\"https://gnutls.org/manual/html_node/Priority-Strings.html#Priority-Strings\" target=\"_top\">GnuTLS priority string</a>.</p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/index.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Cockpit Guide</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"next\" href=\"guide.html\" title=\"Part I. Deployment Guide\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<div class=\"book\">\n<div class=\"titlepage\">\n<div>\n<div><table class=\"navigation\" id=\"top\" width=\"100%\" cellpadding=\"2\" cellspacing=\"0\"><tr><th valign=\"middle\"><p class=\"title\">Cockpit Guide</p></th></tr></table></div>\n<div><p class=\"releaseinfo\">Documentation for Cockpit 195\n --\n    latest version available at:\n      <a class=\"ulink\" href=\"https://cockpit-project.org/guide/latest\" target=\"_top\">https://cockpit-project.org/guide/latest/</a></p></div>\n</div>\n<hr>\n</div>\n<div class=\"toc\"><dl class=\"toc\">\n<dt><span class=\"part\"><a href=\"guide.html\">I. Deployment Guide</a></span></dt>\n<dd><dl>\n<dt><span class=\"chapter\"><a href=\"cockpit-manual.html\">Manual pages</a></span></dt>\n<dd><dl>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit.conf.5.html\">cockpit.conf</a></span><span class=\"refpurpose\"> — Cockpit configuration file</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-ws.8.html\">cockpit-ws</a></span><span class=\"refpurpose\"> — Cockpit web service</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-desktop.1.html\">cockpit-desktop</a></span><span class=\"refpurpose\"> — Cockpit Desktop integration</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"remotectl.8.html\">remotectl</a></span><span class=\"refpurpose\"> — Remote Access Configuration</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-bridge.1.html\">cockpit-bridge</a></span><span class=\"refpurpose\"> — Cockpit Host Bridge</span>\n</dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"https.html\">SSL/TLS Usage</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"https.html#https-required\">HTTPS Requirement</a></span></dt>\n<dt><span class=\"section\"><a href=\"https.html#https-certificates\">Certificates</a></span></dt>\n<dt><span class=\"section\"><a href=\"https.html#https-compat\">SSL Versions and Ciphers</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"listen.html\">TCP Port and Address</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"listen.html#listen-systemd\">Cockpit systemd Socket</a></span></dt>\n<dt><span class=\"section\"><a href=\"listen.html#listen-selinux\">SELinux Port</a></span></dt>\n<dt><span class=\"section\"><a href=\"listen.html#listen-firewalld\">Firewalld Port</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"startup.html\">Start up</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"startup.html#startup-shutdown\">Process exit</a></span></dt>\n<dt><span class=\"section\"><a href=\"startup.html#startup-boot\">Boot start up</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"authentication.html\">Cockpit Authentication</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"authentication.html#initial-auth\">Primary server authentication</a></span></dt>\n<dt><span class=\"section\"><a href=\"authentication.html#secondary-auth\">Secondary server authentication</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"authentication.html#password\">Password</a></span></dt>\n<dt><span class=\"section\"><a href=\"authentication.html#kerberos\">Kerberos</a></span></dt>\n<dt><span class=\"section\"><a href=\"authentication.html#public-key\">Public key</a></span></dt>\n</dl></dd>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"sso.html\">Single Sign On</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"sso.html#sso-server\">Server Requirements</a></span></dt>\n<dt><span class=\"section\"><a href=\"sso.html#sso-client\">Client Requirements</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"privileges.html\">Privileges and Permissions</a></span></dt>\n<dd><dl><dt><span class=\"section\"><a href=\"privileges.html#privileges-polkit\">Customizing Polkit Privileges</a></span></dt></dl></dd>\n</dl></dd>\n<dt><span class=\"part\"><a href=\"features.html\">II. Feature Internals</a></span></dt>\n<dd><dl>\n<dt><span class=\"chapter\"><a href=\"feature-systemd.html\">systemd</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-journal.html\">Journal</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-docker.html\">Docker</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-networkmanager.html\">NetworkManager</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-firewall.html\">Firewall</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-storaged.html\">storaged</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-users.html\">User Tools</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-realmd.html\">realmd</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-terminal.html\">Terminal</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-pcp.html\">PCP</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-subscription.html\">Subscription Manager</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-kubernetes.html\">Kubernetes</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"feature-kubernetes.html#feature-kubernetes-package\">Used in a standard Cockpit session</a></span></dt>\n<dt><span class=\"section\"><a href=\"feature-kubernetes.html#feature-kubernetes-pod\">Used as a Kubernetes Pod</a></span></dt>\n<dt><span class=\"section\"><a href=\"feature-kubernetes.html#feature-openshift-pod\">Used as an Openshift Pod</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"feature-machines.html\">Multiple Machines</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-selinux.html\">SELinux Policy</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-tuned.html\">Tuned Profiles</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-sosreport.html\">SOS Report</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-packagekit.html\">Package Updates</a></span></dt>\n<dt><span class=\"chapter\"><a href=\"feature-virtualmachines.html\">Virtual Machines</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"feature-virtualmachines.html#feature-virtualmachines-nestedvirtualization\">Nested Virtualization</a></span></dt>\n<dt><span class=\"section\"><a href=\"feature-virtualmachines.html#feature-virtualmachines-systemaccess\">Managing VMs on system connection</a></span></dt>\n<dt><span class=\"section\"><a href=\"feature-virtualmachines.html#feature-virtualmachines-extending\">Extensions</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"feature-ovirtvirtualmachines.html\">oVirt Virtual Machines</a></span></dt>\n</dl></dd>\n<dt><span class=\"part\"><a href=\"development.html\">III. Developer Guide</a></span></dt>\n<dd><dl>\n<dt><span class=\"chapter\"><a href=\"embedding.html\">Embedding and Integrating Cockpit</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"embedding.html#embedding-full\">Embedding the Cockpit Interface</a></span></dt>\n<dt><span class=\"section\"><a href=\"embedding.html#embedding-components\">Integrating Cockpit Components into Web Applications</a></span></dt>\n<dt><span class=\"section\"><a href=\"embedding.html#embedding-deep\">Deep Integration</a></span></dt>\n<dt><span class=\"section\"><a href=\"embedding.html#embedding-cors\">Pinging Cockpit</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"packages.html\">Cockpit Packages</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"packages.html#package-layout\">Layout of Package Files</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-manifest\">Package Manifest</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-links\">Package Links and Paths</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-minified\">Content Negotiation</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-api\">Using Cockpit API</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-bridges\">Bridges for specific tasks</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-replace\">Replacing an existing package</a></span></dt>\n</dl></dd>\n<dt><span class=\"chapter\"><a href=\"urls.html\">Cockpit URLs</a></span></dt>\n<dd><dl>\n<dt><span class=\"section\"><a href=\"urls.html#urls-components\">Component URLs</a></span></dt>\n<dt><span class=\"section\"><a href=\"urls.html#urls-visible\">Visible URLs</a></span></dt>\n</dl></dd>\n<dt><span class=\"reference\"><a href=\"api-base1.html\">API: base1</a></span></dt>\n<dd><dl>\n<dt>\n<span class=\"refentrytitle\"><a href=\"api-cockpit.html\">cockpit.js</a></span><span class=\"refpurpose\"> — Basic cockpit API to interact with the system</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-dbus.html\">cockpit.js: DBus Client</a></span><span class=\"refpurpose\"> — DBus API communication</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-file.html\">cockpit.js: File Access</a></span><span class=\"refpurpose\"> — Reading, writing, and watching files.</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-http.html\">cockpit.js: HTTP Client</a></span><span class=\"refpurpose\"> — HTTP and REST API communication</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-spawn.html\">cockpit.js: Spawning Processes</a></span><span class=\"refpurpose\"> — Spawning processes or scripts</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-metrics.html\">cockpit.js: Metrics</a></span><span class=\"refpurpose\"> — Reading and streaming metric data</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-series-data.html\">cockpit.js: Series Data</a></span><span class=\"refpurpose\"> — Representing series data</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-channels.html\">cockpit.js: Raw Channels</a></span><span class=\"refpurpose\"> — Raw communication channels</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-location.html\">cockpit.js: Page Location and Jumping</a></span><span class=\"refpurpose\"> — Page location and navigation between components</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-locale.html\">cockpit.js: Localization</a></span><span class=\"refpurpose\"> — Localization and translations</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-error.html\">cockpit.js: Errors</a></span><span class=\"refpurpose\"> — Problem codes and messages</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-login.html\">cockpit.js: User Session</a></span><span class=\"refpurpose\"> — User information and login session state</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-util.html\">cockpit.js: Utilities</a></span><span class=\"refpurpose\"> — Various utility functions</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-cache.html\">cockpit.js: Object Cache</a></span><span class=\"refpurpose\"> — Caching and sharing data</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"cockpit-manifest.html\">cockpit.js: Manifests</a></span><span class=\"refpurpose\"> — Manifest info</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"api-base1-patternfly.html\">patternfly.css</a></span><span class=\"refpurpose\"> — Patternfly standard style sheets</span>\n</dt>\n</dl></dd>\n<dt><span class=\"reference\"><a href=\"api-docker.html\">API: docker</a></span></dt>\n<dd><dl><dt>\n<span class=\"refentrytitle\"><a href=\"api-console-html.html\">console.html</a></span><span class=\"refpurpose\"> — Container console component</span>\n</dt></dl></dd>\n<dt><span class=\"reference\"><a href=\"api-shell.html\">API: shell</a></span></dt>\n<dd><dl><dt>\n<span class=\"refentrytitle\"><a href=\"api-shell-html.html\">index.html</a></span><span class=\"refpurpose\"> — Main cockpit shell, for a single machine</span>\n</dt></dl></dd>\n<dt><span class=\"reference\"><a href=\"api-system.html\">API: system</a></span></dt>\n<dd><dl>\n<dt>\n<span class=\"refentrytitle\"><a href=\"api-logs-html.html\">logs.html</a></span><span class=\"refpurpose\"> — System log component</span>\n</dt>\n<dt>\n<span class=\"refentrytitle\"><a href=\"api-terminal-html.html\">terminal.html</a></span><span class=\"refpurpose\"> — Server terminal component</span>\n</dt>\n</dl></dd>\n</dl></dd>\n</dl></div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/index.sgml",
    "content": "<ANCHOR id=\"cockpit.conf.5\" href=\"cockpit.conf.5.html\">\n<ANCHOR id=\"cockpit-conf-description\" href=\"cockpit.conf.5.html#cockpit-conf-description\">\n<ANCHOR id=\"cockpit-conf-webservice\" href=\"cockpit.conf.5.html#cockpit-conf-webservice\">\n<ANCHOR id=\"cockpit-conf-log\" href=\"cockpit.conf.5.html#cockpit-conf-log\">\n<ANCHOR id=\"cockpit-conf-oauth\" href=\"cockpit.conf.5.html#cockpit-conf-oauth\">\n<ANCHOR id=\"cockpit-conf-bugs\" href=\"cockpit.conf.5.html#cockpit-conf-bugs\">\n<ANCHOR id=\"cockpit-conf-author\" href=\"cockpit.conf.5.html#cockpit-conf-author\">\n<ANCHOR id=\"cockpit-conf-also\" href=\"cockpit.conf.5.html#cockpit-conf-also\">\n<ANCHOR id=\"cockpit-ws.8\" href=\"cockpit-ws.8.html\">\n<ANCHOR id=\"cockpit-ws-description\" href=\"cockpit-ws.8.html#cockpit-ws-description\">\n<ANCHOR id=\"cockpit-ws-transport\" href=\"cockpit-ws.8.html#cockpit-ws-transport\">\n<ANCHOR id=\"cockpit-ws-timeout\" href=\"cockpit-ws.8.html#cockpit-ws-timeout\">\n<ANCHOR id=\"cockpit-ws-options\" href=\"cockpit-ws.8.html#cockpit-ws-options\">\n<ANCHOR id=\"cockpit-ws-environment\" href=\"cockpit-ws.8.html#cockpit-ws-environment\">\n<ANCHOR id=\"cockpit-ws-bugs\" href=\"cockpit-ws.8.html#cockpit-ws-bugs\">\n<ANCHOR id=\"cockpit-ws-author\" href=\"cockpit-ws.8.html#cockpit-ws-author\">\n<ANCHOR id=\"cockpit-ws-also\" href=\"cockpit-ws.8.html#cockpit-ws-also\">\n<ANCHOR id=\"cockpit-desktop.1\" href=\"cockpit-desktop.1.html\">\n<ANCHOR id=\"cockpit-desktop-description\" href=\"cockpit-desktop.1.html#cockpit-desktop-description\">\n<ANCHOR id=\"cockpit-desktop-environment\" href=\"cockpit-desktop.1.html#cockpit-desktop-environment\">\n<ANCHOR id=\"cockpit-desktop-bugs\" href=\"cockpit-desktop.1.html#cockpit-desktop-bugs\">\n<ANCHOR id=\"cockpit-desktop-author\" href=\"cockpit-desktop.1.html#cockpit-desktop-author\">\n<ANCHOR id=\"cockpit-desktop-also\" href=\"cockpit-desktop.1.html#cockpit-desktop-also\">\n<ANCHOR id=\"remotectl.8\" href=\"remotectl.8.html\">\n<ANCHOR id=\"remotectl-description\" href=\"remotectl.8.html#remotectl-description\">\n<ANCHOR id=\"remotectl-commands\" href=\"remotectl.8.html#remotectl-commands\">\n<ANCHOR id=\"remotectl-options\" href=\"remotectl.8.html#remotectl-options\">\n<ANCHOR id=\"remotectl-bugs\" href=\"remotectl.8.html#remotectl-bugs\">\n<ANCHOR id=\"remotectl-author\" href=\"remotectl.8.html#remotectl-author\">\n<ANCHOR id=\"remotectl-see-also\" href=\"remotectl.8.html#remotectl-see-also\">\n<ANCHOR id=\"cockpit-bridge.1\" href=\"cockpit-bridge.1.html\">\n<ANCHOR id=\"cockpit-bridge-description\" href=\"cockpit-bridge.1.html#cockpit-bridge-description\">\n<ANCHOR id=\"cockpit-bridge-options\" href=\"cockpit-bridge.1.html#cockpit-bridge-options\">\n<ANCHOR id=\"cockpit-bridge-bugs\" href=\"cockpit-bridge.1.html#cockpit-bridge-bugs\">\n<ANCHOR id=\"cockpit-bridge-author\" href=\"cockpit-bridge.1.html#cockpit-bridge-author\">\n<ANCHOR id=\"cockpit-bridge-also\" href=\"cockpit-bridge.1.html#cockpit-bridge-also\">\n<ANCHOR id=\"api-cockpit\" href=\"api-cockpit.html\">\n<ANCHOR id=\"cockpit-dbus\" href=\"cockpit-dbus.html\">\n<ANCHOR id=\"cockpit-file\" href=\"cockpit-file.html\">\n<ANCHOR id=\"cockpit-http\" href=\"cockpit-http.html\">\n<ANCHOR id=\"cockpit-spawn\" href=\"cockpit-spawn.html\">\n<ANCHOR id=\"cockpit-metrics\" href=\"cockpit-metrics.html\">\n<ANCHOR id=\"cockpit-series-data\" href=\"cockpit-series-data.html\">\n<ANCHOR id=\"cockpit-channels\" href=\"cockpit-channels.html\">\n<ANCHOR id=\"cockpit-location\" href=\"cockpit-location.html\">\n<ANCHOR id=\"cockpit-locale\" href=\"cockpit-locale.html\">\n<ANCHOR id=\"cockpit-error\" href=\"cockpit-error.html\">\n<ANCHOR id=\"cockpit-login\" href=\"cockpit-login.html\">\n<ANCHOR id=\"cockpit-util\" href=\"cockpit-util.html\">\n<ANCHOR id=\"cockpit-cache\" href=\"cockpit-cache.html\">\n<ANCHOR id=\"cockpit-manifest\" href=\"cockpit-manifest.html\">\n<ANCHOR id=\"api-base1-patternfly\" href=\"api-base1-patternfly.html\">\n<ANCHOR id=\"api-console-html\" href=\"api-console-html.html\">\n<ANCHOR id=\"api-shell-html\" href=\"api-shell-html.html\">\n<ANCHOR id=\"api-logs-html\" href=\"api-logs-html.html\">\n<ANCHOR id=\"api-terminal-html\" href=\"api-terminal-html.html\">\n"
  },
  {
    "path": "guide/195/listen.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>TCP Port and Address</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"guide.html\" title=\"Part I. Deployment Guide\">\n<link rel=\"prev\" href=\"https.html\" title=\"SSL/TLS Usage\">\n<link rel=\"next\" href=\"startup.html\" title=\"Start up\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"https.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"guide.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"startup.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"listen\"></a>TCP Port and Address</h2></div></div></div>\n<div class=\"toc\"><dl class=\"toc\">\n<dt><span class=\"section\"><a href=\"listen.html#listen-systemd\">Cockpit systemd Socket</a></span></dt>\n<dt><span class=\"section\"><a href=\"listen.html#listen-selinux\">SELinux Port</a></span></dt>\n<dt><span class=\"section\"><a href=\"listen.html#listen-firewalld\">Firewalld Port</a></span></dt>\n</dl></div>\n<p>Cockpit's <code class=\"code\">cockpit-ws</code> component is configured by default to accept\n    connections on port <code class=\"code\">9090</code>. This is the port that is documented for a\n    \"Web-based System Manager\" to listen on. It is also relatively memorable.</p>\n<p>However there are many reasons you may wish to change the default port. For\n    example other software may use port <code class=\"code\">9090</code> or you may wish to setup\n    Cockpit to listen on <code class=\"code\">443</code> instead. It is also possible to have Cockpit\n    only listen on one specific IP address.</p>\n<p>Note that it is only required to have Cockpit listening on a TCP port on\n    the server that you access with your web browser. If you add multiple servers\n    to the Cockpit dashboard, Cockpit will connect to those servers via\n    <code class=\"code\">ssh</code>.</p>\n<p>The systems that Cockpit runs on are typically locked down with firewalls,\n    SELinux, so changing the default port is not as easy as editing a configuration\n    file.</p>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"listen-systemd\"></a>Cockpit systemd Socket</h2></div></div></div>\n<p>On servers with\n      <a class=\"ulink\" href=\"https://www.freedesktop.org/wiki/Software/systemd/\" target=\"_top\"><code class=\"code\">systemd</code></a>\n      Cockpit starts on demand via socket activation. To change its port and/or address\n      you should place the following content in the\n      <code class=\"code\">/etc/systemd/system/cockpit.socket.d/listen.conf</code> file. Create the file\n      and directories in that path which not already exist. The <code class=\"code\">ListenStream</code>\n      option specifies the desired address and TCP port.</p>\n<pre class=\"programlisting\">\n[Socket]\nListenStream=\nListenStream=443\n</pre>\n<pre class=\"programlisting\">\n[Socket]\nListenStream=\nListenStream=192.168.1.1:443\n</pre>\n<p>NOTE: The first empty line is intentional. <code class=\"code\">systemd</code> allows multiple <code class=\"code\">Listen</code> directives to be declared in a single socket unit. To change the activation port instead of adding a second port, use a full override unit instead of a snippet.</p>\n<p>Cockpit can actually listen on multiple ports, also:</p>\n<pre class=\"programlisting\">\n[Socket]\nListenStream=\nListenStream=443\nListenStream=7777\n</pre>\n<p>As above, it's recommended to start with an override unit, otherwise it's possible one of your multiple listen addresses might conflict.</p>\n<p>In order for the changes to take effect, run the following commands:</p>\n<pre class=\"programlisting\">\n$ sudo systemctl daemon-reload\n$ sudo systemctl restart cockpit.socket\n</pre>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"listen-selinux\"></a>SELinux Port</h2></div></div></div>\n<p>If <a class=\"ulink\" href=\"https://selinuxproject.org/page/Main_Page\" target=\"_top\">SELinux</a> is\n      protecting your server, then you will need to tell it to allow Cockpit to listen\n      on the new port. Run the following command to do so. The last argument specifies\n      the desired TCP port.</p>\n<pre class=\"programlisting\">\n$ sudo semanage port -a -t websm_port_t -p tcp 9999\n</pre>\n<p>If the port is already defined by some other part of the SELinux policy, then\n      you will need to use the <code class=\"code\">-m</code> argument to modify the definition. That's\n      the case with the <code class=\"code\">443</code> SSL port, which is typically defined as an\n      <code class=\"code\">http_port_t</code> port.</p>\n<pre class=\"programlisting\">\n$ sudo semanage port -m -t websm_port_t -p tcp 443\n</pre>\n<p>The changes should take effect immediately.</p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"listen-firewalld\"></a>Firewalld Port</h2></div></div></div>\n<p>If <a class=\"ulink\" href=\"https://fedoraproject.org/wiki/FirewallD\" target=\"_top\">Firewalld</a> is\n      configured as your firewall, then you will need to tell it to allow Cockpit to\n      receive connections on the new port. Run the following commands to do so. The last\n      options specify the desired TCP port.</p>\n<pre class=\"programlisting\">\n$ sudo firewall-cmd [--zone=ZONE] --add-port=443/tcp\n$ sudo firewall-cmd --permanent [--zone=ZONE] --add-port=443/tcp\n</pre>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/packages.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Cockpit Packages</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"development.html\" title=\"Part III. Developer Guide\">\n<link rel=\"prev\" href=\"embedding.html\" title=\"Embedding and Integrating Cockpit\">\n<link rel=\"next\" href=\"urls.html\" title=\"Cockpit URLs\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"embedding.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"development.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"urls.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"packages\"></a>Cockpit Packages</h2></div></div></div>\n<div class=\"toc\"><dl class=\"toc\">\n<dt><span class=\"section\"><a href=\"packages.html#package-layout\">Layout of Package Files</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-manifest\">Package Manifest</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-links\">Package Links and Paths</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-minified\">Content Negotiation</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-api\">Using Cockpit API</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-bridges\">Bridges for specific tasks</a></span></dt>\n<dt><span class=\"section\"><a href=\"packages.html#package-replace\">Replacing an existing package</a></span></dt>\n</dl></div>\n<p>Cockpit is separated into various packages, each of which brings specific\n    features and/or code.</p>\n<div class=\"warning\" style=\"margin-left: 0.5in; margin-right: 0.5in;\">\n<h3 class=\"title\">Warning</h3>\n<p>In addition, any APIs or behavior not explicitly documented here is an\n      internal API and can be changed at any time.</p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"package-layout\"></a>Layout of Package Files</h2></div></div></div>\n<p>A package consists of one or more files placed in a directory or its\n      subdirectories. It must have a <code class=\"code\">manifest.json</code> file and follow\n      certain naming conventions.</p>\n<p>The name of a package is the name of the directory.</p>\n<p>The name of the package must be ASCII alphanumeric, and may contain an underscore.\n      Names of directories and files in the package must consist of ASCII alphanumeric\n      along with dash, underscore, dot, and comma. No spaces are allowed.</p>\n<p>Cockpit uses the data directories from the\n      <a class=\"ulink\" href=\"https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html\" target=\"_top\">XDG Base Directory\n        Specification</a>\n      to locate packages. The <code class=\"code\">$XDG_DATA_DIRS</code> represents a colon separate list of system data\n      directories, and <code class=\"code\">$XDG_DATA_HOME</code> is a user specific data directory. If the environment\n      variables are not set, defaults are used, according to the spec. If cockpit has been built with an\n      alternate <code class=\"code\">--prefix=/path</code> then the <code class=\"code\">$prefix/share/cockpit</code> is used by\n      default.</p>\n<p>A <code class=\"code\">cockpit/</code> subdirectories in any of these data directories is the location where\n      packages are loaded by Cockpit. If Cockpit finds a package with the same name, in multiple data\n      directories, then the first one wins. According to the spec the first data directory is\n      <code class=\"code\">$XDG_DATA_HOME</code> and then <code class=\"code\">$XDG_DATA_DIRS</code> in order.</p>\n<p>This means that, by default the following directories are searched for cockpit packages, and\n      in this order:</p>\n<div class=\"itemizedlist\"><ul class=\"itemizedlist\" style=\"list-style-type: disc; \">\n<li class=\"listitem\"><p><code class=\"code\">~/.local/share/cockpit/</code></p></li>\n<li class=\"listitem\"><p><code class=\"code\">/usr/local/share/cockpit/</code></p></li>\n<li class=\"listitem\"><p><code class=\"code\">/usr/share/cockpit/</code></p></li>\n</ul></div>\n<p>Packages placed in <code class=\"code\">$XDG_DATA_HOME</code> are not cached by Cockpit or the web browser.\n      Other packages are cached aggressively, and are accessed using a checksum of the files in\n      the packages and their names.</p>\n<p>You can use the following command to list the packages installed on a server. You'll note that\n      it's output may change when you run the command as different users, if there are packages installed\n      in the user's home directory.</p>\n<pre class=\"programlisting\">\n$ cockpit-bridge --packages\n...\n</pre>\n<p>To further clarify things, here is an example package called \"my-package\" and its file layout:</p>\n<pre class=\"programlisting\">\n/usr/share/cockpit/\n    my-package/\n        manifest.json\n        file.html\n        some.js\n</pre>\n<p>Place or symlink packages in your <code class=\"code\">~/.local/share/cockpit</code> directory (or appropriate\n      <code class=\"code\">$XDG_DATA_HOME</code> location) that you would like to modify and develop. System installed\n      packages should not change while Cockpit is running.</p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"package-manifest\"></a>Package Manifest</h2></div></div></div>\n<p>Each package has a <code class=\"code\">manifest.json</code> file. It is a JSON object. The following\n      fields may be present in the manifest:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\">content-security-policy</span></p></td>\n<td>\n<p>By default Cockpit serves packages using a strict\n            <a class=\"ulink\" href=\"https://en.wikipedia.org/wiki/Content_Security_Policy\" target=\"_top\">Content Security Policy</a>,\n            which among other things does not allow inline styles or scripts. This can\n            be overridden on a per-package basis, with this setting.</p>\n<p>If the overridden content security policy does not contain a <code class=\"code\">default-src</code>,\n            <code class=\"code\">connect-src</code>, <code class=\"code\">base-uri</code>, <code class=\"code\">form-action</code>, <code class=\"code\">object-src</code>,\n            or <code class=\"code\">block-all-mixed-content</code> then these will be added to the policy from the manifest.</p>\n</td>\n</tr>\n<tr>\n<td><p><span class=\"term\">name</span></p></td>\n<td><p>An optional string that changes the name of the package. Normally\n          packages derive their name from the directory that they are located in. This\n          field overrides that name.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\">priority</span></p></td>\n<td><p>An optional number that specifies which package is preferred in cases\n          where there are conflicts. For example given two packages with the same\n          <code class=\"code\">name</code> a package is chosen based on its priority.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\">requires</span></p></td>\n<td><p>An optional JSON object that contains a <code class=\"code\">\"cockpit\"</code>\n          string version number. The package will only be usable if the Cockpit bridge\n          and javascript base are equal or newer than the given version number.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\">version</span></p></td>\n<td><p>An informational version number for the package.</p></td>\n</tr>\n</tbody>\n</table></div>\n<p>In addition, the following keys contain information about where components of the package\n      should appear in Cockpit's user interface. Each of these keys is optional and contains an\n      object mapping unique identifiers to menu items, which are described below. (The naming of\n      these fields doesn't perfectly match the current user interface for historical reasons.)\n    </p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\">dashboard</span></p></td>\n<td><p>Dashboard items appear in the leftmost navigation bar, next to Cockpit's\n        <span class=\"emphasis\"><em>Dashboard</em></span> and the machines themselves.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\">menu</span></p></td>\n<td>\n<p>These items appear in the sidebar for an individual machine.\n          This section is roughly ordered into these categories (with their\n          <span class=\"emphasis\"><em>order</em></span> in parentheses):\n          </p>\n<div class=\"itemizedlist\"><ul class=\"itemizedlist\" style=\"list-style-type: disc; \">\n<li class=\"listitem\"><p>System Information (10)</p></li>\n<li class=\"listitem\"><p>Logs (20)</p></li>\n<li class=\"listitem\"><p>Configuring major subsystems (30-40)</p></li>\n<li class=\"listitem\"><p>Things running on the machine (VMs, Containers - 50-60)</p></li>\n<li class=\"listitem\"><p>Implementation Details (Accounts, Services - 70-100)</p></li>\n</ul></div>\n</td>\n</tr>\n<tr>\n<td><p><span class=\"term\">tools</span></p></td>\n<td><p>These items also appear in the sidebar for an individual machine, but are \n        put in a lower position, next to Cockpit's <span class=\"emphasis\"><em>Terminal</em></span>.\n        </p></td>\n</tr>\n</tbody>\n</table></div>\n<p>Menu items and tools are registered using JSON objects that have the\n      following properties:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\">label</span></p></td>\n<td><p>The label for the menu item or tool.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\">order</span></p></td>\n<td><p>An optional order number to place this menu item or tool. Lower numbers\n          are listed first.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\">path</span></p></td>\n<td><p>The relative path to the HTML file within the package that implements\n          the menu item or tool.</p></td>\n</tr>\n</tbody>\n</table></div>\n<p>An example manifest.json with some optional properties set:</p>\n<pre class=\"programlisting\">\n{\n  \"version\": 0,\n  \"require\": {\n      \"cockpit\": \"120\"\n  },\n  \"tools\": {\n     \"mytool\": {\n        \"label\": \"My Tool\",\n        \"path\": \"tool.html\"\n     }\n  }\n}\n</pre>\n<p>A file called <code class=\"filename\">override.json</code> may be placed next to the manifest.\n      containing overrides to the information in the manifest. These override files are in the\n      simple <a class=\"ulink\" href=\"https://tools.ietf.org/html/rfc7386\" target=\"_top\">JSON Merge Patch</a> format.</p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"package-links\"></a>Package Links and Paths</h2></div></div></div>\n<p>When referring to files in your package, such as in a hyperlink or a <code class=\"code\">&lt;style&gt;</code>\n      tag or <code class=\"code\">&lt;script&gt;</code> tag, simply use a relative path, and refer to the files\n      in the same directory. When you need to refer to files in another package use a relative link.</p>\n<p>For example here's how to include the base <code class=\"code\">cockpit.js</code> script in your HTML\n      from the <code class=\"code\">latest</code> package:</p>\n<pre class=\"programlisting\">\n&lt;script src=\"../base1/cockpit.js\"&gt;&lt;/script&gt;\n</pre>\n<p>Do not assume you can link to any file in any other package. Refer to the\n      <a class=\"link\" href=\"development.html\" title=\"Part III. Developer Guide\">list of API packages</a> for those that are\n      available for use.</p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"package-minified\"></a>Content Negotiation</h2></div></div></div>\n<p>In order to support language specific files, gzipped and/or minified data, the\n      files in a package are loaded using content negotiation logic.</p>\n<p>If a file does not exist at the expected path, Cockpit tries to insert\n      <code class=\"code\">.min</code> before its extension. It also tries adding a <code class=\"code\">.gz</code>\n      to both of those file names. If the file is still not found, and the request path has\n      more than one extension, the second to the last extension is popped off, and the above\n      process repeats.</p>\n<p>This means that for the file <code class=\"code\">test.de.js</code> in the package named\n      <code class=\"code\">mypackage</code> the following files would be tried in this order:</p>\n<pre class=\"programlisting\">\nmypackage/test.de.js\nmypackage/test.de.min.js\nmypackage/test.de.js.gz\nmypackage/test.de.min.js.gz\nmypackage/test.js\nmypackage/test.min.js\nmypackage/test.js.gz\nmypackage/test.min.js.gz\n</pre>\n<p>When packages are loaded from a system directory, Cockpit optimizes the file\n      system lookups above, by pre-listing the files. This is one of the reasons that\n      you should never change packages installed to a system directory while Cockpit\n      is running.</p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"package-api\"></a>Using Cockpit API</h2></div></div></div>\n<p>Cockpit has API available for writing packages. There is no API available\n      for external callers to invoke via HTTP, REST or otherwise.</p>\n<p>API from various packages can be used to implement Cockpit packages. Each package\n      listed here has some API available for use. Only the API explicitly documented should\n      be used.</p>\n<div class=\"itemizedlist\"><ul class=\"itemizedlist\" style=\"list-style-type: disc; \"><li class=\"listitem\"><p><a class=\"link\" href=\"development.html\" title=\"Part III. Developer Guide\">API Listing</a></p></li></ul></div>\n<p>To include javascript from the API, simply load it into your HTML using\n      a script tag. Alternatively you can use an javascript loader.</p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"package-bridges\"></a>Bridges for specific tasks</h2></div></div></div>\n<p>On the server side the\n      <GTKDOCLINK HREF=\"cockpit-bridge.1\"><code class=\"filename\">cockpit-bridge</code></GTKDOCLINK> connects\n      to various system APIs that the front end UI requests it to. There are additional\n      bridges for specific tasks that the main <code class=\"filename\">cockpit-bridge</code> cannot\n      handle. For example tasks that should be carried out with privilege escalation.</p>\n<p>These additional bridges can be registered in a <code class=\"code\">\"bridges\"</code> section of a\n      package's <code class=\"filename\">manifest.json</code> file. Building such a bridge is a complex tasks, and\n      we will skip over that here. However it is useful to adjust how these additional bridges\n      are called, and so we'll look at how they are registered.</p>\n<p>An example <code class=\"filename\">manifest.json</code> with a bridges section:</p>\n<pre class=\"programlisting\">\n{\n  \"bridges\": [\n    {\n      \"match\": { \"superuser\": null },\n      \"environ\": [ \"SUDO_ASKPASS=/usr/bin/my-password-tool\" ],\n      \"spawn: [ \"/usr/bin/sudo\", \"-n\", \"cockpit-bridge\", \"--privileged\" ],\n      \"problem\": \"access-denied\"\n    }\n  ]\n}\n</pre>\n<p>The bridges are considered in the order they are listed in the array. Use the\n      <code class=\"filename\">manifest.json</code><code class=\"code\">\"priority\"</code> field to control order between\n      packages. The bridges are registered using JSON objects that have the following\n      properties:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\">environ</span></p></td>\n<td><p>Optional, additional environment variables to pass to the bridge\n            command.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\">match</span></p></td>\n<td><p>The <code class=\"code\">\"match\"</code> object describes which channel open command\n            options need to match for a given channel to be handed over to this\n            bridge.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\">problem</span></p></td>\n<td><p>If a problem is specified, and this bridge fails to start up then\n            channels will be closed with this problem code. Otherwise later bridges or internal\n            handlers for the channel will be invoked.</p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\">spawn</span></p></td>\n<td><p>The command and arguments to invoke.</p></td>\n</tr>\n</tbody>\n</table></div>\n<p>The <code class=\"code\">spawn</code> and <code class=\"code\">environ</code> values can be dynamically\n    taken from a matching open command values. When a value in either the <code class=\"code\">spawn</code>\n    or <code class=\"code\">environ</code> array contains a named variable wrapped in <code class=\"code\">${}</code>,\n    the variable will be replaced with the value contained in the matching open command.\n    Only named variables are supported and name can only contain letters, numbers and\n    the following symbols: <code class=\"code\">._-</code></p>\n<p>For example a bridges section like:</p>\n<pre class=\"programlisting\">\n{\n  \"bridges\": [\n    {\n      \"match\": { \"payload\": \"example\" },\n      \"environ\": [ \"TAG=${tag}\" ],\n      \"spawn: [ \"/example-bridge\", \"--tag\", \"${tag}\" ],\n      \"problem\": \"access-denied\"\n    }\n  ]\n}\n</pre>\n<p>when a open command is received with a payload of <code class=\"code\">example</code>\n        with <code class=\"code\">tag</code> value of <code class=\"code\">tag1</code>. The following\n        command will be spawned</p>\n<pre class=\"programlisting\">TAG=tag1 /example-bridge --tag tag1</pre>\n<p>Processes that are reused so if another open command with a \"tag\" of\n        <code class=\"code\">tag1</code> is received. The open command will be passed to\n        existing process, rather than spawning a new one. However a open command\n        with an tag of <code class=\"code\">tag2</code> will spawn a new command:</p>\n<pre class=\"programlisting\">TAG=tag2 /example-bridge --tag tag2</pre>\n<p>If you need to include <code class=\"code\">${}</code>, as an actual value in your arguments\n    you can escape it by prefixing it with a <code class=\"code\">\\</code></p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"package-replace\"></a>Replacing an existing package</h2></div></div></div>\n<p>If the functionality in a package replaces that of another package\n      then it can replace that package by claiming the same <code class=\"code\">name</code> and a\n      higher <code class=\"code\">priority</code>.</p>\n<p>For example, a package in the <code class=\"filename\">/usr/share/cockpit/disks</code>\n      directory could replace Cockpit's <span class=\"emphasis\"><em>storage</em></span> package with\n      a <code class=\"filename\">manifest.json</code> like this:</p>\n<pre class=\"programlisting\">\n{\n  \"version\": 0,\n  \"name\": \"storage\",\n  \"priority\": 10,\n  \"menu\": {\n     \"index\": {\n        \"label\": \"Disk Storage\",\n        \"order\": 15\n     }\n  }\n}\n</pre>\n<p>It is also possible to hide or change labels on the menu items of an existing\n      package by including a <code class=\"filename\">override.json</code> in that existing package's\n      directory.</p>\n<p>For example an <code class=\"filename\">/usr/share/cockpit/systemd/override.json</code> could\n      hide the <span class=\"emphasis\"><em>Logs</em></span> menu item and move the <span class=\"emphasis\"><em>Services</em></span>\n      menu item to the top of the menu.</p>\n<pre class=\"programlisting\">\n{\n  \"menu\": {\n    \"logs\": null,\n    \"services\": {\n      \"order\": -1\n    }\n  }\n}\n</pre>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/privileges.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Privileges and Permissions</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"guide.html\" title=\"Part I. Deployment Guide\">\n<link rel=\"prev\" href=\"sso.html\" title=\"Single Sign On\">\n<link rel=\"next\" href=\"features.html\" title=\"Part II. Feature Internals\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"sso.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"guide.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"features.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"privileges\"></a>Privileges and Permissions</h2></div></div></div>\n<div class=\"toc\"><dl class=\"toc\"><dt><span class=\"section\"><a href=\"privileges.html#privileges-polkit\">Customizing Polkit Privileges</a></span></dt></dl></div>\n<p>When a user is logged into Cockpit, they are logged into a normal session\n    that has exactly the same privileges as if they logged in via SSH or on\n    the console.</p>\n<p>In some cases Cockpit will try to escalate the privileges of the user\n    using <a class=\"ulink\" href=\"https://www.freedesktop.org/wiki/Software/polkit/\" target=\"_top\">Policy Kit</a>\n    or <a class=\"ulink\" href=\"https://www.sudo.ws/\" target=\"_top\">sudo</a>. If the user is able to escalate\n    privileges from the command line, then Cockpit will use that same capability to\n    perform certain privileged tasks.</p>\n<p>Cockpit can use the user's login password internally to escalate privileges\n    in these situations. By selecting the\n    <span class=\"emphasis\"><em>Reuse my password for privileged tasks</em></span> option on the login screen\n    the login password will be cached internally and passed to <span class=\"emphasis\"><em>Policy Kit</em></span>\n    when requested in order to escalate privileges.</p>\n<p>To test out whether Cockpit can escalate privileges, you can run these commands\n    from a the <a class=\"link\" href=\"feature-terminal.html\" title=\"Terminal\">terminal built into Cockpit</a>.</p>\n<pre class=\"programlisting\">\n$ sudo cockpit-bridge\n...\n$ pkexec cockpit-bridge\n...\n</pre>\n<p>If either of these commands succeed without prompting for a password,\n    Cockpit will be able to start a privileged copy of the\n    <code class=\"filename\">cockpit-bridge</code> and use it to perform privileged tasks\n    when necessary.</p>\n<p>Usually a user needs to be in the <code class=\"code\">wheel</code> Unix user group for the\n    user to be able to escalate privileges in this way. However both Policy Kit and\n    sudo may be configured to use other criteria.</p>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"privileges-polkit\"></a>Customizing Polkit Privileges</h2></div></div></div>\n<p>Services like <a class=\"ulink\" href=\"https://www.freedesktop.org/wiki/Software/systemd/\" target=\"_top\">systemd</a>\n      and <a class=\"ulink\" href=\"https://wiki.gnome.org/Projects/NetworkManager\" target=\"_top\">NetworkManager</a> use\n      <a class=\"ulink\" href=\"https://www.freedesktop.org/wiki/Software/polkit/\" target=\"_top\">Polkit</a> to\n      validate and escalate privileges. It is possible to customize these rules with files\n      in <code class=\"filename\">/etc/polkit-1/rules.d</code>.</p>\n<p>Polkit rules files are\n      <a class=\"ulink\" href=\"https://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html\" target=\"_top\">javascript with specific methods and objects</a>. For example, placing the following polkit rule to\n      <code class=\"filename\">/etc/polkit-1.rules.d/10-operators.rule</code> allows all users in the\n      <code class=\"code\">operators</code> group to start, stop, restart and otherwise manage systemd services:</p>\n<pre class=\"programlisting\">\npolkit.addRule(function(action, subject) {\n    if (action.id == \"org.freedesktop.systemd1.manage-units\") {\n        if (subject.isInGroup(\"operators\")) {\n            return polkit.Result.YES;\n        }\n    }\n});\n</pre>\n<p>In order to allow a certain group to perform any administrative action you could add\n      a rule like this:</p>\n<pre class=\"programlisting\">\npolkit.addAdminRule(function(action, subject) {\n    return [\"unix-group:operators\"];\n});\n</pre>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/remotectl.8.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>remotectl</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"cockpit-manual.html\" title=\"Manual pages\">\n<link rel=\"prev\" href=\"cockpit-desktop.1.html\" title=\"cockpit-desktop\">\n<link rel=\"next\" href=\"cockpit-bridge.1.html\" title=\"cockpit-bridge\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"cockpit-desktop.1.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"cockpit-manual.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"cockpit-bridge.1.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"refentry\">\n<a name=\"remotectl.8\"></a><div class=\"titlepage\"></div>\n<div class=\"refnamediv\"><table width=\"100%\"><tr>\n<td valign=\"top\">\n<h2><span class=\"refentrytitle\">remotectl</span></h2>\n<p>remotectl — Remote Access Configuration</p>\n</td>\n<td valign=\"top\" align=\"right\"></td>\n</tr></table></div>\n<div class=\"refsynopsisdiv\">\n<h2>Synopsis</h2>\n<div class=\"cmdsynopsis\"><p><code class=\"command\">remotectl</code>  {COMMAND} [OPTIONS...]</p></div>\n</div>\n<div class=\"refsect1\">\n<a name=\"remotectl-description\"></a><h2>DESCRIPTION</h2>\n<p>The <span class=\"command\"><strong>remotectl</strong></span> program will configure remote access to the system. Currently it manages cockpit's SSL certificate.</p>\n</div>\n<div class=\"refsect1\">\n<a name=\"remotectl-commands\"></a><h2>Commands</h2>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody><tr>\n<td><p><span class=\"term\"><span class=\"command\"><strong>certificate</strong></span></span></p></td>\n<td>\n<p>Manage Cockpit's SSL certificate. If used without options will check if cockpit has a valid certificate without making any changes.</p>\n<p>\n          <code class=\"option\">--ensure</code> Ensure that a certificate exists and can be loaded. Certificate will be created if it does not already exist.\n        </p>\n<p>\n          <code class=\"option\">--user username</code> The unix user that should own the certificate. Only takes effect if used with <code class=\"option\">--ensure</code>.\n        </p>\n<p>\n          <code class=\"option\">--group groupname</code> The unix group that should read the certificate. Only takes effect if used with <code class=\"option\">--ensure</code>.\n        </p>\n<p>\n          If any additional arguments are given, they are treated as files that should be combined to create a certificate file. If the combined files validate, they will be saved in the appropriate location using the name of the first file given with the extension changed to .cert. For example:\n        </p>\n<p><span class=\"command\"><strong>remotectl certificate server.pem chain.pem key.pem</strong></span></p>\n<p>will result in <code class=\"literal\">server.cert</code>. If <code class=\"literal\">server.cert</code> already exists it will be overwritten.\n        </p>\n</td>\n</tr></tbody>\n</table></div>\n</div>\n<div class=\"refsect1\">\n<a name=\"remotectl-options\"></a><h2>OPTIONS</h2>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">--help</code></span></p></td>\n<td><p>\n            Show help options.\n          </p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\"><code class=\"option\">--verbose</code></span></p></td>\n<td><p>Print verbose messages about the task</p></td>\n</tr>\n</tbody>\n</table></div>\n</div>\n<div class=\"refsect1\">\n<a name=\"remotectl-bugs\"></a><h2>BUGS</h2>\n<p>\n      Please send bug reports to either the distribution bug tracker or the\n      <a class=\"ulink\" href=\"https://github.com/cockpit-project/cockpit/issues/new\" target=\"_top\">upstream bug tracker</a>.\n    </p>\n</div>\n<div class=\"refsect1\">\n<a name=\"remotectl-author\"></a><h2>AUTHOR</h2>\n<p>Cockpit has been written by many\n      <a class=\"ulink\" href=\"https://github.com/cockpit-project/cockpit/\" target=\"_top\">contributors</a>.</p>\n</div>\n<div class=\"refsect1\">\n<a name=\"remotectl-see-also\"></a><h2>SEE ALSO</h2>\n<p>\n      <span class=\"citerefentry\"><span class=\"refentrytitle\">cockpit-ws</span>(8)</span>\n    </p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/sso.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Single Sign On</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"guide.html\" title=\"Part I. Deployment Guide\">\n<link rel=\"prev\" href=\"authentication.html\" title=\"Cockpit Authentication\">\n<link rel=\"next\" href=\"privileges.html\" title=\"Privileges and Permissions\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"authentication.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"guide.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"privileges.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"sso\"></a>Single Sign On</h2></div></div></div>\n<div class=\"toc\"><dl class=\"toc\">\n<dt><span class=\"section\"><a href=\"sso.html#sso-server\">Server Requirements</a></span></dt>\n<dt><span class=\"section\"><a href=\"sso.html#sso-client\">Client Requirements</a></span></dt>\n</dl></div>\n<p>Cockpit can use Kerberos for Single Sign On authentication, where users are\n    automatically authenticated if they have a valid Kerberos ticket.</p>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"sso-server\"></a>Server Requirements</h2></div></div></div>\n<p>To authenticate users, the server that Cockpit is running on must be\n      joined to a domain. This can usually be accomplished using the\n      <a class=\"ulink\" href=\"https://freedesktop.org/software/realmd/docs/realm.html\" target=\"_top\"><code class=\"code\">realm join example.com</code></a>\n      command.</p>\n<p>The domain must be resolvable by DNS. For instance, the SRV records of the\n      kerberos server should be resolvable:</p>\n<pre class=\"programlisting\">\n$ host -t SRV  _kerberos._udp.example.com\n_kerberos._udp.example.com has SRV record 0 100 88 dc.example.com\n</pre>\n<p>The server running Cockpit should have a fully qualified name that ends with\n      the domain name.</p>\n<p>There must be a valid Kerberos host key for the server in the <code class=\"code\">/etc/krb5.keytab</code>\n      file. Alternatively, if you would like to use a different keytab, you can do so\n      by placing it in <code class=\"code\">/etc/cockpit/krb5.keytab</code>. It may be necessary to\n      create a kerberos service principal and update the keytab if it is not present.\n      Depending on your domain type different service names are required:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\">Active Directory</span></p></td>\n<td><p><code class=\"code\">HOST/server.example.com@EXAMPLE.COM</code></p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\">IPA and MIT</span></p></td>\n<td><p><code class=\"code\">HTTP/server.example.com@EXAMPLE.COM</code></p></td>\n</tr>\n</tbody>\n</table></div>\n<p>When joining an IPA domain with Cockpit and the <code class=\"code\">ipa</code> command line tool is\n      available, both the service principal name and a <code class=\"code\">/etc/cockpit/krb5.keytab</code> get\n      created automatically, so that Kerberos based single sign on into Cockpit works out of the\n      box. If you want/need to do this by hand or in a script, the\n      corresponding commands with IPA are:</p>\n<pre class=\"programlisting\">\n$ sudo ipa service-add --ok-as-delegate=true --force HTTP/server.example.com@EXAMPLE.COM\n$ sudo ipa-getkeytab -p HTTP/server.example.com@EXAMPLE.COM -k /etc/cockpit/krb5.keytab\n</pre>\n<p>The following command can be used to list the <code class=\"code\">/etc/cockpit/krb5.keytab</code>:</p>\n<pre class=\"programlisting\">\n$ sudo klist -k /etc/cockpit/krb5.keytab\n</pre>\n<p>Lastly accounts from the domain must be resolvable to unix accounts on the server\n      running Cockpit. For example:</p>\n<pre class=\"programlisting\">\n$ getent passwd user@example.com\nuser@example.com:*:381001109:381000513:User Name:/home/user:/bin/sh\n</pre>\n<p>If you wish to delegate your kerberos credentials to Cockpit, and allow Cockpit\n      to then connect to other machines using those credentials, you should enable delegation\n      for the hosts running Cockpit, and in some cases the <code class=\"code\">HTTP</code> service as well.\n      When joining an IPA domain, this is enabled by default.</p>\n<p>Domain admins (usually the <code class=\"code\">admins@example.com</code> group) should normally\n      also be able to administer any joined machine. Enable sudo access for that group\n      with the following command on the IPA server, for version 4.7.1 and later:</p>\n<pre class=\"programlisting\">\nipa-advise enable-admins-sudo | sh -ex\n</pre>\n<p>On earlier FreeIPA versions, run these commands instead, as a domain admin on\n      any joined machine:</p>\n<pre class=\"programlisting\">\nipa sudorule-add --hostcat=all --cmdcat=all All\nipa sudorule-add-user --groups=admins All\n</pre>\n<p>Note that this does not change security properties; domain admins can give this\n      privilege to themselves, so it is safe to enable by default.</p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"sso-client\"></a>Client Requirements</h2></div></div></div>\n<p>The client side, where your web browser is running, should have a valid kerberos\n      ticket in the current user session. A command like this will get one:</p>\n<pre class=\"programlisting\">\n$ kinit user@EXAMPLE.COM\nPassword for user@EXAMPLE.COM:\n</pre>\n<p>In addition your browser must be usually be configured to allow kerberos\n      authentication for the domain.</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\">Mozilla Firefox</span></p></td>\n<td><p>Go to <code class=\"code\">about:config</code> and set the\n          <code class=\"code\">network.negotiate-auth.trusted-uris</code> setting to your domain name\n          preceded by a dot, ie: <code class=\"code\">.example.com</code></p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\">Google Chrome</span></p></td>\n<td>\n<p>\n          On Linux: create the file\n          <code class=\"code\">/etc/opt/chrome/policies/managed/example-com.json</code>\n          with the contents:\n</p>\n<pre class=\"programlisting\">\n{\n  \"AuthServerWhitelist\": \"*example.com\"\n}\n</pre>\n<p>\n          and restart the browser. On other platforms, exit your browser\n          completely, and start it with a command line like this:\n          <code class=\"code\">google-chrome --auth-server-whitelist=*example.com</code>\n          </p>\n</td>\n</tr>\n</tbody>\n</table></div>\n<p>Use a fully qualified server name (with the domain name at the end) to access\n      Cockpit in your web browser.</p>\n<p>If you wish to connect from one server to another in Cockpit using kerberos SSO,\n      then you have to explicitly enable all sorts of things. For starters, make sure that\n      delegated credentials are allowed by your domain (see above). Next when requesting your\n      kerberos ticket make sure that forwardable tickets are requested:</p>\n<pre class=\"programlisting\">\n$ kinit -f user@EXAMPLE.COM\nPassword for user@EXAMPLE.COM:\n</pre>\n<p>Make sure that the forwardable flag <code class=\"code\">F</code> is present in your ticket:</p>\n<pre class=\"programlisting\">\n$ klist -f\nTicket cache: KEYRING:persistent:1000:1000\nDefault principal: user@EXAMPLE.COM\n\nValid starting       Expires              Service principal\n18.03.2017 05:39:23  19.03.2017 05:39:20  krbtgt/EXAMPLE.COM@EXAMPLE.COM\n\tFlags: FIA\n</pre>\n<p>Lastly configure your browser to allow delegated, forwardable kerberos\n      credentials to be sent to Cockpit:</p>\n<div class=\"variablelist\"><table border=\"0\" class=\"variablelist\">\n<colgroup>\n<col align=\"left\" valign=\"top\">\n<col>\n</colgroup>\n<tbody>\n<tr>\n<td><p><span class=\"term\">Mozilla Firefox</span></p></td>\n<td><p>Go to <code class=\"code\">about:config</code> and set the\n          <code class=\"code\">network.negotiate-auth.delegation-uris</code> setting to your domain name\n          preceded by a dot, ie: <code class=\"code\">.example.com</code></p></td>\n</tr>\n<tr>\n<td><p><span class=\"term\">Google Chrome</span></p></td>\n<td>\n<p>\n          On Linux: create the file\n          <code class=\"code\">/etc/opt/chrome/policies/managed/example-com.json</code>\n          with the contents:\n</p>\n<pre class=\"programlisting\">\n{\n  \"AuthServerWhitelist\": \"*example.com\",\n  \"AuthNegotiateDelegateWhitelist\": \"*example.com\"\n}\n</pre>\n<p>\n          and restart the browser. On other platforms, exit your browser\n          completely, and start it with a command line like this:\n          <code class=\"code\">google-chrome --auth-server-whitelist=*example.com --auth-negotiate-delegate-whitelist=*example.com</code>\n          </p>\n</td>\n</tr>\n</tbody>\n</table></div>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/startup.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Start up</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"guide.html\" title=\"Part I. Deployment Guide\">\n<link rel=\"prev\" href=\"listen.html\" title=\"TCP Port and Address\">\n<link rel=\"next\" href=\"authentication.html\" title=\"Cockpit Authentication\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"listen.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"guide.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"authentication.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"startup\"></a>Start up</h2></div></div></div>\n<div class=\"toc\"><dl class=\"toc\">\n<dt><span class=\"section\"><a href=\"startup.html#startup-shutdown\">Process exit</a></span></dt>\n<dt><span class=\"section\"><a href=\"startup.html#startup-boot\">Boot start up</a></span></dt>\n</dl></div>\n<p>Cockpit's <code class=\"code\">cockpit-ws</code> component is what the browser connects to\n    and it typically starts on demand via\n    <a class=\"ulink\" href=\"https://www.freedesktop.org/wiki/Software/systemd/\" target=\"_top\"><code class=\"code\">systemd</code></a>\n    socket activation.</p>\n<p>The actual <code class=\"code\">cockpit.service</code> and <code class=\"code\">cockpit-ws</code> process will start on\n    demand when a browser accesses the <code class=\"code\">cockpit.socket</code>,\n    <a class=\"link\" href=\"listen.html\" title=\"TCP Port and Address\">usually on port 9090</a>. Once a user logs in then\n    a <code class=\"code\">cockpit-bridge</code> process will be started in a Linux user login session.</p>\n<p>Only systems that you connect to with your browser need to have the <code class=\"code\">cockpit.socket</code>\n    enabled. For systems that you add to the dashboard of another Cockpit instance, the bridge is started\n    via SSH on demand.</p>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"startup-shutdown\"></a>Process exit</h2></div></div></div>\n<p>The <code class=\"code\">cockpit-bridge</code> process will exit when the user logs out. In addition,\n      after 10 minutes of inactivity, the <code class=\"code\">cockpit-ws</code> process will exit on its own.\n      The browser will automatically disconnect if it fails to hear from the\n      <code class=\"code\">cockpit-ws</code> process for 30 seconds.</p>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"startup-boot\"></a>Boot start up</h2></div></div></div>\n<p>To make Cockpit available by default after system boot the <code class=\"code\">cockpit.socket</code>\n      needs to be enabled:</p>\n<pre class=\"programlisting\">\n$ sudo systemctl enable cockpit.socket\n</pre>\n<p>If you wish to not have Cockpit available by default via a browser, then the\n      <code class=\"code\">cockpit.socket</code> should be disabled:</p>\n<pre class=\"programlisting\">\n$ sudo systemctl disable cockpit.socket\n</pre>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/195/style.css",
    "content": "@import url(\"gtk-doc.css\");\n\n@font-face {\n  font-family: 'Open Sans';\n  font-style: normal;\n  font-weight: 300;\n  src: url('OpenSans-Light-webfont.woff') format('woff');\n}\n@font-face {\n  font-family: 'Open Sans';\n  font-style: normal;\n  font-weight: 400;\n  src: url('OpenSans-Regular-webfont.woff') format('woff');\n}\n@font-face {\n  font-family: 'Open Sans';\n  font-style: normal;\n  font-weight: 600;\n  src: url('OpenSans-Semibold-webfont.woff') format('woff');\n}\n@font-face {\n  font-family: 'Open Sans';\n  font-style: normal;\n  font-weight: 700;\n  src: url('OpenSans-Bold-webfont.woff') format('woff');\n}\n@font-face {\n  font-family: 'Open Sans';\n  font-style: normal;\n  font-weight: 800;\n  src: url('OpenSans-ExtraBold-webfont.woff') format('woff');\n}\n\nH1.guides {\n\tbackground-color: #238b49;\n\tcolor: white;\n\tfont-family: Georgia, \"Times New Roman\", Times, serif;\n\tfont-size: 30pt;\n\tpadding: 5px 0px 5px 20px;\n}\n\nH2.guides {\n    margin-left: 20px;\n}\n\nDIV.guides {\n\tmargin-left: 20px;\n\tmargin-right: 20px;\n\tfont-family: 'Open Sans', Verdana, Arial, 'Bitstream Vera Sans', Helvetica, sans-serif;\n\tfont-size: 11pt;\n}\n\nDIV.guides > p {\n    margin-left: 20px;\n}\n\nDIV.guides > A {\n\tmargin-left: 40px;\n\tmargin-right: 20px;\n\tfont-size: 13px;\n\tline-height: 200%;\n        display: block;\n}\n\nTABLE.navigation {\n\tbackground-color: #238b49 !important;\n\tborder-width: 0 !important;\n\tcolor: white;\n\tfont-family: Georgia, \"Times New Roman\", Times, serif;\n}\n\nTABLE.navigation TH {\n\tfont-size: 30pt !important;\n\tfont-weight: normal;\n\ttext-align: left !important;\n\tpadding-left: 10pt;\n}\n\nTABLE.navigation TH:first-child {\n\tpadding: 5px 0px 5px 20px;\n}\n\n.shortcuts {\n\tcolor: white !important;\n}\n\n.shortcuts a {\n\tcolor: white !important;\n\tfont-family: 'Open Sans', Verdana, Arial, 'Bitstream Vera Sans', Helvetica, sans-serif;\n}\n\nP.title {\n\tfont-size: 30pt !important;\n}\n\nDIV.warning {\n    padding: 15px;\n}\n.warning .title {\n\tfont-weight: bold !important;\n\tleft: 0px;\n}\n\nBODY {\n\tpadding-top: 5.5em !important;\n\tmargin: 0px;\n}\n\n\n/* Target all Firefox, since firefox has bug wrt TABLE + position: fixed */\n@-moz-document url-prefix() {\n\tTABLE.navigation { position: static !important; }\n\tBODY { padding-top: 0 !important; }\n}\n\nP.releaseinfo {\n\tmargin: 1em;\n}\n\nDIV.toc {\n\tmargin: 1em;\n}\n\nDIV.book,\nDIV.refentry,\nDIV.chapter,\nDIV.article,\nDIV.reference,\nDIV.index,\nDIV.footer,\nDIV.section,\nDIV.part {\n\tfont-family: 'Open Sans', Verdana, Arial, 'Bitstream Vera Sans', Helvetica, sans-serif;\n\tfont-size: 11pt;\n\tline-height: 160%;\n}\n\nCODE {\n    font-size: 10.5pt;\n}\n\nBODY > DIV.footer,\nBODY > DIV.part {\n\tmargin-left: 1em;\n\tmargin-right: 1em;\n}\n\nBODY > DIV.refentry,\nBODY > DIV.chapter,\nBODY > DIV.article,\nBODY > DIV.reference,\nBODY > DIV.index,\nBODY > DIV.section,\nBODY > DIV.part,\nBODY > DIV.book > DIV.toc {\n    padding-top: 50px;\n    max-width: 800px;\n    padding-left: 40px;\n    padding-right: 20px;\n    margin-left: auto;\n    margin-right: auto;\n    /*\n\tmargin-left: 3em;\n\tmargin-right: 1em;\n        */\n}\n\nBODY > DIV.book > DIV.toc {\n    padding-top: 20px;\n}\n\nDIV.section {\n\tmargin-top: 3em;\n}\n\nPRE.programlisting {\n    font-size: 9.5pt;\n    line-height: 130%;\n    padding-left: 10px;\n}\n\nDIV.variablelist TABLE {\n\tfont-size: 11pt;\n\tline-height: 150%;\n        margin-left: 0px;\n}\n\nDIV.variablelist TABLE SPAN.term {\n\tpadding-right: 1em;\n}\n\nDIV.variablelist {\n    margin-left: 0px;\n}\n\nDIV.refsect1,\nDIV.refsect2,\nDIV.refsection,\nDIV.refnamediv,\nDIV.refsynopsisdiv {\n\tmargin-bottom: 2em !important;\n}\n\nDIV.refsection > H3 {\n\tmargin-top: 1.5em !important;\n}\n\nDIV.abstract > .title {\n\tmargin: 0.3em;\n\tvisibility: hidden;\n}\n\nH1 {\n\tfont-weight: normal !important;\n}\n\nH2 {\n\tposition: relative;\n\tleft: -1em;\n\tfont-weight: normal !important;\n}\n\nH3 {\n\tposition: relative;\n\tleft: -1em;\n\tfont-weight: normal !important;\n}\n\nDD > DL {\n\tmargin-top: 0.3em;\n\tmargin-bottom: 0.3em;\n}\n\nPRE.screen {\n\tborder: solid 1px #729fcf;\n\tpadding: 0.5em;\n\tbackground: #e6f3ff;\n}\n\nCODE.option {\n\twhite-space: nowrap;\n}\n"
  },
  {
    "path": "guide/195/urls.html",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">\n<title>Cockpit URLs</title>\n<meta name=\"generator\" content=\"DocBook XSL Stylesheets Vsnapshot\">\n<link rel=\"home\" href=\"index.html\" title=\"Cockpit Guide\">\n<link rel=\"up\" href=\"development.html\" title=\"Part III. Developer Guide\">\n<link rel=\"prev\" href=\"packages.html\" title=\"Cockpit Packages\">\n<link rel=\"next\" href=\"api-base1.html\" title=\"API: base1\">\n<link rel=\"stylesheet\" href=\"style.css\" type=\"text/css\">\n</head>\n<body bgcolor=\"white\" text=\"black\" link=\"#0000FF\" vlink=\"#840084\" alink=\"#0000FF\">\n<table class=\"navigation\" id=\"top\" width=\"100%\" summary=\"Navigation header\" cellpadding=\"2\" cellspacing=\"2\"><tr valign=\"middle\">\n<td><a accesskey=\"p\" href=\"packages.html\"><img src=\"left.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Prev\"></a></td>\n<td><a accesskey=\"u\" href=\"development.html\"><img src=\"up.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Up\"></a></td>\n<td><a accesskey=\"h\" href=\"index.html\"><img src=\"home.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Home\"></a></td>\n<th width=\"100%\" align=\"center\">Cockpit Guide</th>\n<td><a accesskey=\"n\" href=\"api-base1.html\"><img src=\"right.png\" width=\"24\" height=\"24\" border=\"0\" alt=\"Next\"></a></td>\n</tr></table>\n<div class=\"chapter\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\">\n<a name=\"urls\"></a>Cockpit URLs</h2></div></div></div>\n<div class=\"toc\"><dl class=\"toc\">\n<dt><span class=\"section\"><a href=\"urls.html#urls-components\">Component URLs</a></span></dt>\n<dt><span class=\"section\"><a href=\"urls.html#urls-visible\">Visible URLs</a></span></dt>\n</dl></div>\n<p>Cockpit URLs follow a specific structure, related to the components they are\n    loading. Various components are loaded in <code class=\"code\">&lt;iframe&gt;</code> tags. The\n    URLs for these components are described first. Further down below you can\n    find information about the top level bookmarkable Cockpit address URLs.</p>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"urls-components\"></a>Component URLs</h2></div></div></div>\n<p>Cockpit components are HTML documents. They are organized into\n      <a class=\"link\" href=\"packages.html\" title=\"Cockpit Packages\">packages</a>. Each package contains information about\n      which HTML components are available in that package. Components should always use\n      relative URLs to access resources, such as images, scripts or CSS files, even\n      if they refer to a resource in another package.</p>\n<p>The following are valid component URLs, each bit will be discussed\n      below:</p>\n<pre class=\"programlisting\">\n/cockpit/@localhost/package/component.html#/hash\n/cockpit/$checksum/package/component.html#/hash\n/cockpit/@server.example.com/package/component.html#/hash\n/cockpit+embedder/@localhost/package/component.html#/hash\n</pre>\n<p>All resource URLs are under the <code class=\"code\">/cockpit</code> namespace. In cases\n      where a Cockpit component is being <a class=\"link\" href=\"embedding.html\" title=\"Embedding and Integrating Cockpit\">embedded</a>\n      the <code class=\"code\">/cockpit</code> may be followed by a plus sign and another\n      <code class=\"code\">embedder</code> specific identifier.</p>\n<p>What follows is either a <code class=\"code\">@host</code> or <code class=\"code\">$checksum</code> which\n      tells cockpit where to <a class=\"link\" href=\"packages.html\" title=\"Cockpit Packages\">find the package</a>.\n      Checksums are used when more than one host has identical packages and the resources\n      can be cached.</p>\n<p>The <code class=\"code\">package</code> name is next, followed by the <code class=\"code\">component</code>\n      HTML path inside that package. And lastly a hash allows for navigation within a\n      single component. The hash should follow a URL path and/or query string form.</p>\n<div class=\"warning\" style=\"margin-left: 0.5in; margin-right: 0.5in;\">\n<h3 class=\"title\">Warning</h3>\n<p>Never assume that the <code class=\"code\">@host</code> or <code class=\"code\">$checksum</code> portion\n        is predictable. Only refer to resources in packages on the same host.</p>\n</div>\n</div>\n<div class=\"section\">\n<div class=\"titlepage\"><div><div><h2 class=\"title\" style=\"clear: both\">\n<a name=\"urls-visible\"></a>Visible URLs</h2></div></div></div>\n<p>The above Component URLs are usually not visible to the user. Instead the\n      Cockpit Web Service wraps the components in a shell which allows navigation, and\n      provides bookmarkable clean URLs to the component. These URLs do not affect\n      <a class=\"link\" href=\"embedding.html\" title=\"Embedding and Integrating Cockpit\">embedders</a> or\n      <a class=\"link\" href=\"packages.html\" title=\"Cockpit Packages\">components</a> directly.</p>\n<p>If no path is present then the Cockpit will redirect to either the default\n      page for the server or the default dashboard.</p>\n<p>If the first segment of the path begins with an <code class=\"code\">@</code> sign, then\n      the component is being shown from a non-local host.</p>\n<p>The next segment of the path, (or first if the component is being shown on\n      the local host) is the <a class=\"link\" href=\"packages.html\" title=\"Cockpit Packages\">package name</a>.\n      The remainder of the path is a component file in the package. If no further path\n      segments are present, a default <code class=\"code\">index.html</code> component in the package\n      is loaded. An extension of <code class=\"filename\">.html</code> is automatically\n      appended.</p>\n<p>The hash portion of the path is automatically transferred to the component\n      as the hash of its <a class=\"link\" href=\"urls.html#urls-components\" title=\"Component URLs\">resource URL</a>.</p>\n</div>\n</div>\n<div class=\"footer\"><hr></div>\n</body>\n</html>\n"
  },
  {
    "path": "guide/index.md",
    "content": "---\ntitle: Cockpit guide archives\nclass: cockpit-guide\n---\n\nThe Cockpit Guide is for those deploying Cockpit or developing parts of Cockpit.\n\n## Latest Cockpit Guide\n\n- [View the latest Cockpit Guide](./latest/)\n\n## Guide for specific older versions of Cockpit\n\nSpecific, older versions of the guide:\n\n- [195](195/)\n"
  },
  {
    "path": "guide/latest/api-base1.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>API: base1</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>API: base1</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_cockpit_js\">cockpit.js</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#api-cockpit-loading\">Loading cockpit.js</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_object_caching\">cockpit.js: Object Caching</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-cache-func\">cockpit.cache()</a></li>\n<li><a href=\"#cockpit-cache-close\">cache.close()</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_raw_channels\">cockpit.js: Raw Channels</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-channels-channel\">cockpit.channel()</a></li>\n<li><a href=\"#cockpit-channels-binary\">channel.binary</a></li>\n<li><a href=\"#cockpit-channels-options\">channel.options</a></li>\n<li><a href=\"#cockpit-channels-valid\">channel.valid</a></li>\n<li><a href=\"#cockpit-channels-send\">channel.send()</a></li>\n<li><a href=\"#cockpit-channels-control\">channel.control()</a></li>\n<li><a href=\"#cockpit-channels-wait\">channel.wait()</a></li>\n<li><a href=\"#cockpit-channels-close\">channel.close()</a></li>\n<li><a href=\"#cockpit-channels-message\">channel.onmessage</a></li>\n<li><a href=\"#cockpit-channels-oncontrol\">channel.oncontrol</a></li>\n<li><a href=\"#cockpit-channels-onready\">channel.onready</a></li>\n<li><a href=\"#cockpit-channels-close-ev\">channel.onclose</a></li>\n<li><a href=\"#cockpit-transport-origin\">cockpit.transport.origin</a></li>\n<li><a href=\"#cockpit-transport-host\">cockpit.transport.host</a></li>\n<li><a href=\"#cockpit-transport-csrf-token\">cockpit.transport.csrf_token</a></li>\n<li><a href=\"#cockpit-transport-options\">cockpit.transport.options</a></li>\n<li><a href=\"#cockpit-transport-wait\">cockpit.transport.wait()</a></li>\n<li><a href=\"#cockpit-transport-close\">cockpit.transport.close()</a></li>\n<li><a href=\"#cockpit-transport-filter\">cockpit.transport.filter()</a></li>\n<li><a href=\"#cockpit-transport-inject\">cockpit.transport.inject()</a></li>\n<li><a href=\"#cockpit-base64-encode\">cockpit.base64_encode()</a></li>\n<li><a href=\"#cockpit-base64-decode\">cockpit.base64_decode()</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_dbus_client\">cockpit.js: DBus Client</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-dbus-types\">DBus Types</a></li>\n<li><a href=\"#cockpit-dbus-dbus\">cockpit.dbus()</a></li>\n<li><a href=\"#cockpit-dbus-wait\">client.wait()</a></li>\n<li><a href=\"#cockpit-dbus-close\">client.close()</a></li>\n<li><a href=\"#cockpit-dbus-onclose\">client.onclose</a></li>\n<li><a href=\"#cockpit-dbus-onowned\">client.onowner</a></li>\n<li><a href=\"#cockpit-dbus-options\">client.options</a></li>\n<li><a href=\"#cockpit-dbus-unique-name\">client.unique_name</a></li>\n<li><a href=\"#cockpit-dbus-proxy\">client.proxy()</a></li>\n<li><a href=\"#cockpit-dbus-proxy-client\">proxy.client</a></li>\n<li><a href=\"#cockpit-dbus-proxy-path\">proxy.path</a></li>\n<li><a href=\"#cockpit-dbus-proxy-iface\">proxy.iface</a></li>\n<li><a href=\"#cockpit-dbus-proxy-valid\">proxy.valid</a></li>\n<li><a href=\"#cockpit-dbus-proxy-data\">proxy.data</a></li>\n<li><a href=\"#cockpit-dbus-proxy-call\">proxy.call()</a></li>\n<li><a href=\"#cockpit-dbus-proxy-wait\">proxy.wait()</a></li>\n<li><a href=\"#cockpit-dbus-proxy-onchanged\">proxy.onchanged</a></li>\n<li><a href=\"#cockpit-dbus-proxy-signal\">proxy.onsignal</a></li>\n<li><a href=\"#cockpit-dbus-proxies\">client.proxies()</a></li>\n<li><a href=\"#cockpit-dbus-proxies-wait\">proxies.wait()</a></li>\n<li><a href=\"#cockpit-dbus-proxies-client\">proxies.client</a></li>\n<li><a href=\"#cockpit-dbus-proxies-iface\">proxies.iface</a></li>\n<li><a href=\"#cockpit-dbus-proxies-path_namespace\">proxies.path_namespace</a></li>\n<li><a href=\"#cockpit-dbus-proxies-onadded\">proxies.onadded</a></li>\n<li><a href=\"#cockpit-dbus-proxies-onchanged\">proxies.onchanged</a></li>\n<li><a href=\"#cockpit-dbus-proxies-onremoved\">proxies.onremoved</a></li>\n<li><a href=\"#cockpit-dbus-call\">client.call()</a></li>\n<li><a href=\"#cockpit-dbus-then\">invocation.then()</a></li>\n<li><a href=\"#cockpit-dbus-catch\">invocation.catch()</a></li>\n<li><a href=\"#cockpit-dbus-subscribe\">client.subscribe()</a></li>\n<li><a href=\"#cockpit-dbus-remove\">subscription.remove()</a></li>\n<li><a href=\"#cockpit-dbus-watch\">client.watch()</a></li>\n<li><a href=\"#cockpit-dbus-watch-then\">watch.then()</a></li>\n<li><a href=\"#cockpit-dbus-watch-catch\">watch.catch()</a></li>\n<li><a href=\"#cockpit-dbus-watch-remove\">watch.remove()</a></li>\n<li><a href=\"#cockpit-dbus-onnotify\">client.onnotify</a></li>\n<li><a href=\"#cockpit-dbus-notify\">client.notify()</a></li>\n<li><a href=\"#cockpit-dbus-onmeta\">client.onmeta</a></li>\n<li><a href=\"#cockpit-dbus-variant\">cockpit.variant()</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_errors\">cockpit.js: Errors</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-problems\">Problem Codes</a></li>\n<li><a href=\"#cockpit-messages\">cockpit.message()</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_file_access\">cockpit.js: File Access</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-file-simple\">Simple reading and writing</a></li>\n<li><a href=\"#cockpit-file-format\">File format</a></li>\n<li><a href=\"#cockpit-file-binary\">Binary files</a></li>\n<li><a href=\"#cockpit-file-atomic\">Atomic modifications</a></li>\n<li><a href=\"#cockpit-file-notify\">Change notifications</a></li>\n<li><a href=\"#cockpit-file-path\">file.path</a></li>\n<li><a href=\"#cockpit-file-close\">Closing</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_http_client\">cockpit.js: HTTP Client</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-http-constructor\">cockpit.http()</a></li>\n<li><a href=\"#cockpit-http-get\">http.get()</a></li>\n<li><a href=\"#cockpit-http-post\">http.post()</a></li>\n<li><a href=\"#cockpit-http-request\">http.request()</a></li>\n<li><a href=\"#cockpit-http-then\">request.then()</a></li>\n<li><a href=\"#cockpit-http-catch\">request.catch()</a></li>\n<li><a href=\"#cockpit-http-response\">request.response()</a></li>\n<li><a href=\"#cockpit-http-stream\">request.stream()</a></li>\n<li><a href=\"#cockpit-http-input\">request.input()</a></li>\n<li><a href=\"#cockpit-http-close\">request.close()</a></li>\n<li><a href=\"#cockpit-http-close-all\">http.close()</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_localization\">cockpit.js: Localization</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-locale-language\">cockpit.language</a></li>\n<li><a href=\"#cockpit-locale-locale\">cockpit.locale()</a></li>\n<li><a href=\"#cockpit-locale-gettext\">cockpit.gettext()</a></li>\n<li><a href=\"#cockpit-locale-noop\">cockpit.noop()</a></li>\n<li><a href=\"#cockpit-locale-ngettext\">cockpit.ngettext()</a></li>\n<li><a href=\"#cockpit-locale-translate\">cockpit.translate()</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_page_location_and_jumping\">cockpit.js: Page Location and Jumping</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-location-general\">Page location</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-location-href\">location.href</a></li>\n<li><a href=\"#cockpit-location-path\">location.path</a></li>\n<li><a href=\"#cockpit-location-options\">location.options</a></li>\n<li><a href=\"#cockpit-location-go\">location.go()</a></li>\n<li><a href=\"#cockpit-location-replace\">location.replace()</a></li>\n<li><a href=\"#cockpit-location-decode\">location.decode()</a></li>\n<li><a href=\"#cockpit-location-encode\">location.encode()</a></li>\n<li><a href=\"#cockpit-location-changed\">cockpit.onlocationchanged</a></li>\n</ul>\n</li>\n<li><a href=\"#cockpit-jump\">Jumping between components</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-jump-jump\">cockpit.jump()</a></li>\n<li><a href=\"#cockpit-jump-hidden\">cockpit.hidden</a></li>\n<li><a href=\"#cockpit-jump-visibilitychange\">cockpit.onvisibilitychange</a></li>\n</ul>\n</li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_user_session\">cockpit.js: User Session</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-logout\">cockpit.logout()</a></li>\n<li><a href=\"#cockpit-user\">cockpit.user()</a></li>\n<li><a href=\"#cockpit-permission\">Permission lookup</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-permission-constructor\">cockpit.permission()</a></li>\n<li><a href=\"#cockpit-permission-allowed\">permission.allowed</a></li>\n<li><a href=\"#cockpit-permission-changed\">permission.onchanged</a></li>\n<li><a href=\"#cockpit-permission-close\">permission.close()</a></li>\n</ul>\n</li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_manifests\">cockpit.js: Manifests</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-manifest-loading\">Loading Manifests</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_metrics\">cockpit.js: Metrics</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-metrics-function\">cockpit.metrics()</a></li>\n<li><a href=\"#cockpit-metrics-fetch\">metrics.fetch()</a></li>\n<li><a href=\"#cockpit-metrics-follow\">metrics.follow()</a></li>\n<li><a href=\"#cockpit-metrics-close\">metrics.close()</a></li>\n<li><a href=\"#cockpit-metrics-series\">metrics.series</a></li>\n<li><a href=\"#cockpit-metrics-meta\">metrics.meta</a></li>\n<li><a href=\"#cockpit-metrics-onchanged\">metrics.onchanged</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_series_data\">cockpit.js: Series Data</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-grid\">cockpit.grid()</a></li>\n<li><a href=\"#cockpit-grid-add\">grid.add()</a></li>\n<li><a href=\"#cockpit-grid-remove\">grid.remove()</a></li>\n<li><a href=\"#cockpit-grid-sync\">grid.sync()</a></li>\n<li><a href=\"#cockpit-grid-move\">grid.move()</a></li>\n<li><a href=\"#cockpit-grid-walk\">grid.walk()</a></li>\n<li><a href=\"#cockpit-grid-notify\">grid.notify()</a></li>\n<li><a href=\"#cockpit-grid-onnotify\">grid.onnotify</a></li>\n<li><a href=\"#cockpit-grid-close\">grid.close()</a></li>\n<li><a href=\"#cockpit-grid-interval\">grid.interval</a></li>\n<li><a href=\"#cockpit-grid-beg\">grid.beg</a></li>\n<li><a href=\"#cockpit-grid-end\">grid.end</a></li>\n<li><a href=\"#cockpit-series\">cockpit.series()</a></li>\n<li><a href=\"#cockpit-series-input\">series.input()</a></li>\n<li><a href=\"#cockpit-series-load\">series.load()</a></li>\n<li><a href=\"#cockpit-series-interval\">series.interval</a></li>\n<li><a href=\"#cockpit-series-limit\">series.limit</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_spawning_processes\">cockpit.js: Spawning Processes</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-spawn-spawn\">cockpit.spawn()</a></li>\n<li><a href=\"#cockpit-spawn-script\">cockpit.script()</a></li>\n<li><a href=\"#cockpit-spawn-then\">process.then()</a></li>\n<li><a href=\"#cockpit-spawn-catch\">process.catch()</a></li>\n<li><a href=\"#cockpit-spawn-stream\">process.stream()</a></li>\n<li><a href=\"#cockpit-spawn-input\">process.input()</a></li>\n<li><a href=\"#cockpit-spawn-close\">process.close()</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_utilities\">cockpit.js: Utilities</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-format\">cockpit.format()</a></li>\n<li><a href=\"#cockpit-format-number\">cockpit.format_number()</a></li>\n<li><a href=\"#cockpit-format-bytes\">cockpit.format_bytes()</a></li>\n<li><a href=\"#cockpit-format-bytes-per-sec\">cockpit.format_bytes_per_sec()</a></li>\n<li><a href=\"#cockpit-format-bits-per-sec\">cockpit.format_bits_per_sec()</a></li>\n<li><a href=\"#cockpit-init\">cockpit.init()</a></li>\n<li><a href=\"#cockpit-info\">cockpit.info</a></li>\n<li><a href=\"#cockpit-event-target\">cockpit.event_target</a></li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>This package contains basic support API available to other packages.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_js\">cockpit.js</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Basic cockpit API to interact with the system</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"api-cockpit-loading\">Loading cockpit.js</h3>\n<div class=\"paragraph\">\n<p><code>cockpit.js</code> should be loaded via a script tag.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;script src=\"../base1/cockpit.js\"&gt;</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_js_object_caching\">cockpit.js: Object Caching</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>If the same information is displayed by multiple components in Cockpit,\n<code>cockpit.cache()</code> provides a way to share data between them. The\nshared data should be simple objects, arrays, and values, and not\ncontain functions or other objects.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-cache-func\">cockpit.cache()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cache = cockpit.cache(key, provider, consumer)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new cache object. The <code>key</code> should be a globally unique\nstring that describes the data being cached. This string must describe\nthe data, across all machines and all versions of cockpit. It is\ncustomary to include a version number in the <code>key</code> string.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>function provider(result, key) {\n    result(\"myvalue\");\n\n    return {\n        close: function() {\n            /* closed */\n        }\n    };\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <code>provider</code> is a function that will be invoked to start retrieving\ndata for the cache. It will be passed a <code>result</code> function as its first\nargument. The <code>result</code> should be invoked whenever new data is\navailable. The <code>key</code> argument matches the key string the cache was\ncreated with.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>provider</code> can return an object with a <code>close</code> method. This\nmethod will be invoked when the cache no longer needs data from the\nprovider.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>function consumer(value, key) {\n    /* ... */\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <code>consumer</code> is a function that will be passed new values when they\nare available, whether they come from the <code>provider</code> or a source in a\ndifferent component/frame.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-cache-close\">cache.close()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cache.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close a cache and stop calling its <code>consumer</code>. If the <code>provider</code> was\ninvoked, then the <code>close()</code> method it returned will be invoked.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_js_raw_channels\">cockpit.js: Raw Channels</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>At a low level Cockpit communicates with the system via messages passed\nthrough various channels. These are usually exposed via higher level\nAPIs, such as the <code>cockpit.spawn()</code> function. It is rare to use raw\nchannels directly.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-channels-channel\">cockpit.channel()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel = cockpit.channel(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This function creates a new channel for communication with the system.\nIt returns a new channel object. The <code>options</code> argument is a plain\nobject. At least the <code>\"payload\"</code> option is required, and based on the\npayload type, other options may be required.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"binary\"</code></dt>\n<dd>\n<p>Set to <code>true</code> to transfer binary payloads. Both messages sent via\n<a href=\"#cockpit-channels-send\"><code>channel.send()</code></a> and those received via\n<a href=\"#cockpit-channels-message\"><code>channel.onmessage</code></a> should be arrays\nof bytes, either <code>Uint8Array</code> or <code>Array</code> depending on browser\nsupport.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"payload\"</code></dt>\n<dd>\n<p>The payload type for the channel. Only specific payload types are\nsupported.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to open this channel as root. If the currently\nlogged in user is not permitted to become root (eg: via <code>pkexec</code>)\nthen the <code>channel</code> will immediately be\n<a href=\"#cockpit-channels-close-ev\">closed</a> with a <code>\"access-denied\"</code>\nproblem code.\n+\nSet to <code>\"try\"</code> to try to open the channel as root, but if that\nfails, then fall back to an unprivileged channel.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The channel object returned has the following fields and methods and\nevents. You should call the <code>channel.close()</code> method when done with\nthe channel.</p>\n</div>\n<div class=\"paragraph\">\n<p>A valid channel will always be returned and the is ready to\n<code>channel.send()</code>. The channel may\n<a href=\"#cockpit-channels-close-ev\">close shortly afterword</a> due to a\nfailure.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-channels-binary\">channel.binary</h3>\n<div class=\"paragraph\">\n<p>Will be <code>true</code> for an binary channel. Will be set to <code>false</code> if the\nchannel is textual.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-channels-options\">channel.options</h3>\n<div class=\"paragraph\">\n<p>The options used to open this channel. This should not be changed.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-channels-valid\">channel.valid</h3>\n<div class=\"paragraph\">\n<p>Will be <code>true</code> for an open channel. Will be set to <code>false</code> if the\nchannel closes.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-channels-send\">channel.send()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.send(data)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Send a message over the channel. The contents of the message depends on\nthe payload type of the channel. If a binary channel, then <code>data</code> is\nexpected to be an <code>Array</code> of bytes or a <code>Uint8Array</code>. If not binary,\nthen the <code>data</code> will be converted to a string if not already a string.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-channels-control\">channel.control()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.control(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Notify the channel to tune certain parameters on the fly. The\n<code>options</code> is a plain javascript object, and the contents depend on the\n<code>\"payload\"</code> of the channel.</p>\n</div>\n<div class=\"paragraph\">\n<p>One common operation is to set <code>\"command\"</code> to <code>\"done\"</code> in the\noptions field. To indicate that no further messages will be sent through\nthe channel.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-channels-wait\">channel.wait()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = channel.wait([callback])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Returns a <code>promise</code> that is ready when the channel is ready, or fails\nif the client closes. If a <code>callback</code> is specified, it is attached to\nthe promise. The promise will be rejected or resolved with the contents\n<code>options</code> passed to the\n<a href=\"#cockpit-channels-onready\">channel.onready</a> and\n<a href=\"#cockpit-channels-close-ev\">channel.onclose</a> events respectively.</p>\n</div>\n<div class=\"paragraph\">\n<p>In general it&#8217;s not necessary to wait for the channel before starting to\nuse the channel.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-channels-close\">channel.close()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.close([options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the channel.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>options</code> is present it can be a plain javascript object containing\nadditional channel close options to send to the peer. If closing for\nbecause of a problem, set the <code>\"problem\"</code> field to a\n<a href=\"#cockpit-problems\">problem code</a>. If <code>options</code> is not an object it\nwill be treated as a <code>\"problem\"</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-channels-close-ev\">close event</a> will fire. A channel\ncan also be closed by a peer or if the underlying transport closes.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-channels-message\">channel.onmessage</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"message\", function(event, data) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the channel receives a message. The message is\npassed as a string to the handler in the <code>data</code>. In the case of binary\nchannels <code>data</code> is an <code>Uint8Array</code> or an <code>Array</code> of bytes if the\nformer is not supported by the browser. The contents of the message\ndepends on the payload type of the channel.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-channels-oncontrol\">channel.oncontrol</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"control\", function(event, options) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the channel receives an control message in the\nmiddle of the flow. One particular use is when the <code>command</code> is set to\n<code>\"done\"</code> then no further messages will be received in the channel. The\nexact form of these messages depend on the <code>\"payload\"</code> of the channel.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-channels-onready\">channel.onready</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"ready\", function(event, options) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the other end of the channel is ready to start\nprocessing messages. This indicates the channel is completely open. It\nis possible to start sending messages on the channel before this point.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-channels-close-ev\">channel.onclose</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"close\", function(event, options) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the channel closes. This can happen either\nbecause <a href=\"#cockpit-channels-close\">channel.close()</a> function was\ncalled, or if the peer closed the channel, or the underlying transport\ncloses.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> will contain various close information, including a\n<code>\"problem\"</code> field which will be set if the channel was closed because\nof a problem.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-transport-origin\">cockpit.transport.origin</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.origin</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The HTTP origin that is being used by the underlying channel transport.\nThis is read-only, you should not assign a value. If the browser\nsupports <code>window.location.origin</code> then this will be identical to that\nvalue.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-transport-host\">cockpit.transport.host</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.host</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The host that this transport is going to talk to by default. This is\nread-only, you should not assign a value. If the value is null that\nmeans that the transport has not been setup yet.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-transport-csrf-token\">cockpit.transport.csrf_token</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.csrf_token</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>A cross site request forgery token for use with external channels. This\nbecomes valid once the connection is properly established.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-transport-options\">cockpit.transport.options</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.options</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Initialization options received over the underlying channel transport.\nThese will be empty until connection is properly established.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-transport-wait\">cockpit.transport.wait()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.wait(callback)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Call the <code>callback</code> function once the underlying channel transport is\ninitialized. This will start the initialization if not already in\nprogress or completed. If the channel transport is already initialized,\nthen <code>callback</code> will be called immediately.</p>\n</div>\n<div class=\"paragraph\">\n<p>In general it&#8217;s not necessary to wait for the transport before starting\nto open channels.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-transport-close\">cockpit.transport.close()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the underlying channel transport. All channels open channels will\nclose. The <code>problem</code> argument should be a problem code string. If not\nspecified it will default to <code>\"disconnected\"</code>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-transport-filter\">cockpit.transport.filter()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.filter((message, channelid, control) =&gt;  { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Add a filter to the underlying channel transport. All incoming messages\nwill be passed to each of the filter callbacks that are registered.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is rarely used.</p>\n</div>\n<div class=\"paragraph\">\n<p>Filter callbacks are called in the order they are registered. If a\nfilter callback returns <code>false</code> then the message will not be\ndispatched further, whether to other filters, or to channels, etc.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>message</code> is the string or array with the raw message including,\nthe framing. The <code>channelid</code> is the channel identifier or an empty\nstring for control messages. If <code>control</code> is set then this is a\ncontrol message,d and the <code>control</code> argument contains the parsed JSON\nobject of the control message.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-transport-inject\">cockpit.transport.inject()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.inject(message, [out])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Inject a message into the underlying channel transport. The <code>message</code>\nshould be a <code>string</code> or an array of bytes, and should be valid\naccording to the Cockpit message protocol. If the <code>out</code> argument is\nequal to <code>false</code> then the message will be injected as an incoming\nmessage as if it was received on the underlying channel transport.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is rarely used. In general you should only <code>inject()</code>\nmessages you got from a <code>filter()</code>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-base64-encode\">cockpit.base64_encode()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.base64_encode(data)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Encode binary data into a string using the Base64 encoding. The <code>data</code>\nargument can either be a <code>string</code>, an <code>Array</code>, an <code>ArrayBuffer</code> or\na <code>Uint8Array</code>. The return value is a string.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-base64-decode\">cockpit.base64_decode()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>data = cockpit.base64_decode(string, [constructor])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Decode binary data from a Base64 encoded string. The <code>string</code> argument\nshould be a javascript string. The returned <code>data</code>&gt; will be an array\nof bytes.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can pass <code>Uint8Array</code>, <code>Array</code> or <code>String</code> as an alternate\n<code>constructor</code> if you want the decoded data in an alternate form. The\ndefault is to return an <code>Array</code>. Note that if you use a <code>String</code> for\nthe decoded data, then you must guarantee that the data does not contain\nbytes that would be invalid for a string.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_js_dbus_client\">cockpit.js: DBus Client</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit allows access to DBus services via this API.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-types\">DBus Types</h3>\n<div class=\"paragraph\">\n<p>DBus values are represented as javascript values and objects as follows:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>BYTE 'y'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>BOOLEAN 'b'</code></dt>\n<dd>\n<p>Javascript boolean.</p>\n</dd>\n<dt class=\"hdlist1\"><code>INT16 'n'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>UINT16 'q'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>INT32 'i'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>UINT32 'u'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>INT64 'x'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>UINT64 't'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>DOUBLE 'd'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>STRING 's'</code></dt>\n<dd>\n<p>Javascript string.</p>\n</dd>\n<dt class=\"hdlist1\"><code>OBJECT_PATH 'o'</code></dt>\n<dd>\n<p>Javascript string.</p>\n</dd>\n<dt class=\"hdlist1\"><code>SIGNATURE 'g'</code></dt>\n<dd>\n<p>Javascript string.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of BYTE 'ay'</code></dt>\n<dd>\n<p>A string containing base64 encoded data.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of DICT_ENTRY with STRING keys 'a{s?}'</code></dt>\n<dd>\n<p>A javascript plain object with the keys as property names.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of DICT_ENTRY with other keys 'a{??}'</code></dt>\n<dd>\n<p>A javascript plain object each key JSON encoded into a string property\nname.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of other</code></dt>\n<dd>\n<p>A javascript array.</p>\n</dd>\n<dt class=\"hdlist1\"><code>VARIANT</code></dt>\n<dd>\n<p>A javascript plain object with the <code>\"t\"</code> property set to a DBus type\nstring, and the <code>\"v\"</code> property set to a value.</p>\n</dd>\n<dt class=\"hdlist1\"><code>HANDLE 'h'</code></dt>\n<dd>\n<p>A javascript object that describes a cockpit channel which represents\nthe passed file descriptor. The <code>payload</code> is always set to\n<code>stream</code>. Pass it to\n<a href=\"#cockpit-channels-channel\">cockpit.channel()</a> to create the\nchannel and start reading or writing on it. Handles can only be\nreceived, not sent from within cockpit.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-dbus\">cockpit.dbus()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client = cockpit.dbus(name, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a DBus client for the given bus <code>name</code> (eg: service name). Use\nthe following functions to make DBus method calls, watch for events,\netc. The optional <code>options</code> argument is a javascript plain object, and\nmay include:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"bus\"</code></dt>\n<dd>\n<p>The DBus bus to connect to. Specifying <code>\"session\"</code> will connect to\nthe DBus user session bus, <code>\"user\"</code> will connect to the user bus (on\nsome systems this is identical to the session bus), <code>\"system\"</code> will\nconnect to the DBus system bus, and <code>\"none\"</code> to the non-standard bus\nspecified with the <code>address</code> option. This defaults to \"system\" if\nnot present.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"address\"</code></dt>\n<dd>\n<p>The bus address to connect to in case <code>bus</code> is <code>\"none\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to talk to this service as root. The DBus service\nwill see the DBus method calls and accesses as coming from root,\nrather than the logged in user. This is useful for talking to services\nthat do not correctly use\n<a href=\"https://www.freedesktop.org/software/polkit\">polkit</a> to authorize\nadministrative users. If the currently logged in user is not permitted\nto become root (eg: via <code>pkexec</code>) then the <code>client</code> will\nimmediately be <a href=\"#cockpit-dbus-onclose\">closed</a> with a\n<code>\"access-denied\"</code> problem code.\n+\nSet to <code>\"try\"</code> to try to talk as root, but if that fails, fall back\nto unprivileged.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"track\"</code></dt>\n<dd>\n<p>It is valid for a DBus service to exit, and be restarted in such a way\nthat clients continue to talk to it across the restart. Some services\nare not written with this in mind. If the <code>\"track\"</code> option is set to\n<code>true</code> then the channel will close when the service exits and/or\ndisconnects from the DBus bus.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>If the <code>name</code> argument is null, and no options other than <code>\"bus\"</code>\nare specified, then a shared DBus <code>client</code> is created. When using such\na client with a DBus bus, a <code>\"name\"</code> option must be specified on\nvarious other methods in order to specify which client to talk to.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-wait\">client.wait()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = client.wait([callback])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Returns a <code>promise</code> that is ready when the client is ready, or fails\nif the client closes. If a <code>callback</code> is specified, it is attached to\nthe promise.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-close\">client.close()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the DBus client. If <code>problem</code> is specified it should be a\n<a href=\"#cockpit-problems\">problem code</a> string.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-onclose\">client.onclose</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.addEventListener(\"close\", options =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the DBus client closes. This can happen either\nbecause <a href=\"#cockpit-dbus-close\">client.close()</a> function was called, or\nthe DBus service went away, or some other problem or disconnection.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> will contain various close information, including a\n<code>\"problem\"</code> field which will be set if the channel was closed because\nof a problem.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-onowned\">client.onowner</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.addEventListener(\"owner\", (event, owner) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the owner of the DBus name changes. The owner\nvalue will be the id of the name owner on the bus or null if the name is\nunowned. The absence of an owner should not be treated as a\ndisconnection. However this makes it possible to take some action based\non the actual status of the service, for example disconnecting a pending\nsignal handler.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-options\">client.options</h3>\n<div class=\"paragraph\">\n<p>Set to the options used when creating the client. Will not change for\nthe life of the client.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-unique-name\">client.unique_name</h3>\n<div class=\"paragraph\">\n<p>The unique DBus name of the client. Initially null, and becomes valid\nonce the the client is ready.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxy\">client.proxy()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy = client.proxy([interface, path], [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create proxy javascript object for a DBus <code>interface</code>. At the\nspecified DBus object <code>path</code>. The proxy will have properties, methods\nand signals from to the DBus interface, and allows for natural\ninteraction. If no <code>interface</code> is specified then the DBus bus name of\nthe client is used. If no <code>path</code> is specified, then the DBus name of\nthe client is converted to a path.</p>\n</div>\n<div class=\"paragraph\">\n<p>If creating lots of proxies for a given <code>interface</code> it is more\nefficient to use the <a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a>\nfunction.</p>\n</div>\n<div class=\"paragraph\">\n<p>The proxy is loaded when the\n<a href=\"#cockpit-dbus-proxy-valid\"><code>proxy.valid</code></a> field is <code>true</code>, and\nit is set to <code>false</code> if the underlying <code>interface</code> and/or <code>path</code>\ndon&#8217;t or no longer exist, or the <code>client</code> has closed. You can wait for\nproxy to become valid by passing a callback to its\n<a href=\"#cockpit-dbus-proxy-wait\"><code>proxy.wait()</code></a> function. The\n<a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a> event will also\nfire when the proxy becomes valid or invalid. DBus properties and\nmethods on the proxy are not defined until the proxy becomes valid.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>value = proxy.Prop1\nproxy.WritableProp = value</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>All DBus properties on the <code>interface</code> that start with an upper case\nletter (as is convention) will be automatically defined on this proxy,\nand will update their values as the DBus property values change. In\naddition the <a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a>\nevent will fire every time the properties change.</p>\n</div>\n<div class=\"paragraph\">\n<p>If you assign a value to a writable property on the proxy, the proxy\nwill try to set that property on the DBus <code>interface</code> at <code>path</code>. The\nactual proxy property value will not update until the DBus service has\nnotified the proxy of the change. If setting a property fails a warning\nwill be logged. In order to have more reliable setting of properties, or\ntrack when they have been set, or if setting fails, use the\n<a href=\"#cockpit-dbus-call\"><code>client.call()</code></a> directly. It should be noted\nthat DBus service implementations may also be inconsistent in their\nbehavior when setting a property fails.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can access the raw property data using the\n<a href=\"#cockpit-dbus-proxy-data\"><code>proxy.data</code></a> field, including data for\nproperties that do not start with an upper case letter.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.Method(arg1, arg2)\n    .then((retval1, retval2) =&gt; {\n        ...\n    })\n    .catch(ex =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>All DBus methods on the <code>interface</code> that start with an upper case\nletter (as is convention) will be automatically defined on this proxy.\nThese methods are called with arguments as normal javascript arguments.\nA\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the method returns, or fail if an\nerror occurs. The return values from the DBus method will be passed to\nthe <code>then</code> handler function directly.</p>\n</div>\n<div class=\"paragraph\">\n<p>Methods that do not start with an upper case letter can be invoked by\nusing the usual <a href=\"#cockpit-dbus-proxy-call\"><code>proxy.call()</code></a>\ndirectly.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.addEventListener(\"signal\", (event, arg1, arg2) =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>All DBus signals on the <code>interface</code> that start with an upper case\nletter (as is convention) will be automatically emit events on this\nproxy. These events will contain the signal arguments after the standard\n<code>event</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>Signals that do not start with an upper case letter can be subscribed to\nby using <a href=\"#cockpit-dbus-proxy-signal\"><code>proxy.onsignal</code></a> directly.</p>\n</div>\n<div class=\"paragraph\">\n<p>Usually a proxy asks the <code>client</code> to watch and notify it of changes to\nthe relevant object or path. You can pass an <code>options</code> argument with\nthe <code>watch</code> field set to <code>false</code> to prevent this.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxy-client\">proxy.client</h3>\n<div class=\"paragraph\">\n<p>Set to the DBus client of the proxy. Will not change for the life of the\nproxy.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxy-path\">proxy.path</h3>\n<div class=\"paragraph\">\n<p>Set to the DBus object path of the proxy. Will not change for the life\nof the proxy.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxy-iface\">proxy.iface</h3>\n<div class=\"paragraph\">\n<p>Set to the DBus interface name of the proxy. Will not change for the\nlife of the proxy.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxy-valid\">proxy.valid</h3>\n<div class=\"paragraph\">\n<p>Set to <code>true</code> when the proxy&#8217;s DBus interface is present at its DBus\npath, and all information for the proxy has loaded. Is set to <code>false</code>\nwhile loading, and after the proxy no longer refers a DBus interface and\npath. Also set to <code>false</code> if the <code>client</code> closes.</p>\n</div>\n<div class=\"paragraph\">\n<p>Use the by <a href=\"#cockpit-dbus-proxy-wait\"><code>proxy.wait()</code></a> function to\nwait for a proxy to load. The\n<a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a> event will also\nbe emitted when the proxy becomes valid or invalid. DBus properties and\nmethods on the proxy are not defined until the proxy becomes valid.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxy-data\">proxy.data</h3>\n<div class=\"paragraph\">\n<p>A plain javascript object containing all the raw property data that this\nproxy has loaded. This will be updated automatically as the proxy is\nnotified of property changes from the DBus service. The\n<a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a> event will be\nemitted when it changes.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxy-call\">proxy.call()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation = proxy.call(method, args, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Make a DBus method call on this proxy.</p>\n</div>\n<div class=\"paragraph\">\n<p>For DBus methods that start with an upper case letter, is usually more\nconvenient <a href=\"#cockpit-dbus-proxy\">to call the method directly on the\nproxy</a>. However if methods that do not follow the usual DBus convention,\nor specify additional options, or the caller cannot be sure that the\nmethod actually exists, you can use this method.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function also works on proxies that have are still loading and have\nnot become valid yet.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>method</code> should be a DBus method name, and the <code>args</code> should be\nan array of arguments to pass to the method. The <code>options</code> are\n<a href=\"#cockpit-dbus-call\">described elsewhere</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The returned value is identical to the one returned from\n<a href=\"#cockpit-dbus-call\">client.call()</a>. It is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the method returns, or fail if an\nerror occurs.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxy-wait\">proxy.wait()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = proxy.wait()\nproxy.wait(() =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Wait for a proxy to finish loading. This function returns a promise. If\na callback function is passed as an argument then that function will be\ninvoked when the proxy is ready. If this method is called after a proxy\nhas already loaded, then the promise will be resolved immediately, and\nany callback will be invoked immediately. Use the promise or\n<code>proxy.valid</code> to determine whether the proxy is valid.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxy-onchanged\">proxy.onchanged</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.addEventListener(\"changed\", (event, data) =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when the proxy&#8217;s properties change.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> has the following form, and will only include properties\nthat have changed:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n    \"Prop1\": \"value\",\n    \"Prop2\": 5\n}</pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxy-signal\">proxy.onsignal</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.addEventListener(\"signal\", (event, name, args) =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when the proxy&#8217;s emits an event.</p>\n</div>\n<div class=\"paragraph\">\n<p>For most events, that have names which start with an upper case letter,\nyou can just <a href=\"#cockpit-dbus-proxy\">connect to that event as a signal\ndirectly</a>. However if you wish to be notified when any signal is\nemitted, or for signals that do not follow the usual DBus convention,\nyou can connect to this event.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>name</code> is the DBus signal name, and the <code>args</code> is an array of\narguments that were emitted with the signal.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxies\">client.proxies()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies = client.proxies([interface], [path_namespace], [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create <a href=\"#cockpit-dbus-proxy\">proxy javascript objects</a> for a DBus\ninterfaces. The proxies will have properties, methods and signals from\nthe DBus <code>interface</code>, and allow for natural interaction. If no\n<code>interface</code> is specified then the DBus bus name of the client is used.\nIf no <code>path_namespace</code> is provided then <code>\"/\"</code> will be used.</p>\n</div>\n<div class=\"paragraph\">\n<p>Proxies will be automatically created for instances of the <code>interface</code>\navailable at the DBus service. The optional <code>path_namespace</code> argument\ncan be used to restrict the proxies for instances that have DBus paths\nwhich have the namespace path prefix.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy1 = proxies[\"/dbus/path1\"];\nproxy2 = proxies[\"/dbus/path2\"];\nfor (proxy in proxies) {\n    ...\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The returned <code>proxies</code> object will is used as a dictionary, and will\nhave values containing proxies for DBus interface instances, with the\nkeys being the DBus paths of those instances. It is possible to\nenumerate over the returned <code>proxies</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>Proxies will be automatically added and removed from the <code>proxies</code>\nobject as they appear and disappear in the service. The\n<a href=\"#cockpit-dbus-proxies-onadded\"><code>proxies.onadded</code></a> and\n<a href=\"#cockpit-dbus-proxies-onremoved\"><code>proxies.onremoved</code></a> events will\nbe emitted. DBus services may not support notifications of paths\ndisappearing.</p>\n</div>\n<div class=\"paragraph\">\n<p>Use the <code>proxies.wait()</code> function to be notified when the initial set\nof proxies has been populated.</p>\n</div>\n<div class=\"paragraph\">\n<p>Usually a proxies ask the <code>client</code> to watch and be notified of changes\nto the relevant object or path. You can pass an <code>options</code> argument\nwith the <code>watch</code> field set to <code>false</code> to prevent this.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxies-wait\">proxies.wait()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = proxies.wait()\nproxies.wait(() =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Wait for a <code>proxies</code> object to populate its initial set of proxies.\nThis function returns a promise. If a callback function is passed as an\nargument then that function will be invoked when the proxies are ready.\nIf this method is called after the proxies have populated, then the\npromise will be resolved immediately, and any callback will be invoked\nimmediately.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxies-client\">proxies.client</h3>\n<div class=\"paragraph\">\n<p>Set to the DBus client of the proxies. Will not change.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxies-iface\">proxies.iface</h3>\n<div class=\"paragraph\">\n<p>Set to the DBus interface name of the proxies. Will not change.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxies-path_namespace\">proxies.path_namespace</h3>\n<div class=\"paragraph\">\n<p>Set to the DBus path namespace used which the proxies must have as a\nDBus path prefix. Will not change.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxies-onadded\">proxies.onadded</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies.addEventListener(\"added\", (event, proxy) =&gt; {\n    ...\n})</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when a proxy is added to the <code>proxies</code> object.\nThe proxy will already have loaded.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxies-onchanged\">proxies.onchanged</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies.addEventListener(\"changed\", (event, proxy) =&gt; {\n    ...\n})</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when one of the proxy in the <code>proxies</code> object\nchanges its properties.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-proxies-onremoved\">proxies.onremoved</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies.addEventListener(\"removed\", (event, proxy) =&gt; {\n    ...\n})</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when a proxy is removed to the <code>proxies</code> object.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-call\">client.call()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation = client.call(path, interface, method, args, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Make a DBus method call.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>path</code> is the DBus object path to make the call on, <code>interface</code>\nis the DBus interface for the method and <code>method</code> is the name of the\nmethod to call. The <code>args</code> is an array of arguments to pass to the\nmethod, each of which must be appropriate for the expected\n<a href=\"#cockpit-dbus\">DBus type</a> of that argument. The <code>args</code> may be\n<code>null</code> if no arguments are to be sent.</p>\n</div>\n<div class=\"paragraph\">\n<p>The returned value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the method returns, or fail if an\nerror occurs.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>options</code> is specified it should be a plain javascript object,\nwhich may contain the following properties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>flags</code></dt>\n<dd>\n<p>A string containing DBus message flags. The character <code>\"i\"</code>\nindicates to the dbus service that interactive authentication is\nallowed. If the entire <code>flags</code> field is missing, then <code>\"i\"</code> is set\nby default.</p>\n</dd>\n<dt class=\"hdlist1\"><code>type</code></dt>\n<dd>\n<p>A valid DBus type signature to use when calling the method. In the\nabsence of this, the DBus service will be introspected (and the result\ncached) to ask what the method type signature is.</p>\n</dd>\n<dt class=\"hdlist1\"><code>timeout</code></dt>\n<dd>\n<p>The timeout of the call in milliseconds. The call will fail with the\n<code>\"timeout\"</code> problem code. If \"timeout\" is not given, the call will\nnever time out.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-then\">invocation.then()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation.then((args, options) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the DBus method call\nfinishes successfully.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>args</code> argument is an array of return values from the DBus method.\nEach of them will be converted to an appropriate\n<a href=\"#cockpit-dbus\">javascript type</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> argument may contain additional information about the\nreply. If the <code>type</code> option was specified when performing the method\ncall, then the <code>options</code> in the reply here will also contain a\n<code>type</code> field containing the DBus type signature of the output. If the\n<code>flags</code> option was specified when performing the call then the\n<code>options</code> in the reply here will contain message flags. Possible out\nmessage flags are:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>&gt;</code></dt>\n<dd>\n<p>A big endian message.</p>\n</dd>\n<dt class=\"hdlist1\"><code>&lt;</code></dt>\n<dd>\n<p>A little endian message.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-catch\">invocation.catch()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation.catch(exception =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the DBus method call\nfails.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>exception</code> object passed to the handler can have the following\nproperties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>problem</code></dt>\n<dd>\n<p>A <a href=\"#cockpit-problems\">problem code</a> string when a problem occurred\nstarting or communicating with the DBus service. This is <code>null</code> in\nthe cases where an actual DBus error was occurred.</p>\n</dd>\n<dt class=\"hdlist1\"><code>name</code></dt>\n<dd>\n<p>The DBus error name. This will be <code>null</code> in cases where the failure\nwas not due to a DBus error.</p>\n</dd>\n<dt class=\"hdlist1\"><code>message</code></dt>\n<dd>\n<p>A DBus error message. This will be <code>null</code> in cases where the failure\nwas not due to a DBus error.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-subscribe\">client.subscribe()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>subscription = client.subscribe(match, (path, interface, signal, args) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Subscribe to signals. The <code>match</code> argument is a javascript plain\nobject which defines what signals to subscribe to. Each property in the\n<code>match</code> argument restricts signals subscribed to. If a property is not\npresent then it is treated as a wildcard, matching anything. If an empty\nobject is specified as <code>match</code> then all signals will be subscribed to.\nThe <code>match</code> argument may contain the following properties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>interface</code></dt>\n<dd>\n<p>A DBus interface to match.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path</code></dt>\n<dd>\n<p>A DBus object path to match. May not be used together with the\n<code>path_namespace</code> property. It should be a valid DBus object path,\nthat is, it should have no trailing slash.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path_namespace</code></dt>\n<dd>\n<p>A DBus object path prefix to match. Any paths in the hierarchy below\nthis top path will match. May not be used together with the <code>path</code>\nproperty.</p>\n</dd>\n<dt class=\"hdlist1\"><code>member</code></dt>\n<dd>\n<p>The DBus signal name to match.</p>\n</dd>\n<dt class=\"hdlist1\"><code>arg0</code></dt>\n<dd>\n<p>Matches the first argument of a DBus message, which must be a string.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The handler passed as the second argument will be invoked when the\nsignal is received. A <code>subscription</code> is returned which can be used to\nremove the subscription by calling its <code>subscription.remove()</code> method.</p>\n</div>\n<div class=\"paragraph\">\n<p>It is not a problem to subscribe to the same signals more than once,\nwith identical or slightly different <code>match</code> arguments.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-remove\">subscription.remove()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>subscription.remove()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Unsubscribe from the DBus signal subscription.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-watch\">client.watch()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch = client.watch(path)\nwatch = client.watch({ \"path_namespace\": path_namespace, \"interface\": interface })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Watch for property and interface changes on the given DBus object\n<code>path</code> DBus <code>path_namespace</code>. If <code>interface</code> is specified only\nproperties on that DBus interface will be watched.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-dbus-proxy\"><code>client.proxy()</code></a> and\n<a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a> functions and the\nobjects they return are high level wrappers around <code>client.watch()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The property and interface changes will be available in raw form on the\n<a href=\"#cockpit-dbus-onnotify\"><code>client.onnotify</code></a> event.</p>\n</div>\n<div class=\"paragraph\">\n<p>Property and interface changes that are caused by a method call or\nsignal will show up before that method call reply is received, or signal\nevent is triggered. It should be possible to rely on this guarantee,\nunless the DBus service in question behaves incorrectly. Internally\nthese watches work well with code that implements the\n<a href=\"https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager\">ObjectManager</a>\nportion of the DBus specification. If no ObjectManager implementation is\navailable, the watch falls back to using DBus\n<a href=\"https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-introspectable\">Introspection</a>\nalong with the usual\n<a href=\"https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties\">PropertiesChanged</a>\nsignal. If the DBus service implements none of these, or implements them\nin an inconsistent manner, then this function will provide inconsistent\nor unexpected results.</p>\n</div>\n<div class=\"paragraph\">\n<p>The parameter is either a DBus <code>path</code> or a plain javascript object\nwith zero or more of the following fields. If an empty javascript object\nis used as an argument, then all paths, interfaces and properties will\nbe watched.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>interface</code></dt>\n<dd>\n<p>Watch properties on this DBus interface.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path</code></dt>\n<dd>\n<p>Watch interfaces and properties at this DBus path. May not be used\ntogether with the <code>path_namespace</code> property.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path_namespace</code></dt>\n<dd>\n<p>Watch interfaces and properties under this DBus path. It should be a\nvalid DBus object path, that is, it should have no trailing slash. If\nan ObjectManager implementation is available at this interface, then\nit is used. May not be used together with the <code>path</code> property.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The returned value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the watch has populated its initial\nset of properties and interfaces, and these have been notified via\n<a href=\"#cockpit-dbus-onnotify\"><code>client.onnotify</code></a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>A watch can be removed by calling the\n<a href=\"#cockpit-dbus-watch-remove\"><code>watch.remove()</code></a> method on the\nreturned value. If identical watches are added more than once, then they\nmust also be removed the same number of times before the removal takes\neffect.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-watch-then\">watch.then()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch.then(() =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the watch has populated\nits initial properties and interfaces.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-watch-catch\">watch.catch()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch.catch(ex =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called if the watch fails to populate\nits initial properties and interfaces. Note that a watch will only fail\nif the DBus client closes or is somehow disconnected. It does not fail\nin the case of missing interfaces or properties.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-watch-remove\">watch.remove()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch.remove()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Remove the watch. This may not have any immediate effect if other\nwatches are in place. In particular, if identical watches are added more\nthan once, then they must also be removed the same number of times\nbefore the removal takes effect.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-onnotify\">client.onnotify</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.addEventListener(\"notify\", data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when <a href=\"#cockpit-dbus-watch\">watched</a> properties or\ninterfaces change.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-dbus-proxy\"><code>client.proxy()</code></a> and\n<a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a> functions and the\nobjects they return are high level wrappers around the <code>data</code> provided\nby this event.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> has the following form:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n    \"/path1\": {\n        \"org.Interface1\": {\n            \"Prop1\": \"value\",\n            \"Prop2\": 5\n        },\n        \"org.Interface2\": null\n    }\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Multiple paths may be present, each of which may have multiple\ninterfaces, each of which may have multiple properties. The first time a\ngiven path and interface is emitted from this signal, it will have all\nits properties and interfaces. Thereafter only changes are noted. If an\ninterface is set to <code>null</code>, then that interface has disappeared.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-notify\">client.notify()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.notify(data)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Emits a synthetic <a href=\"#cockpit-dbus-onnotify\"><code>notify</code></a> event. The\n<code>data</code> argument should follow the same layout as described for the\n<code>notify</code> event.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-onmeta\">client.onmeta</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.onmeta = (ev, data) =&gt; { ... }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the meta data about\n<a href=\"#cockpit-dbus-watch\">watched</a> interfaces is loaded.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-dbus-proxy\"><code>client.proxy()</code></a> and\n<a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a> functions and the\nobjects they return are high level wrappers around the <code>data</code> provided\nby this event.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> has the following form:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>  {\n      \"org.Interface\": {\n          \"methods\": {\n              \"Method1\": {\n                  \"in\": [ \"s\", \"v\" ],\n                  \"out\": [ \"i\" ]\n              },\n              \"Method2\": { }\n          },\n          \"signals\": {\n              \"Signal\": {\n                  \"in\": [ \"b\", \"s\" ]\n              }\n          },\n          \"properties\": {\n              \"Prop1\": {\n                  \"flags\": \"rw\",\n                  \"type\": \"s\"\n              },\n              \"Prop2\": {\n                  \"flags\": \"r\",\n                  \"type\": \"b\"\n              }\n          }\n      }\n  }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Multiple interfaces may be present, each of which may have methods and\nproperties. This is emitted before the first\n<a href=\"#cockpit-dbus-proxy\"><code>client.onnotify</code></a> event for the relevant\ninterface.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-dbus-variant\">cockpit.variant()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>variant = cockpit.variant(type, value)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>A DBus variant is represented as a plain javascript object with a\n<code>\"t\"</code> property represesting the full DBus type of the variant, and a\n<code>\"v\"</code> property containing the variant value.</p>\n</div>\n<div class=\"paragraph\">\n<p>This is a helper function for creating such a variant object.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_js_errors\">cockpit.js: Errors</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>cockpit.js: Errors</p>\n</div>\n<div class=\"paragraph\">\n<p>Problem codes and messages</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-problems\">Problem Codes</h3>\n<div class=\"paragraph\">\n<p>Cockpit represents problems with standardized problem string codes.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"access-denied\"</code></dt>\n<dd>\n<p>The user is not permitted to perform the action in question.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"authentication-failed\"</code></dt>\n<dd>\n<p>User authentication failed.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"internal-error\"</code></dt>\n<dd>\n<p>An unexpected internal error without further info. This should not\nhappen during the normal course of operations.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"no-cockpit\"</code></dt>\n<dd>\n<p>The system does not have a compatible version of Cockpit installed or\ninstalled properly.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"no-session\"</code></dt>\n<dd>\n<p>Cockpit is not logged in.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"not-found\"</code></dt>\n<dd>\n<p>Something specifically requested was not found, such as a file,\nexecutable etc.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"terminated\"</code></dt>\n<dd>\n<p>Something was terminated forcibly, such as a connection, process\nsession, etc.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"timeout\"</code></dt>\n<dd>\n<p>Something timed out.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"unknown-hostkey\"</code></dt>\n<dd>\n<p>The remote host had an unexpected or unknown key.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"no-forwarding\"</code></dt>\n<dd>\n<p>Could not forward authentication credentials to the remote host.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-messages\">cockpit.message()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>message = cockpit.message(problem)\nmessage = cockpit.message(exception)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Return a message for the <code>exception</code> or <code>problem</code> code passed as an\nargument. If the argument is an object with a <code>\"message\"</code> property, as\nis the case with most exceptions, that will be returned directly. If the\nargument is an object with a <code>\"problem\"</code> property, then it will be\nused as the problem code. An appropriate message will be returned for\nproblem codes.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_js_file_access\">cockpit.js: File Access</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The <code>cockpit.file</code> API lets you read, write, and watch regular files\nin their entirety. It cannot efficiently do random access in a big file\nor read non-regular files such as <code>/dev/random</code>.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>file = cockpit.file(path,\n                    { syntax: syntax_object,\n                      binary: boolean,\n                      max_read_size: int,\n                      superuser: string,\n                    })\n\npromise = file.read()\npromise\n    .then((content, tag) =&gt; { ... })\n    .catch(error =&gt; { ... })\n\npromise = file.replace(content, [ expected_tag ])\npromise\n    .then(new_tag =&gt; { ... })\n    .catch(error =&gt; { ... })\n\npromise = file.modify(callback, [ initial_content, initial_tag ]\npromise\n    .then((new_content, new_tag) =&gt; { ... })\n    .catch(error =&gt; { ... })\n\nfile.watch((content, tag, [error]) =&gt; { }, [ { read: boolean } ])\n\nfile.close()</pre>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-file-simple\">Simple reading and writing</h3>\n<div class=\"paragraph\">\n<p>You can read a file with code like this:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.file(\"/path/to/file\").read()\n    .then((content, tag) =&gt; {\n        ...\n    })\n    .catch(error =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>It is recommended to use absolute paths. Relative paths are resolved\nagainst <code>/</code>. To work with the current user&#8217;s files\n<a href=\"#cockpit-user\">cockpit.user()</a> can be used to get the user&#8217;s home\ndirectory.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>read()</code> method returns a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>When successful, the promise will be resolved with the content of the\nfile. Unless you specify options to change this (see below), the file is\nassumed to be text in the UTF-8 encoding, and <code>content</code> will be a\nstring.</p>\n</div>\n<div class=\"paragraph\">\n<p>The tag that is passed to the <code>then()</code> callback is a short string that\nis associated with the file and changes whenever the content of the file\nchanges. It is meant to be used with <code>replace()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>It is not an error when the file does not exist. In this case, the\n<code>then()</code> callback will be called with a <code>null</code> value for <code>content</code>\nand <code>tag</code> is <code>\"-\"</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>superuser</code> option can be used the same way as described in the\n<a href=\"#cockpit-channels-channel\">cockpit.channel()</a> to provide a different\naccess level to the file.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can use the <code>max_read_size</code> option to limit the amount of data\nthat is read. If the file is larger than the given number of bytes, no\ndata is read and the channel is closed with problem code <code>too-large</code>.\nThe default limit is 16 MiB. The limit can be completely removed by\nsetting it to -1.</p>\n</div>\n<div class=\"paragraph\">\n<p>To write to a file, use code like this:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.file(\"/path/to/file\").replace(\"my new content\\n\")\n    .then(tag =&gt; {\n        ...\n    })\n    .catch(error =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <code>replace()</code> method returns a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>When the promise is resolved, the file has been atomically replaced (via\nthe <code>rename()</code> syscall) with the new content. As with <code>read()</code>, by\ndefault the new content is a string and will be written to the file as\nUTF-8. The returned tag corresponds to the new content of the file.</p>\n</div>\n<div class=\"paragraph\">\n<p>When the promise is rejected because of an error, the file or its meta\ndata has not been changed in any way.</p>\n</div>\n<div class=\"paragraph\">\n<p>As a special case, passing the value <code>null</code> to <code>replace()</code> will\nremove the file.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>replace()</code> method can also check for conflicting changes to a\nfile. You can pass a tag (as returned by <code>read()</code> or <code>replace()</code>) to\n<code>replace()</code>, and the file will only be replaced if it still has the\ngiven tag. If the tag of the file has changed, <code>replace()</code> will fail\nwith an error object that has <code>error.problem == \"change-conflict\"</code>.\nSee <code>modify()</code> below for a convenient way to achieve transactional\nupdates to a file.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-file-format\">File format</h3>\n<div class=\"paragraph\">\n<p>By default, a file is assumed to be text encoded in UTF-8, and the\n<code>read()</code> and <code>replace()</code> functions use strings to represent the\ncontent.</p>\n</div>\n<div class=\"paragraph\">\n<p>By specifying the <code>syntax.parser()</code> and <code>syntax.stringify()</code>\noptions, you can cause <code>read()</code> to parse the content before passing it\nback to you, and <code>replace()</code> to unparse it before writing.</p>\n</div>\n<div class=\"paragraph\">\n<p>The main idea is to be able to write <code>{ syntax: JSON }</code>, of course,\nbut you can easily pass in individual functions or make your own\nparser/unparser object:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.file(\"/path/to/file.json\", { syntax: JSON })\n\nvar syntax_object = {\n    parse:     my_parser,\n    stringify: my_unparser\n};\n\ncockpit.file(\"/path/to/file\", { syntax: syntax_object })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Any exceptions thrown by the <code>parse()</code> and <code>stringify()</code> functions\nare caught and reported as read or write errors.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>null</code> value that is used to represent the content of a\nnon-existing file (see \"Simple reading and writing\", above) is not\npassed through the <code>parse()</code> and <code>stringify()</code> functions.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-file-binary\">Binary files</h3>\n<div class=\"paragraph\">\n<p>By default the content of the file is assumed to be text encoded as\nUTF-8 and it can not contain zero bytes. The content is represented as a\nJavaScript string with <code>read()</code>, <code>replace()</code>, etc. By setting the\n<code>binary</code> option to true when creating the proxy, no assumptions are\nplaced on the content, and it is represented as a <code>Uint8Array</code> in\nJavaScript.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-file-atomic\">Atomic modifications</h3>\n<div class=\"paragraph\">\n<p>Use <code>modify()</code> to modify the content of the file safely. A call to\n<code>modify()</code> will read the content of the file, call <code>callback</code> on the\ncontent, and then replace the content of the file with the return value\nof the callback.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>modify()</code> method uses the <code>read()</code> and <code>replace()</code> methods\ninternally in the obvious way. Thus, the <code>syntax.parse()</code> and\n<code>syntax.stringify()</code> options work as expected, <code>null</code> represents a\nnon-existing file, and the watch callbacks are fired.</p>\n</div>\n<div class=\"paragraph\">\n<p>It will do this one or more times, until no other conflicting changes\nhave been made to the file between reading and replacing it.</p>\n</div>\n<div class=\"paragraph\">\n<p>The callback is called like this</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>new_content = callback (old_content)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The callback is allowed to mutate <code>old_content</code>, but note that this\nwill also mutate the objects that are passed to the watch callbacks.\nReturning <code>undefined</code> from the proxy is the same as returning\n<code>old_content</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>modify()</code> method returns a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The promise will be resolved with the new content and its tag, like so</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>function shout(old_content) {\n    return old_content.toUpperCase();\n}\n\ncockpit.file(\"/path/to/file\").modify(shout)\n    .then((content, tag) =&gt; {\n        ...\n    })\n    .catch(error =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If you have cached the last content and tag results of the <code>read()</code> or\n<code>modify()</code> method, or the last values passed to a watch callback, you\ncan pass them to <code>modify()</code> as the second and third argument. In this\ncase, <code>modify()</code> will skip the initial read and start with the given\nvalues.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-file-notify\">Change notifications</h3>\n<div class=\"paragraph\">\n<p>Calling <code>watch()</code> will start monitoring the file for external changes.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>handle = file.watch(callback);\n\nhandle_no_read = file.watch(callback, { read: false });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Whenever a change occurs, the <code>callback()</code> is called with the new\ncontent and tag of the file. This might happen because of external\nchanges, but also as part of calls to <code>read()</code>, <code>replace()</code>, and\n<code>modify()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>When a read error occurs, the <code>callback()</code> is called with an error as\na third argument. Write errors are not reported via the watch callback.</p>\n</div>\n<div class=\"paragraph\">\n<p>Calling <code>watch()</code> will also automatically call <code>read()</code> to get the\ninitial content of the file. Thus, you normally don&#8217;t need to call\n<code>read()</code> at all when using <code>watch()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>To disable the automatic reading, e.g. for large files or unreadable\nfile system objects, set the <code>read</code> option to <code>false</code>. The first\n<code>content</code> argument of the callback will then always be <code>null</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>To free the resources used for monitoring, call <code>handle.remove()</code>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-file-path\">file.path</h3>\n<div class=\"paragraph\">\n<p>A string containing the path that was passed to the <code>cockpit.file()</code>\nmethod.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-file-close\">Closing</h3>\n<div class=\"paragraph\">\n<p>Call the <code>close()</code> method on a file proxy to cancel all ongoing\noperations, such as reading, writing, and monitoring. The proxy should\nnot be used after closing it.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_js_http_client\">cockpit.js: HTTP Client</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit allows access to local HTTP and REST services via this API.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-http-constructor\">cockpit.http()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>http = cockpit.http(endpoint, [options])\nhttp = cockpit.http(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new HTTP client. The <code>endpoint</code> can be a file path starting\nwith <code>/</code> to connect to a unix socket, or it can be a port number to\nconnect to. The optional <code>options</code> argument is a javascript plain\nobject, and may include:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"address\"</code></dt>\n<dd>\n<p>Connect to an address other than localhost. Must be a valid host name\nor IP address. To use this option you also must provide a port number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"port\"</code></dt>\n<dd>\n<p>Port number to use with \"address\" option, when not given in\n<code>endpoint</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"tls\"</code></dt>\n<dd>\n<p>Object properties for an https connection. See\n<code>http-stream2 TLS options</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"headers\"</code></dt>\n<dd>\n<p>Additional HTTP headers to include with the HTTP request. This is a\nplain javascript object with each key as a header name, and each value\nas the header value.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to open this channel as root. If the currently\nlogged in user is not permitted to become root (eg: via <code>pkexec</code>)\nthen the <code>channel</code> will immediately be\n<a href=\"#cockpit-channels-close-ev\">closed</a> with a <code>\"access-denied\"</code>\nproblem code.\n+\nSet to <code>\"try\"</code> to try to make the request as root, but if that\nfails, fall back to perform an unprivileged request.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"tls\"</code></dt>\n<dd>\n<p>If set to a plain javascript object, then the connection will be an\nHTTPS connection and include TLS encryption. The fields of the <code>tls</code>\nobject declare various TLS configuration and data. All fields are\noptional:\n+</p>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><code>\"authority\"</code>: Certificate authority(s) to expect as signers of\nthe server&#8217;s TLS certificate, represented as a plain javascript\nobject. It should have either a <code>\"file\"</code> field containing a readable\nPEM file on the system containing authorities, or a <code>\"data\"</code> with\nPEM encoded certificate data.</p>\n</li>\n<li>\n<p><code>\"certificate\"</code>: A client certificate to use, represented as a\nplain javascript object. It should have either a <code>\"file\"</code> field\ncontaining a readable PEM file on the system to use as a certificate,\nor a <code>\"data\"</code> with PEM encoded certificate data.</p>\n</li>\n<li>\n<p><code>\"key\"</code>: A client key to use, represented as a plain javascript\nobject. It should have either a <code>\"file\"</code> field containing a readable\nPEM file on the system to use as a key, or a <code>\"data\"</code> with PEM\nencoded key data.</p>\n</li>\n<li>\n<p><code>\"validate\"</code>: A boolean that describes whether to validate the\nserver&#8217;s TLS certificate or not. By default local connections are not\nvalidated, and remote connections are validated.</p>\n</li>\n</ul>\n</div>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Here is a somewhat complex example of using most of the above\n<code>options</code> when when calling <code>cockpit.http()</code>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>http = cockpit.http({\n    \"address\": \"localhost\",\n    \"headers\": {\n        \"Authorization\": \"Basic dXNlcjpwYXNzd29yZA==\"\n    },\n    \"port\": 443,\n    \"tls\": {\n        \"validate\": true,\n        \"authority\": {\n            \"file\": \"/etc/pki/tls/certs/ca-bundle.crt\",\n        },\n        \"certificate\": {\n            \"data\": \"-----BEGIN CERTIFICATE-----\\nMIIDsDCCA...\"\n        },\n        \"key\": {\n            \"data\": \"-----BEGIN RSA PRIVATE KEY-----\\nMIIEogIBA...\"\n        }\n    }\n});</pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-http-get\">http.get()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request = http.get(path, [params, [headers]])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Perform an HTTP GET request for the given <code>path</code>. If the <code>params</code> is\nspecified it should be a plain javascript object, which will be turned\ninto a query string.</p>\n</div>\n<div class=\"paragraph\">\n<p>Optionally a plain javascript object containing headers can be included\nin the <code>headers</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>The return value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete if the request happens successfully, or fail if\nthere&#8217;s a problem.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-http-post\">http.post()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request = http.post(path, body, [headers])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Perform an HTTP POST request for the given <code>path</code>. The <code>body</code> can be\na string, or a javascript plain object, which will be encoded as JSON\ndata. If <code>body</code> is <code>undefined</code> or <code>null</code> then an empty HTTP body\nwill be sent.</p>\n</div>\n<div class=\"paragraph\">\n<p>Optionally a plain javascript object containing headers can be included\nin the <code>headers</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>The return value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete if the request happens successfully, or fail if\nthere&#8217;s a problem.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-http-request\">http.request()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request = http.request(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Perform an HTTP request. The <code>options</code> can contain the following:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"body\"</code></dt>\n<dd>\n<p>The HTTP request body. If you do not specify a body, then you must\ncall <a href=\"#cockpit-http-input\">request.input()</a> to complete the body\nand allow the request to start.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"headers\"</code></dt>\n<dd>\n<p>A javascript plain object containing HTTP headers.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"method\"</code></dt>\n<dd>\n<p>The HTTP method. Defaults to <code>\"GET\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"params\"</code></dt>\n<dd>\n<p>A javascript plain object containing query string parameters.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"path\"</code></dt>\n<dd>\n<p>The HTTP path. Defaults to <code>/</code>.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The return value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete if the request happens successfully, or fail if\nthere&#8217;s a problem.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-http-then\">request.then()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.then(data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the request finishes\nsuccessfully.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> argument contains the body result of the request. If it a\nstring, unless the process was opened in binary mode, in which case the\n<code>data</code> is an array of bytes. If a <code>request.stream()</code> handler is set\nup, then any standard output data consumed by the handler will not be\nincluded in the <code>data</code> argument.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-http-catch\">request.catch()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.catch((exception[, data]) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the request fails, or\nreturns an error code.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>exception</code> object passed to the handler can have the following\nfields:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>problem</code></dt>\n<dd>\n<p>A <a href=\"#cockpit-problems\">problem code</a> string when a problem occurred\nstarting or communicating with the server. This is <code>null</code> if the\nprocess exited or was terminated.</p>\n</dd>\n<dt class=\"hdlist1\"><code>status</code></dt>\n<dd>\n<p>The numeric status of the response. This is <code>null</code> if no response\nwas received.</p>\n</dd>\n<dt class=\"hdlist1\"><code>reason</code></dt>\n<dd>\n<p>A string reason returned in the response. This is <code>null</code> if no\nresponse was received.</p>\n</dd>\n<dt class=\"hdlist1\"><code>message</code></dt>\n<dd>\n<p>A string message returned in the response. This is <code>null</code> if no\nresponse was received.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>If the request returned a response body, it will be available in the\n<code>data</code> argument. Otherwise this argument will be <code>undefined</code>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-http-response\">request.response()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.response((status, headers) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This sets up a handler to be called when the HTTP request gets the\ninitial response from the server. The <code>status</code> argument is the HTTP\nstatus integer, and the <code>headers</code> is a plain javascript object\ncontaining the headers of the response.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-http-stream\">request.stream()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.stream(data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This sets up a handler to be called when the request returns output\ndata. The handler will be called multiple times.</p>\n</div>\n<div class=\"paragraph\">\n<p>Only one handler may be registered at a time. Registering an additional\nhandler replaces the previous one. The handler receives either string\n<code>data</code> or an array of binary bytes as its argument. A stream handler\nmay return a number, which indicates the number of characters or bytes\nconsumed from <code>data</code>. Any data not consumed will be included again the\nnext time the handler is called.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>request.stream()</code> handler is set up, then the <code>request.then()</code>\nhandlers will only get any remaining data not consumed by the stream\nhandler.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-http-input\">request.input()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.input(data, [stream])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This method writes <code>data</code> to the HTTP request body. It is only valid\nif no <code>\"body\"</code> has been specified in\n<a href=\"#cockpit-http-request\">http.request()</a> options. If <code>stream</code> is\n<code>true</code> then this function can be called again to provide further data.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-http-close\">request.close()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cancel the request. If <code>problem</code> is specified it should be a standard\n<a href=\"#cockpit-problems\">problem code</a> string.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-http-close-all\">http.close()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>http.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cancel all outstanding requests with the given problem code. This is\nuseful when you know that the server is going down soon.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_js_localization\">cockpit.js: Localization</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit provides a <a href=\"https://www.gnu.org/software/gettext/\"><code>gettext()</code></a>\nlike API for easy translation of strings.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-locale-language\">cockpit.language</h3>\n<div class=\"paragraph\">\n<p>The current locale language code. This is set based on the\n<a href=\"#cockpit-locale-locale\"><code>cockpit.locale()</code></a> data loaded.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-locale-locale\">cockpit.locale()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.locale(po)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Load locale information for a given <code>po</code> data. The data should be JSON\ndata in the <a href=\"https://www.npmjs.org/package/po2json\">po2json</a> format. The\ndata will be loaded globally. If <code>po</code> data has already been loaded,\nthen this will extend that loaded data with additional strings. Any\nidentical translations strings will be replaced with the new strings. A\n<code>null</code> argument clears all the locale information previously loaded.</p>\n</div>\n<div class=\"paragraph\">\n<p>Various methods such as\n<a href=\"#cockpit-locale-gettext\"><code>cockpit.gettext()</code></a> make use of the\nloaded data.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-locale-gettext\">cockpit.gettext()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>translated = cockpit.gettext([context], string)\nvar _ = cockpit.gettext\nvar C_ = cockpit.gettext\ntranslated = _(\"string\")\ntranslated = C_(\"context\", \"string\")</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Lookup <code>string</code> for translation in the loaded locale data. The\ntranslated string will be returned, or <code>string</code> will be returned if no\nsuch translated string is present. The <code>context</code> argument is an\noptional string used to qualify the string.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function can be assigned to a variable called <code>_</code> (underscore)\nwhich will make your code work with the typical <code>_(\"string\")</code> syntax.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-locale-noop\">cockpit.noop()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>var N_ = cockpit.noop\nvar NC_ = cockpit.noop</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>A noop function suitable for assigning to <code>N_</code> or <code>NC_</code> so that\ngettext scanners will be able to find translatable strings. More\nspecifically this function returns its last argument.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-locale-ngettext\">cockpit.ngettext()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>translated = cockpit.ngettext([context], string1, stringN, number)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Lookup a string appropriate for a pluralization form of the <code>number</code>.\nVarious languages have complex pluralization forms that go far between\nthe singular and plural forms speakers of English are familiar with. If\nno such translated string is found then either one of <code>string1</code> or\n<code>stringN</code> is returned according to simple pluralization rules.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>context</code> argument is an optional string used to qualify the\nstring.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-locale-translate\">cockpit.translate()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.translate()\ncockpit.translate(element, ...)\ncockpit.translate(selection)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The document will be scanned for <code>translate</code> tags and they will be\ntranslated according to the strings in loaded locale data. One or more\n<code>element</code> arguments may be specified. These are DOM elements for\nspecific parts of the document to be translated. If no <code>element</code> is\nspecified then the entire document is translated.</p>\n</div>\n<div class=\"paragraph\">\n<p>If an array or array-like object is passed as a <code>selection</code> then all\nDOM elements in the array will be treated as parts of the document to be\ntranslated.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_js_page_location_and_jumping\">cockpit.js: Page Location and Jumping</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Page location and navigation between components</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-location-general\">Page location</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>location = cockpit.location\ncockpit.location = \"/path\"</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit components often have different views, without changing the HTML\nfile that is being viewed. These are known as pages.\n<code>cockpit.location</code> is an object that can be used to read the current\npage and to navigate to a different page location. It works by updating\n<code>window.location.hash</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>cockpit.location</code> looks like a HTTP path with a possible query\nstring:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>/path/sub/page?option=value,option2</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-location-path\"><code>location.path</code></a> and\n<a href=\"#cockpit-location-options\"><code>location.options</code></a> contain a parsed\nform of the location. While the location cannot be modified in place, a\nnew one can be created by assigning a string to <code>cockpit.location</code> or\nby calling the <a href=\"#cockpit-location-go\"><code>location.go()</code></a> function.</p>\n</div>\n<div class=\"paragraph\">\n<p><code>cockpit.location</code> is designed similarly to <code>window.location</code> in\nthat the location object is preplaced whenever the current page location\nchanges. To be aware of when the page location changes listen for the\n<a href=\"#cockpit-location-changed\"><code>cockpit.onlocationchanged</code></a> event.</p>\n</div>\n<div class=\"paragraph\">\n<p>Using the location object as a string will result in the\n<a href=\"#cockpit-location-href\"><code>location.href</code></a>.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-location-href\">location.href</h4>\n<div class=\"paragraph\">\n<p>The string representation of this page location, including any options.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-location-path\">location.path</h4>\n<div class=\"paragraph\">\n<p>An array of path segments, parsed and decoded appropriately. An empty\narray denotes the root path.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-location-options\">location.options</h4>\n<div class=\"paragraph\">\n<p>A javascript object containing the various options present in the\nlocation.</p>\n</div>\n<div class=\"paragraph\">\n<p>If an option appears more than once, its value will be an array.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-location-go\">location.go()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>location.go(path, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Changes the current location to the given <code>path</code> and <code>options</code>. If\nthe <code>path</code> argument is a string, it will be parsed into a path. If it\nis a relative path, then the result will be relative to the current\n<code>location.path</code>. If the <code>path</code> argument is an array of path\nsegments, it will be treated as a full parsed absolute path.</p>\n</div>\n<div class=\"paragraph\">\n<p>Any options found in a <code>path</code> will be added to those in the optional\n<code>options</code> argument, and used in the result.</p>\n</div>\n<div class=\"paragraph\">\n<p>The location change will only take effect if the location has not\nchanged in the meantime. This can be to good effect by saving a\n<code>cockpit.location</code> object and doing a conditional navigation, by\ncalling the saved <code>location.go()</code> method later. This will only\nnavigate if the user or other code has not navigated in the meantime.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-location-replace\">location.replace()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>location.replace(path, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Similar to <a href=\"#cockpit-location-go\"><code>location.go()</code></a> except the\nlocation change will not result in a navigation change in the browser&#8217;s\nhistory.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-location-decode\">location.decode()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>path = location.decode(href, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Decode a cockpit href into its <code>path</code> array. If the <code>options</code>\nargument is specified, then it will be populated with options found in\nthe href.</p>\n</div>\n<div class=\"paragraph\">\n<p>If href is a relative path it will be resolved relative to\n<code>location.href</code>.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-location-encode\">location.encode()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>href = location.encode(path, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Encode the given <code>path</code> and <code>options</code> into a cockpit href. The\n<code>path</code> argument may be an array of path segments, or a string path. If\na relative path is passed, it will be resolved relative to\n<code>location.href</code>.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-location-changed\">cockpit.onlocationchanged</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.addEventListener(\"locationchanged\", function() { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event emitted when over the <code>cockpit.location</code> changes. Typically a\ncomponent reacts to this event by updating its interface to reflect the\nnew <a href=\"#cockpit-location-path\"><code>cockpit.location.path</code></a> and\n<a href=\"#cockpit-location-options\"><code>cockpit.location.options</code></a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This event is not triggered immediately during a <code>location.go()</code> or\nsimilar call. It will be triggered asynchronously at a later time.</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-jump\">Jumping between components</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.jump(\"/system/log\")</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>In Cockpit in there multiple components shown. In order to tell Cockpit\nto jump to and show another component and a certain location within that\ncomponent, use the <code>cockpit.jump()</code> function. Stable component paths\nare documented. Don&#8217;t assume you can navigate into paths that are not\nstable API.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-jump-jump\">cockpit.jump()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.jump(path, [ host ])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Ask Cockpit to jump to another component. The location of the current\ncomponent will not be affected. The <code>path</code> argument can be a string\npath, starting with <code>/</code> or an array containing the parts of a path\nthat will be joined to create a path. If <code>host</code> is not specified, then\nthe component on the same host as the caller will be displayed. If host\nis null, then the host portion of the path will be removed, displaying\nthe component on the host that cockpit is connected directly to.</p>\n</div>\n<div class=\"paragraph\">\n<p>If the calling component is not running within Cockpit, or the calling\ncomponent is not currently displayed, then the jump will not happen, and\nthis function has no effect.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-jump-hidden\">cockpit.hidden</h4>\n<div class=\"paragraph\">\n<p>A boolean property that indicates if the current component page is\nvisible or hidden. When the code or user jumps to another component, the\nprior one remains loaded and initialized but is hidden. Use this\nproperty together with the\n<a href=\"#cockpit-jump-visibilitychange\"><code>cockpit.onvisibilitychange</code></a>\nevent to decide whether or not to perform expensive tasks to update the\ninterface.</p>\n</div>\n<div class=\"paragraph\">\n<p>This property is analogous to the <code>document.hidden</code> page visibility\nAPI, but works with the document and frame implementation of Cockpit.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-jump-visibilitychange\">cockpit.onvisibilitychange</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.onvisibilitychange = function() { ... }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when the\n<a href=\"#cockpit-jump-hidden\"><code>cockpit.hidden</code></a> property changes. This\nevent is similar to the <code>document.onvisibilitychange</code> API, but works\nwith the document and frame implementation of Cockpit.</p>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_js_user_session\">cockpit.js: User Session</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>User information and login session state</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-logout\">cockpit.logout()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.logout([reload])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Logout of Cockpit. Unless <code>reload</code> is <code>false</code> this will also cause\nthe page to be reloaded, so that the user can see the logged out state.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-user\">cockpit.user()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>var promise = cockpit.user();\npromise.then(user =&gt; { ... });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This object contains information about the user that&#8217;s currently logged\ninto cockpit. The following fields are defined:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"id\"</code></dt>\n<dd>\n<p>This is unix user id.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"gid\"</code></dt>\n<dd>\n<p>This is unix user group id.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"name\"</code></dt>\n<dd>\n<p>This is the unix user name like <code>\"root\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"full_name\"</code></dt>\n<dd>\n<p>This is a readable name for the user.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"groups\"</code></dt>\n<dd>\n<p>This is an array of group names to which the user belongs. Since\nversion 318, the first item in this list is the primary group.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"home\"</code></dt>\n<dd>\n<p>This is user&#8217;s home directory.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"shell\"</code></dt>\n<dd>\n<p>This is unix user shell.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Returns a promise that completes once the user information is available.</p>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p><code>cockpit.user()</code> is soft-deprecated since Cockpit 336, if your page\ndoes not need to maintain compatibility with older Cockpit versions you\ncan use<a href=\"#cockpit-info\">cockpit.info</a> to obtain the user information.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-permission\">Permission lookup</h3>\n<div class=\"paragraph\">\n<p>Cockpit provides a mechanism for checking if the current user satisfies\na given criteria. This is meant for updating UI elements based on what\nactions the user can perform. It is <em>not an access control mechanism</em>.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-permission-constructor\">cockpit.permission()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>permission = cockpit.permission([options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new permission object to check if the current user has a\nparticular permission specified by <code>options</code>:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>admin: true</code></dt>\n<dd>\n<p>True if the session has superuser privileges, i.e. can run channels as\nroot with <code>{ superuser: \"require\" }</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>group:</code> <em>name</em></dt>\n<dd>\n<p>True if the currently logged user is a member of group <em>name</em>.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The permission result is always true for the \"root\" user. When\n<code>options</code> is not given, check if the current user is root.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-permission-allowed\">permission.allowed</h4>\n<div class=\"paragraph\">\n<p>A boolean value which indicates if the permission is allowed or not.\nThis will be <code>null</code> if the permission is unknown, or there was an\nerror checking the permission or the permission data has not yet loaded.\nThis property will update asynchronously and if you wish to be notified\nof changes connect to the\n<a href=\"#cockpit-permission-changed\">permission.onchanged</a> event.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-permission-changed\">permission.onchanged</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>permission.addEventListener(\"changed\", function() { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is fired when the permission changes. In particular the\n<a href=\"#cockpit-permission-allowed\">permission.allowed</a> property.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-permission-close\">permission.close()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>permission.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Closes the permission object and tears down any registered callbacks and\ndbus subscriptions.</p>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_js_manifests\">cockpit.js: Manifests</h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"cockpit-manifest-loading\">Loading Manifests</h3>\n<div class=\"paragraph\">\n<p>For a convenient access to all page manifests, include\n<code>&lt;script src=\"../manifests.js\"&gt;&lt;/script&gt;</code> into your page to register\nthe manifests at the <code>cockpit.manifests</code> global variable.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can also load <code>../manifests.json</code> directly in your page, with\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch\"><code>fetch()</code></a>.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_js_metrics\">cockpit.js: Metrics</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Metrics about the system can be retrieved from several sources using\n<a href=\"#cockpit-metrics\"><code>cockpit.metrics()</code></a> metrics channels. The\nmetrics are made available as series data, and can be used with the\n<a href=\"#cockpit-series\"><code>cockpit.series()</code></a> and\n<a href=\"#cockpit-grid\"><code>cockpit.grid()</code></a> facilities.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-metrics-function\">cockpit.metrics()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics = cockpit.metrics(interval, options, cache)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Opens a new metrics channel. The data retrieved will be available in the\n<a href=\"#cockpit-metrics-series\"><code>metrics.series</code></a> series sink, and can be\nused together with <a href=\"#cockpit-grid\"><code>cockpit.grid()</code></a> objects.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>interval</code> is in milliseconds, and is the granularity of the\nseries data retrieved. Any grids consuming the data must have the same\ninterval.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>cache</code> argument is a cache identifier. If specified, then this\nmetrics channel will share data with other metrics channels of the same\nidentifier. Make sure to use a globally unique string.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> argument is either a javascript plain object, or an\narray of those. Each object can have the following fields.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"metrics\"</code></dt>\n<dd>\n<p>An array of full metric descriptions, as javascript objects. The\nspecifics of these, and how to determine which ones to use, can\nunfortunately only be found in the low-level protocol documentation.\nThis option is required.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"source\"</code></dt>\n<dd>\n<p>The source to use for real-time data. This is used by the <code>follow</code>\nmethod, see below. Set to <code>\"internal\"</code> to retrieve internal metrics\nread by the bridge. If set to <code>\"direct\"</code> or <code>\"pmcd\"</code> then data\nwill be retrieved from <a href=\"https://pcp.io\">PCP</a>if it is available. The\ndefault is <code>\"internal\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"archive_source\"</code></dt>\n<dd>\n<p>The source to use for retrieving historical data. This is used by the\n<code>fetch</code> method, see below. Set to <code>\"pcp-archive\"</code> to retrieve data\nfrom PCP archives. The default is not to try to retrieve historical\ndata.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>When the <code>options</code> argument is an array of javascript objects, then\nthe metrics channel tries to use them in order until one succeeds. This\nway, you can prefer PCP as the source but fall back to internal metrics\nwhen PCP is not available, for example. The channel gives no indication\nwhich of the options has been used, and <code>fetch</code> and <code>follow</code> might\nuse different entries from the list.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-metrics-fetch\">metrics.fetch()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.fetch(beg, end)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Retrieve archived metrics data between <code>beg</code> and <code>end</code>. The\narguments can either be numbers, in which case they are interval based\noffsets, or they can be javascript Date objects.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-metrics-follow\">metrics.follow()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.follow()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Start retrieving live metrics data as it become available.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-metrics-close\">metrics.close()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Stop the retrieval of metrics and release resources.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-metrics-series\">metrics.series</h3>\n<div class=\"paragraph\">\n<p>The series sink where data retrieved data will be processed.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-metrics-meta\">metrics.meta</h3>\n<div class=\"paragraph\">\n<p>The metrics meta data last received.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-metrics-onchanged\">metrics.onchanged</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.onchanged = function() { }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when one of the properties on this metrics object\nchanges.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_js_series_data\">cockpit.js: Series Data</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Series data consists of values along a continuous (usually time) axis.\nWe can place these in grids which expose a distinct subset of these\nvalues. These are the underlying mechanism for displaying metrics data\nin graphs.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-grid\">cockpit.grid()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid = cockpit.grid(interval, [beg, end])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Creates a grid object to contain series data.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>interval</code> is the granularity of the grid. Usually this is a\nnumber of milliseconds, when used with time series data. The <code>beg</code> and\n<code>end</code> are the bounds of the grid. If omitted they will be set to zero\nfor an initially empty grid.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>beg</code> and/or <code>end</code> are negative (including negative zero) then\nthey are interpreted in number of intervals relative to the current\ntime. Thus cockpit.grid(1000, -300, -0) will create a grid for the most\nrecent 5 minutes.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-grid-add\">grid.add()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>row = grid.add(series, path)\nrow = grid.add(callback, [early])\nrow = grid.add()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Adds a row to the grid. The returned <code>row</code> is a Javascript array that\nwill contain series data. The arguments control how the row is populated\nfrom the series data. The <code>row</code> is a sparse array. Its <code>row.length</code>\nwill not match the expected size of the grid, unless and until the row\nhas been completely filled in. The first index of the <code>row</code> will\ncontain the data from the series data at the\n<a href=\"#cockpit-grid-beg\"><code>grid.beg</code></a> offset.</p>\n</div>\n<div class=\"paragraph\">\n<p>When no arguments are passed, an empty row is added, and it is not\npopulated with data.</p>\n</div>\n<div class=\"paragraph\">\n<p>When called with a <code>series</code> and <code>path</code> argument then the row will be\npopulated directly with series data. The <code>series</code> can either be a\n<a href=\"#cockpit-series\">series object</a> or an object that has an\n<code>obj.series</code> property. The <a href=\"#cockpit-series-interval\">series\ninterval</a> must match the interval of this grid. If <code>path</code> is missing\nor empty, then the series data is placed into the row directly.\nOtherwise <code>path</code> indicates which part of the series data to place in\nthe row. When <code>path</code> is an array, it is used as a set of property\nnames or array indexes to follow into nested series data. When <code>path</code>\nis a dotted string, it is split and used the same way to locate the\ncorrect value in nested series data. The exact format of the series data\ndepends on its producer, and relevant paths will be documented there.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>callback</code> function is specified, then it will be invoked to\nprovide series data for the row. The function is invoked as\n<code>callback(row, index, count)</code>, where the <code>row</code> is the row to fill\nin, the <code>index</code> is the index to start filling in and <code>count</code> is the\nnumber of items to fill in. The <code>this</code> variable will be set to the\ngrid while invoking the <code>callback</code>. The callback is called after other\ndata rows for a given series have been filled in. Callbacks are called\nin the order added, unless the <code>early</code> argument is set to <code>true</code>, in\nwhich case the callback is called earlier than callbacks without the\n<code>early</code> argument set.</p>\n</div>\n<div class=\"paragraph\">\n<p>To remove the row use the <a href=\"#cockpit-grid-remove\"><code>grid.remove()</code>\nmethod.</a></p>\n</div>\n<div class=\"paragraph\">\n<p>The row will start being populated with data when the <code>series</code>\nproduces data. To make this happen right away, use the\n<a href=\"#cockpit-grid-sync\"><code>grid.sync()</code></a> method.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-grid-remove\">grid.remove()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.remove(row)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Remove a previously added <code>row</code> from the grid. The row will no longer\nbe updated with series data.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-grid-sync\">grid.sync()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.sync()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Load or reload data from the series into the rows. This does not clear\nthe rows before populating them. Some data may be populated immediately,\nothers may have to wait until data can be loaded. Internally this\nfunction calls <a href=\"#cockpit-series-load\"><code>series.load()</code></a> for each\nseries.</p>\n</div>\n<div class=\"paragraph\">\n<p>All rows with callbacks will be invoked to regenerate all the data. The\n<a href=\"#cockpit-grid-onnotify\"><code>grid.onnotify</code></a> event will be triggered.\nIt is not necessary to call this function after a call of the\n<a href=\"#cockpit-grid-move\"><code>grid.move()</code></a> method.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-grid-move\">grid.move()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.move(beg[, end])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Move the grid to new <code>beg</code> and <code>end</code> range. Data will be discarded\nfrom the rows and <a href=\"#cockpit-grid-sync\"><code>grid.sync()</code></a> will be\ncalled to load or reload series data for the new range of offsets.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>end</code> is not specified it will be set to <code>beg</code>. If <code>beg</code> and/or\n<code>end</code> are negative (including negative zero) then they will be set to\nthe number of intervals prior to the current time taken as an interval.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>beg</code> and/or <code>end</code> are negative (including negative zero) then\nthey are interpreted in number of intervals relative to the current\ntime. Thus cockpit.grid(1000, -300, -0) will create a grid for the most\nrecent 5 minutes.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-grid-walk\">grid.walk()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.walk()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Move the grid forward every\n<a href=\"#cockpit-grid-interval\"><code>grid.interval</code></a> milliseconds. To stop\nmoving forward, call <a href=\"#cockpit-grid-move\"><code>grid.move()</code></a>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-grid-notify\">grid.notify()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.notify(index, count)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This function is called to have rows with callbacks recalculate their\ndata. It is not normally necessary to call this function, as it will be\ninvoked automatically when new series data is available or has been\nloaded. This function triggers the\n<a href=\"#cockpit-grid-onnotify\"><code>grid.onnotify</code></a> event.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-grid-onnotify\">grid.onnotify</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.addEventListener(\"notify\", function(index, count) { ... });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event that is triggered when some part of the series data in grid\nchanges. The <code>index</code> is the row index where things changed, and the\n<code>count</code> is the length of the data that changed.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-grid-close\">grid.close()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the grid, and stop updating the rows.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-grid-interval\">grid.interval</h3>\n<div class=\"paragraph\">\n<p>The granularity of the grid. For time series data this is an interval in\nmilliseconds. In order to use a given <a href=\"#cockpit-grid\">grid</a> and\n<a href=\"#cockpit-series\">series</a> together, their interval properties must\nmatch.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-grid-beg\">grid.beg</h3>\n<div class=\"paragraph\">\n<p>The beginning offset of the series data in the grid. Do not set this\nproperty directly. Use the <a href=\"#cockpit-grid-move\">grid.move()</a> method\ninstead.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-grid-end\">grid.end</h3>\n<div class=\"paragraph\">\n<p>The ending offset of the series data in the grid. Do not set this\nproperty directly. Use the <a href=\"#cockpit-grid-move\">grid.move()</a> method\ninstead.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-series\">cockpit.series()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>series = cockpit.series(interval, [cache, fetch])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new sink of series data. This is usually done by producers of\nseries data, and it is rare to invoke this function directly.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>interval</code> is the granularity of the series data. For time series\ndata this is an interval in milliseconds. If a <code>cache</code> string is\nspecified, series data will be cached across frames for series with the\nsame <code>cache</code> cache identifier to load and/or reload.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>fetch</code> callback is specified, then it will be invoked when grids\nrequest certain ranges of data. The <code>fetch</code> callback is invoked with\n<code>function fetch(beg, end) { ... }</code> range offsets. The\n<a href=\"#cockpit-series-input\">series.input()</a> should be called with data\nretrieved, either immediately or at a later time. The callback may be\ncalled multiple times for the same ranges of data. It is up to the\ncallback to determine when or whether it should retrieve the data more\nthan once.</p>\n</div>\n<div class=\"paragraph\">\n<p>A producer of series data, usually calls this function and creates\nitself a <code>obj.series</code> property containing this series object.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-series-input\">series.input()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>series.input(beg, items[, mapping])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Send series data into the series sink. Any grids that have added rows\nbased on this series, will have data filled in. The <code>beg</code> is the\nbeginning offset of <code>items</code>. The <code>items</code> are an array one or more\nseries data items.</p>\n</div>\n<div class=\"paragraph\">\n<p>Producers may wish to provide additional properties that can be used in\nlookup paths that rows can pull from. This is done in the <code>mapping</code>\nargument. If specified it is a tree of objects. Each sub object should\nhave a property with the name <code>\"\"</code> empty string, which will be used as\nthe property name or index in place of the one used in the lookup path.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-series-load\">series.load()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>series.load(beg, end)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Load data from the series into any grids that have rows based on this\nseries data. Any cached data will be filled in immediately. Any data not\ncached, will be requested from the producer, if possible, and may arrive\nat a later time.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>beg</code> and <code>end</code> denote the range of data to load.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-series-interval\">series.interval</h3>\n<div class=\"paragraph\">\n<p>The granularity of the series. For time series data this is an interval\nin milliseconds. In order to use a given <a href=\"#cockpit-grid\">grid</a> and\n<a href=\"#cockpit-series\">series</a> together, their interval properties must\nmatch.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-series-limit\">series.limit</h3>\n<div class=\"paragraph\">\n<p>The maximum number of items to cache for loading and/or reloading. You\ncan change this value to a different number. Having a number close to\nzero will break certain usage of grids, such as\n<a href=\"#cockpit-grid-walk\"><code>grid.walk()</code></a>.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_js_spawning_processes\">cockpit.js: Spawning Processes</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>This is the API for spawning a process and receiving its output, as well\nas exit codes.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-spawn-spawn\">cockpit.spawn()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process = cockpit.spawn(args, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Spawns a process on the system.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>args</code> should be an array starting with the executable and\ncontaining all the arguments to pass on the command line. If <code>args</code> is\na string then it is interpreted as an executable name. The optional\n<code>options</code> argument is a javascript plain object and can contain any of\nthe following fields:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"binary\"</code></dt>\n<dd>\n<p>If set to <code>true</code> then handle the input and output of the process as\narrays of binary bytes.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"directory\"</code></dt>\n<dd>\n<p>The directory to spawn the process in.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"err\"</code></dt>\n<dd>\n<p>Controls where the standard error is sent. By default it is logged to\nthe journal. If set to <code>\"out\"</code> it is included in with the output\ndata. If set to <code>\"ignore\"</code> then the error output is discarded. If\nset to <code>\"message\"</code>, then it will be returned as the error message.\nWhen the <code>\"pty\"</code> field is set, this field has no effect.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"environ\"</code></dt>\n<dd>\n<p>An optional array that contains strings to be used as additional\nenvironment variables for the new process. These are <code>\"NAME=VALUE\"</code>\nstrings.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"pty\"</code></dt>\n<dd>\n<p>Launch the process in its own PTY terminal, and send/receive terminal\ninput and output.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"batch\"</code></dt>\n<dd>\n<p>Batch data coming from the process in blocks of at least this size.\nThis is not a guarantee. After a short timeout the data will be sent\neven if the data doesn&#8217;t match the batch size. Defaults to zero.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"latency\"</code></dt>\n<dd>\n<p>The timeout for flushing any cached data in milliseconds.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to spawn the process as root instead of the\nlogged in user. If the currently logged in user is not permitted to\nbecome root (eg: via <code>pkexec</code>) then the <code>client</code> will immediately\nbe <a href=\"#cockpit-dbus-onclose\">closed</a> with a <code>\"access-denied\"</code>\nproblem code.\n+\nSet to <code>\"try\"</code> to try to run the process as root, but if that fails,\nfall back to an unprivileged process.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The spawned process is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">promise</a>\nthat will complete if the process exits successfully, or fail if there&#8217;s\na problem. Some additional methods besides the standard promise methods\nare documented below.</p>\n</div>\n<div class=\"paragraph\">\n<p>The standard output of the process is made available via the spawned\nprocess object. Any non-UTF8 output from the process will be coerced\ninto textual form. It is highly recommended that only textual output be\nproduced by the command. The standard error is logged to the journal.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-spawn-script\">cockpit.script()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process = cockpit.script(script, [args], [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Run a shell script on the system.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function <a href=\"#cockpit-spawn-spawn\">spawns</a> a Bourne shell script\nprocess. The full text of the <code>/bin/sh</code> shell script should be passed\nin as the first argument. The <code>args</code> can be an array of arguments, not\nincluding the executable, which are passed to the script as <code>$1</code>,\n<code>$2</code> and so on. Shebang options are not used or respected.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> is an optional javascript plain object and can include\nany of the fields listed for the\n<a href=\"#cockpit-spawn-spawn\"><code>cockpit.spawn()</code></a> function.</p>\n</div>\n<div class=\"paragraph\">\n<p>The spawned process is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">promise</a>\nthat will complete if the script exits successfully, or fail if there&#8217;s\na problem. Some additional methods besides the standard promise methods\nare documented below.</p>\n</div>\n<div class=\"paragraph\">\n<p>The standard output of the process is made available via the spawned\nprocess object. Any non-UTF8 output from the process will be coerced\ninto textual form. It is highly recommended that only textual output be\nproduced by the command. The standard error is logged to the journal by\ndefault.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-spawn-then\">process.then()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.then((data[, message]) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">promise</a>\nmethod. It sets up a handler to be called when the process finishes\nsuccessfully.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> argument contains the standard output of the process. If it\na string, unless the process was opened in binary mode, in which case\nthe <code>data</code> is an array of bytes. If a <code>process.stream()</code> handler is\nset up, then any standard output data consumed by the handler will not\nbe included in the <code>data</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>If the process was spawned with the <code>\"err\"</code> option set to\n<code>\"message\"</code> then the second argument will contain the standard error\noutput of the process.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-spawn-catch\">process.catch()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.catch((exception[, data]) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the process fails,\nterminates or exits.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>exception</code> object passed to the handler can have the following\nfields:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>message</code></dt>\n<dd>\n<p>A message describing the exception. If the process was spawned with\nthe <code>\"err\"</code> option set to <code>\"message\"</code> then the second argument\nwill contain the standard error output of the process.</p>\n</dd>\n<dt class=\"hdlist1\"><code>problem</code></dt>\n<dd>\n<p>A <a href=\"#cockpit-problems\">problem code</a> string when a problem occurred\nstarting or communicating with the process. This is <code>null</code> if the\nprocess exited or was terminated.</p>\n</dd>\n<dt class=\"hdlist1\"><code>exit_status</code></dt>\n<dd>\n<p>The numeric exit status of the process. This is <code>null</code> if the\nprocess did not exit.</p>\n</dd>\n<dt class=\"hdlist1\"><code>exit_signal</code></dt>\n<dd>\n<p>A string representing a unix signal that caused the process to\nterminate. This is <code>null</code> if the process did not terminate because\nof a signal.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>If the process actually ran and produced output before failing, it will\nbe available in the <code>data</code> argument. Otherwise this argument will be\n<code>undefined</code>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-spawn-stream\">process.stream()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.stream(data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This sets up a handler to be called when the process has standard\noutput. The handler will be called multiple times. The handler will be\ncalled regardless of whether the process ends up exiting successfully or\nnot.</p>\n</div>\n<div class=\"paragraph\">\n<p>Only one handler may be registered at a time. Registering an additional\nhandler replaces the previous one. The handler receives either string\n<code>data</code> or an array of binary bytes as its argument. A stream handler\nmay return a number, which indicates the number of characters or bytes\nconsumed from <code>data</code>. Any data not consumed will be included again the\nnext time the handler is called.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>process.stream()</code> handler is set up, then the <code>process.then()</code>\nhandlers will only get any remaining data not consumed by the stream\nhandler.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-spawn-input\">process.input()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.input(data, [stream])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This method writes <code>data</code> to the standard input of the process. If\n<code>data</code> is <code>null</code> or <code>undefined</code> it is not sent. The <code>data</code>\nshould be a string or an array of bytes if the process was opened in\nbinary mode.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>stream</code> is set to <code>true</code> then this function may be called again\nwith further input. Otherwise the standard input of the process is\nclosed.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-spawn-close\">process.close()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the process by closing its standard input and output. If\n<code>problem</code> is specified it should be a standard\n<a href=\"#cockpit-problems\">problem code</a> string. In this case the process\nwill be terminated with a signal.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_js_utilities\">cockpit.js: Utilities</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Various utility functions</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-format\">cockpit.format()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format(template, args)\nstring = cockpit.format(template, [arg, ...])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Format a string interpolating <code>args</code> into <code>template</code> using shell\nlike syntax. The <code>args</code> may be either an array or javascript object.\nThe <code>template</code> can contain fields that look like <code>$name</code> or\n<code>${name}</code> or <code>$0</code>. Numeric fields are used with array <code>args</code> and\nstart at zero.</p>\n</div>\n<div class=\"paragraph\">\n<p>In the second form, multiple <code>arg</code> arguments may be passed directly,\nand interpolated as as numeric fields in the <code>template</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>All falsy arguments except the numbers <code>0</code> and `0.0`are replaced by\nan empty string.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-format-number\">cockpit.format_number()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_number(number, [precision])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Formats <code>number</code> into a displayable <code>string</code>. If the number is not\nan integer, it is rounded to the given number of decimal places,\ndefaulting to 3. If the number is near zero, but not quite zero it is\nrounded to the smallest non-zero value of the given precision; i.e.\n±0.001 for default precision 3.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>number</code> is <code>null</code> or <code>undefined</code> an empty string will be\nreturned.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-format-bytes\">cockpit.format_bytes()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_bytes(number, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Formats <code>number</code> into a displayable <code>string</code> with a suffix, such as\n<em>kB</em> or <em>MB</em>.</p>\n</div>\n<div class=\"paragraph\">\n<p>By default, SI units are used. IEC units (1024-based) can be requested\nby including <code>base2: true</code> in <code>options</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>By default, non-integer numbers will be formatted with 3 digits of\nprecision. This can be changed with <code>options.precision</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>number</code> is <code>null</code> or <code>undefined</code> an empty string will be\nreturned.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-format-bytes-per-sec\">cockpit.format_bytes_per_sec()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_bytes_per_sec(number, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Format <code>number</code> of bytes into a displayable speed <code>string</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is mostly equivalent to <code>cockpit.format_bytes()</code> but the\nreturned value contains a unit like <em>kB/s</em> or <em>MB/s</em>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-format-bits-per-sec\">cockpit.format_bits_per_sec()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_bits_per_sec(number, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Format <code>number</code> of bits into a displayable speed <code>string</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is mostly equivalent to <code>cockpit.format_bytes()</code> but the\nreturned value contains a unit like <em>kbps</em> or <em>Mbps</em>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function does not support IEC units. <code>base2</code> may not be passed as\npart of <code>options</code>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-init\">cockpit.init()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>await cockpit.init();\n\ncockpit.init().then(() =&gt; { ... });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Requests initialization of the Cockpit client library. This will ensure\nthat the transport is connected and we are ready to create channels. It\nalso populates the <code>cockpit.info</code> field.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function returns a promise. Initialization isn&#8217;t complete until the\npromise has resolved. You can either <code>await</code> it or call <code>.then()</code> on\nit.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-info\">cockpit.info</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.info.channels[payload]\n\ncockpit.info.os_release[field]\n\ncockpit.info.user\n\ncockpit.info.ws.version</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This object contains information about Cockpit itself. It is only\navailable after cockpit.init() has been called and awaited.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>channels</code></dt>\n<dd>\n<p>This is a mapping of channel payload types (keys, strings) supported\nby the bridge to capabilities advertised by those channels (values,\nlists of strings). Channels are listed even if they don&#8217;t advertise\nany capabilities, making this useful as a way to determine which\nchannel types are supported by the bridge.</p>\n</dd>\n<dt class=\"hdlist1\"><code>os_release</code></dt>\n<dd>\n<p>This is the data from the <code>/etc/os-release</code> or\n<code>/usr/lib/os-release</code> on the system that the bridge is running on.\nIt is a mapping from the key names to their values. See the\n<a href=\"https://www.freedesktop.org/software/systemd/man/latest/os-release.html\">os-release\nSpecification</a> for information about the available keys.</p>\n</dd>\n<dt class=\"hdlist1\"><code>user</code></dt>\n<dd>\n<p>Contains information about the user we&#8217;re logged in as.</p>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>uid</code></dt>\n<dd>\n<p>This is unix user id as an integer.</p>\n</dd>\n<dt class=\"hdlist1\"><code>gid</code></dt>\n<dd>\n<p>This is unix user group id as an integer.</p>\n</dd>\n<dt class=\"hdlist1\"><code>name</code></dt>\n<dd>\n<p>This is the unix user name like <code>\"root\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>fullname</code></dt>\n<dd>\n<p>This is a readable name for the user, from the GECOS field.</p>\n</dd>\n<dt class=\"hdlist1\"><code>group</code></dt>\n<dd>\n<p>This is the primary group name of the user.</p>\n</dd>\n<dt class=\"hdlist1\"><code>groups</code></dt>\n<dd>\n<p>This is an array of group names to which the user belongs. The first\nitem in this list is the primary group.</p>\n</dd>\n<dt class=\"hdlist1\"><code>home</code></dt>\n<dd>\n<p>This is user&#8217;s home directory.</p>\n</dd>\n<dt class=\"hdlist1\"><code>shell</code></dt>\n<dd>\n<p>This is unix user shell.</p>\n</dd>\n</dl>\n</div>\n</dd>\n<dt class=\"hdlist1\"><code>ws</code></dt>\n<dd>\n<p>Contains information about the webserver Cockpit is being served with.</p>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>version</code></dt>\n<dd>\n<p>The version of the webserver.</p>\n</dd>\n</dl>\n</div>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-event-target\">cockpit.event_target</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.event_target(object, [handlers])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Adds an\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/EventTarget\">EventTarget</a>\nimplementation to the <code>object</code>. Optionally store the handlers in\n<code>handlers</code> if its specified.</p>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/api-cockpit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit.js</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.js</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#api-cockpit-loading\">Loading cockpit.js</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Basic cockpit API to interact with the system</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"api-cockpit-loading\">Loading cockpit.js</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><code>cockpit.js</code> should be loaded via a script tag.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;script src=\"../base1/cockpit.js\"&gt;</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/api-logs-html.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>logs.html</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>logs.html</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#api-logs-html-description\">Description</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>System log component</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"api-logs-html-description\">Description</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;iframe src=\"http://127.0.0.1:9090/cockpit+app/@localhost/system/logs.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a Cockpit component that brings up system log viewer, with\nfiltering capabilities. On systemd based systems this displays the\nentries from journal.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Component URL</dt>\n<dd>\n<p><code>/cockpit+app/@localhost/system/logs.html</code></p>\n</dd>\n<dt class=\"hdlist1\">Filter by priority</dt>\n<dd>\n<p><code>#?prio=notice</code><br>\n<br>\nFilters the log to show entries below the specific priority,\ninclusive. These\n<a href=\"https://en.wikipedia.org/wiki/Syslog#Severity_levels\">priorities are\nsyslog level keywords</a>. Specifying <code>*</code> as a priority will show all\navailable entries. The default priority is <code>err</code>.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by service</dt>\n<dd>\n<p><code>#?service=sshd.service</code><br>\n<br>\nFilters the log to show entries related to the specific service. The\nformat of the service is specific to the logging implementation. For\njournald these are systemd service unit names.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by tag</dt>\n<dd>\n<p><code>#?tag=kernel</code><br>\n<br>\nFilters the log to show entries related to the specific syslog\nidentifier.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by message</dt>\n<dd>\n<p><code>#?grep=</code><br>\n<br>\nFilters the log to show entries where the <code>MESSAGE=</code> field matches\nthe specified regular expression. PERL-compatible regular expressions\nare used. If the pattern is all lowercase, matching is case\ninsensitive. Otherwise, matching is case sensitive.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by any field</dt>\n<dd>\n<p><code>#?FIELD=VALUE</code><br>\n<br>\nA field is referring to the components of a structured journal entry.\nThe match must be exact. Value can be comma separated list in which\ncase they are automatically matched as alternatives.</p>\n</dd>\n<dt class=\"hdlist1\">Start at point</dt>\n<dd>\n<p><code>#?start=boot</code><br>\n<br>\nFilters the log to show entries after the specific point in time.\nValid values are <code>boot</code> (since last boot), <code>last-24h</code> (last 24\nhours), <code>last-week</code> (last seven days) and <code>previous-boot</code>\n(previous boot).</p>\n</dd>\n<dt class=\"hdlist1\">Follow the journal</dt>\n<dd>\n<p><code>#?follow=true</code><br>\n<br>\nKeep listening on new entries. Valid values are <code>true</code> (follow) and\n<code>false</code> (do not follow).</p>\n</dd>\n<dt class=\"hdlist1\">Show log entry</dt>\n<dd>\n<p><code>#/6e272d82993c4e0d...</code><br>\n<br>\nTo show a specific log entry, put the log entry cursor in a path after\nthe hash above. Note that cursors are logging system specific, and\njournal cursors are subject to change.</p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/api-shell-html.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>index.html</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article\">\n<div id=\"header\">\n<h1>index.html</h1>\n</div>\n<div id=\"content\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;iframe src=\"http://127.0.0.1:9090/cockpit+app/@localhost/shell/index.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a Cockpit component that provides an interface to configure a\nsingle machine. It loads other components on demand to make that happen.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Component URL</dt>\n<dd>\n<p><code>/cockpit+app/@localhost/shell/index.html</code></p>\n</dd>\n</dl>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/api-shell.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>API: shell</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>API: shell</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_index_html\">index.html</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>This package contains the shell that loads other components.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_index_html\">index.html</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;iframe src=\"http://127.0.0.1:9090/cockpit+app/@localhost/shell/index.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a Cockpit component that provides an interface to configure a\nsingle machine. It loads other components on demand to make that happen.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Component URL</dt>\n<dd>\n<p><code>/cockpit+app/@localhost/shell/index.html</code></p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/api-system.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>API: system</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>API: system</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_logs_html\">logs.html</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#api-logs-html-description\">Description</a></li>\n</ul>\n</li>\n<li><a href=\"#_terminal_html\">terminal.html</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#api-terminal-html-description\">Description</a></li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>This package contains general components for basic control of a system.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_logs_html\">logs.html</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>System log component</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"api-logs-html-description\">Description</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;iframe src=\"http://127.0.0.1:9090/cockpit+app/@localhost/system/logs.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a Cockpit component that brings up system log viewer, with\nfiltering capabilities. On systemd based systems this displays the\nentries from journal.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Component URL</dt>\n<dd>\n<p><code>/cockpit+app/@localhost/system/logs.html</code></p>\n</dd>\n<dt class=\"hdlist1\">Filter by priority</dt>\n<dd>\n<p><code>#?prio=notice</code><br>\n<br>\nFilters the log to show entries below the specific priority,\ninclusive. These\n<a href=\"https://en.wikipedia.org/wiki/Syslog#Severity_levels\">priorities are\nsyslog level keywords</a>. Specifying <code>*</code> as a priority will show all\navailable entries. The default priority is <code>err</code>.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by service</dt>\n<dd>\n<p><code>#?service=sshd.service</code><br>\n<br>\nFilters the log to show entries related to the specific service. The\nformat of the service is specific to the logging implementation. For\njournald these are systemd service unit names.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by tag</dt>\n<dd>\n<p><code>#?tag=kernel</code><br>\n<br>\nFilters the log to show entries related to the specific syslog\nidentifier.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by message</dt>\n<dd>\n<p><code>#?grep=</code><br>\n<br>\nFilters the log to show entries where the <code>MESSAGE=</code> field matches\nthe specified regular expression. PERL-compatible regular expressions\nare used. If the pattern is all lowercase, matching is case\ninsensitive. Otherwise, matching is case sensitive.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by any field</dt>\n<dd>\n<p><code>#?FIELD=VALUE</code><br>\n<br>\nA field is referring to the components of a structured journal entry.\nThe match must be exact. Value can be comma separated list in which\ncase they are automatically matched as alternatives.</p>\n</dd>\n<dt class=\"hdlist1\">Start at point</dt>\n<dd>\n<p><code>#?start=boot</code><br>\n<br>\nFilters the log to show entries after the specific point in time.\nValid values are <code>boot</code> (since last boot), <code>last-24h</code> (last 24\nhours), <code>last-week</code> (last seven days) and <code>previous-boot</code>\n(previous boot).</p>\n</dd>\n<dt class=\"hdlist1\">Follow the journal</dt>\n<dd>\n<p><code>#?follow=true</code><br>\n<br>\nKeep listening on new entries. Valid values are <code>true</code> (follow) and\n<code>false</code> (do not follow).</p>\n</dd>\n<dt class=\"hdlist1\">Show log entry</dt>\n<dd>\n<p><code>#/6e272d82993c4e0d...</code><br>\n<br>\nTo show a specific log entry, put the log entry cursor in a path after\nthe hash above. Note that cursors are logging system specific, and\njournal cursors are subject to change.</p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_terminal_html\">terminal.html</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Server terminal component</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"api-terminal-html-description\">Description</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;iframe src=\"http://127.0.0.1:9090/cockpit+app/@localhost/system/terminal.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a Cockpit component that brings up a web-based terminal for the\nlogged in user.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Component URL</dt>\n<dd>\n<p><code>/cockpit+app/@localhost/system/terminal.html</code></p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/api-terminal-html.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>terminal.html</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>terminal.html</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#api-terminal-html-description\">Description</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Server terminal component</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"api-terminal-html-description\">Description</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;iframe src=\"http://127.0.0.1:9090/cockpit+app/@localhost/system/terminal.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a Cockpit component that brings up a web-based terminal for the\nlogged in user.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Component URL</dt>\n<dd>\n<p><code>/cockpit+app/@localhost/system/terminal.html</code></p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/authentication.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Cockpit Authentication</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"authentication\" class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>Cockpit Authentication</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#initial-auth\">Directly logging into the primary server</a></li>\n<li><a href=\"#direct-secondary-auth\">Directly logging into a secondary server without a primary session</a></li>\n<li><a href=\"#secondary-auth\">Logging into a secondary server from the primary session</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_password\">Password</a></li>\n<li><a href=\"#_kerberos\">Kerberos</a></li>\n<li><a href=\"#_public_key\">Public key</a></li>\n<li><a href=\"#host-keys\">SSH host keys</a></li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>While cockpit allows you to monitor and administer several servers at\nthe same time, there is always a primary server your browser connects to\nthat runs the Cockpit web service (cockpit-ws) through which connections\nto additional servers are established. See\n<a href=\"https://raw.githubusercontent.com/cockpit-project/cockpit/main/doc/cockpit-transport.png\">this\ndiagram</a> for how it works.</p>\n</div>\n<div class=\"paragraph\">\n<p>Normally, a session is established on the primary server, and you use\nthe Shell UI of that session to connect to secondary servers.</p>\n</div>\n<div class=\"paragraph\">\n<p>However, it is also possible to instruct the <code>cockpit-ws</code> process on\nthe primary server to directly connect to a secondary server, without\nopening a session on the primary server at all. This is done on the main\nlogin page of Cockpit, by filling out the \"Connect to\" field.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"initial-auth\">Directly logging into the primary server</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The most common way to use Cockpit is to just log directly into the\nserver that you want to access. This can be done if you have direct\nnetwork access to port 9090 on that server.</p>\n</div>\n<div class=\"paragraph\">\n<p>By default the cockpit web service is installed on the base system and\n<a href=\"#listen\">socket activated by systemd</a>. In this setup access is\ncontrolled by a cockpit specific pam stack, generally located at\n<code>/etc/pam.d/cockpit</code>. By default this is configured to allow you to\nlogin with the username and password of any local account on the system.\nYou can also setup a <a href=\"#sso\">Kerberos based SSO solution</a> or\n<a href=\"#cert-authentication\">certificate/smart card authentication</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can also\n<a href=\"https://github.com/cockpit-project/cockpit/blob/main/doc/authentication.md#actions\">disable\nauthentication schemes</a> to enforce authentication policies, or to\nsuppress undesired browser GSSAPI authentication dialogs.</p>\n</div>\n<div class=\"paragraph\">\n<p>The web server can also be run from the\n<a href=\"https://quay.io/cockpit/ws\">cockpit/ws</a> container. If you are\nrunning cockpit on a container host operating system like\n<a href=\"https://getfedora.org/coreos/\">Fedora CoreOS</a> this will be the only\nsupported mode. In this setup, cockpit establishes an SSH connection\nfrom the container to the underlying host, meaning that it is up to your\nSSH server to grant access. To login with a local account, <code>sshd</code> will\nneed to be configured to allow password based authentication.\nAlternatively you can setup a <a href=\"#sso\">Kerberos based SSO solution</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>Like <code>sshd</code>, cockpit can be configured to limit the number of\nconcurrent login attempts allowed. This is done by adding a\n<code>MaxStartups</code> option to the <code>WebService</code> section of your\n<code>cockpit.conf</code>. Additional connections will be dropped until\nauthentication succeeds or the connections are closed.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"direct-secondary-auth\">Directly logging into a secondary server without a primary session</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>It is also possible to log into a secondary server without opening a\nsession on the primary server. This is useful if you are not actually\ninterested in the primary server and would only use it because you do\nnot have direct network access to the secondary server.</p>\n</div>\n<div class=\"paragraph\">\n<p>In this case, <code>cockpit-ws</code> still runs on the primary server, but the\ncredentials from the login screen are directly used with SSH to log into\nthe secondary server given in the \"Connect To\" field of the login\nscreen.</p>\n</div>\n<div class=\"paragraph\">\n<p>Thus, the PAM configuration and accounts on the primary server don&#8217;t\nmatter at all. Often, the only purpose of the primary server is to sit\non the boundary of your network and forward connections to internal\nmachines.</p>\n</div>\n<div class=\"paragraph\">\n<p>In this case, the login page will prompt you to verify unknown SSH keys.\nAccepted keys will be remembered in the local storage of your browser.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"secondary-auth\">Logging into a secondary server from the primary session</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Once you have a session on the primary server, it is possible connect to\nadditional servers by using the host switching UI of the Cockpit Shell.\nThis is useful if you have direct network access to the primary server,\nbut not to the secondary server.</p>\n</div>\n<div class=\"paragraph\">\n<p>On the command line, you would log into the primary server and then use\nSSH to log into the secondary one. Cockpit does just the same, and uses\nSSH to log into the secondary server. Instead of running a interactive\nshell there, however, it starts a <code>cockpit-bridge</code> process.</p>\n</div>\n<div class=\"paragraph\">\n<p><em>Warning:</em> Unlike with SSH on the command line though, this will also\nload and use the Cockpit pages (i.e. JavaScript) from the remote\nmachine, which means that the remote machine can execute arbitrary code\non your primary and all other connected secondary machines. Hence, only\nconnect to <em>machines which you trust</em>.</p>\n</div>\n<div class=\"paragraph\">\n<p>Due to this security risk, this host switcher functionality is disabled\nby default, except on long-term stable Linux distributions (Red Hat\nEnterprise Linux 9, Debian 12, and Ubuntu 22.04/24.04 LTS). If you are\ncomfortable with the security implications, you can enable it manually\nwith the <code>AllowMultiHost</code> option in <code>cockpit.conf</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>These servers will need to be running an SSH server and be configured to\nsupport one of the following authentication methods.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_password\">Password</h3>\n<div class=\"paragraph\">\n<p>The target server will need to have password based authentication\nenabled in <code>sshd</code>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_kerberos\">Kerberos</h3>\n<div class=\"paragraph\">\n<p>The target server will need to be a member of the same domain as the\nprimary server and your domain must be whitelisted in your browser. See\nthe <a href=\"#sso\">SSO documentation</a> for how to set this up.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_public_key\">Public key</h3>\n<div class=\"paragraph\">\n<p>When you successfully log into the primary server, a <code>ssh-agent</code> is\nstarted and keys are loaded into it by running <code>ssh-add</code> without any\narguments. Any passphrase prompt is answered with the password used to\nlog into the primary server.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit provides a user interface for loading other keys into the agent\nthat could not be automatically loaded.</p>\n</div>\n<div class=\"paragraph\">\n<p>The target server will need to have public key authentication enabled in\n<code>sshd</code>, and the public key you wish to use must be present in\n<code>~/.ssh/authorized_keys</code>. Cockpit has a user interface for creating\nSSH keys and for authorizing them.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"host-keys\">SSH host keys</h3>\n<div class=\"paragraph\">\n<p>Cockpit will prompt the user to verify unknown SSH host keys, and will\nwrite accepted host keys into <code>~/.ssh/known_hosts</code>.</p>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cert-authentication.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Certificate/smart card authentication</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"cert-authentication\" class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>Certificate/smart card authentication</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#certauth-server-cert-generation\">User certificate generation</a></li>\n<li><a href=\"#certauth-server-ipa\">Certificate mapping with FreeIPA</a></li>\n<li><a href=\"#certauth-server-ms-ad\">Certificate mapping with Microsoft Active Directory</a></li>\n<li><a href=\"#certauth-server-samba-ad\">Certificate mapping with Samba Active Directory</a></li>\n<li><a href=\"#certauth-server-cockpitconf\">Cockpit web server configuration</a></li>\n<li><a href=\"#certauth-server-resourcelimits\">Cockpit web server resource limits</a></li>\n<li><a href=\"#certauth-forwarding\">Authentication to other services like sudo and ssh</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit can use TLS client certificates for authenticating users.\nCommonly these are provided by a smart card, but it&#8217;s equally possible\nto import certificates directly into the web browser.</p>\n</div>\n<div class=\"paragraph\">\n<p>This requires the host to be in an Identity Management domain like\n<a href=\"https://www.freeipa.org\">FreeIPA</a> or\n<a href=\"https://en.wikipedia.org/wiki/Active_Directory\">Active Directory</a>, which\ncan associate certificates to users.</p>\n</div>\n<div class=\"paragraph\">\n<p>To authenticate users from a Identity Management domain, the server that\nCockpit is running on must be joined to that domain. See the\n<a href=\"#sso-server\">SSO server requirements</a> for details.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"certauth-server-cert-generation\">User certificate generation</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Generating the certificates for users is usually done with a certificate\nmanagement system like <a href=\"https://pagure.io/certmonger\">certmonger</a> or\n<a href=\"https://www.freeipa.org/page/PKI\">FreeIPA</a>, which are not documented\nhere. This command generates a simple key and certificate request for\nthe \"alice\" user:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>openssl req -new -newkey rsa:2048 -days 365 \\\n    -keyout alice.key -out alice.csr -subj \"/CN=alice\"</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Now get this certificate request signed by the Certificate Authority of\nyour Identity Management domain, to get a PEM certificate. Browsers and\nsmart cart utilities accept PKCS#12 format for importing/transfer, so\nconvert the certificate/key pair; it will ask for and protect it with a\ntransfer password:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>openssl pkcs12 -export -in alice.pem -inkey alice.key -out alice.p12</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Don&#8217;t forget to clean up the key file when you do not need it any more:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>shred -u alice.key</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>You can now import <code>alice.p12</code> directly into your browser, with giving\nthe transfer password set above. Or\n<a href=\"https://linux.die.net/man/1/pkcs15-init\">put the certificate onto a smart\ncard</a>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>pkcs15-init --store-private-key alice.p12 --format pkcs12 --auth-id 01</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"certauth-server-ipa\">Certificate mapping with FreeIPA</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The recommended method to sign a user certificate request and associate\nit to a user is <code>ipa cert-request</code>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>ipa cert-request alice.csr --principal=alice --certificate-out=alice.pem</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Alternatively, if you are using a different CA, you can use\n<code>ipa user-add-cert</code> to associate the signed certificate to the user.\nThis expects PEM format, but without the <code>-----BEGIN</code>/<code>-----END</code>\nmarkers:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>ipa user-add-cert alice --certificate=\"$(grep -v ^---- alice.pem)\"</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>See the\n<a href=\"https://www.freeipa.org/page/V4/User_Certificates#Feature_Management\">FreeIPA\nUser Certificates documentation</a> for details.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"certauth-server-ms-ad\">Certificate mapping with Microsoft Active Directory</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The domain user certificates get imported into the\n<code>userCertificate;binary</code> LDAP attribute. The following commands\nconvert the PEM certificate into binary DER form, create an\n<a href=\"https://ldap.com/ldif-the-ldap-data-interchange-format/\">LDIF</a> file and\napply it to the LDAP server running on the domain controller\n\"dc.example.com\":</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>openssl x509 -outform der -in alice.pem -out alice.der\n\ncat &lt;&lt;EOF &gt; alice.ldif\nversion: 1\ndn: cn=alice,ou=users,ou=YOUR_NETBIOS_NAME,dc=example,dc=com\nchangetype: modify\nadd: userCertificate;binary\nuserCertificate;binary:&lt; file://$(pwd)/alice.der\nEOF\n\nldapmodify -H ldap://dc.example.com -f alice.ldif</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"certauth-server-samba-ad\">Certificate mapping with Samba Active Directory</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>At least some versions of <a href=\"https://www.samba.org/\">Samba</a> do not support\nthe <code>userCertificate;binary</code> LDAP attribute, so the import has to\nhappen in base64 PEM form into the textual <code>userCertificate</code> attribute\ninstead. Also, Samba uses a slightly different user hierarchy:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cat &lt;&lt;EOF &gt; alice.ldif\nversion: 1\ndn: cn=alice,cn=users,dc=example,dc=com\nchangetype: modify\nadd: userCertificate\nuserCertificate: $(grep -v ^---- alice.pem | tr -d '\\n')\nEOF\n\nldapmodify -H ldap://dc.example.com  -f alice.ldif</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>As <code>userCertificate</code> is a text instead of binary field, you need to\nset up a\n<a href=\"https://www.mankier.com/5/sssd.conf#Certificate_Mapping_Section\">certificate\nmapping rule</a> in <code>sssd.conf(5)</code> in a <code>[certmap/domain/rulename]</code>\nsection, for example:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>[certmap/example.com/adcerts]\n# we match full certificates, so it is not important to check anything here\nmatchrule = &lt;KU&gt;digitalSignature\nmaprule = LDAP:(userCertificate={cert!base64})</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"certauth-server-cockpitconf\">Cockpit web server configuration</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Set the trusted Certificate Authority of your user certificates in\n<code>sssd</code>, either by copying the CA PEM file to\n<code>/etc/sssd/pki/sssd_auth_ca_db.pem</code> or setting the\n<a href=\"https://www.mankier.com/5/sssd.conf#Services_Sections-PAM_configuration_options\"><code>pam_cert_db_path</code></a>\nconfiguration option to the path of the CA. If you use FreeIPA and its\nCA:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cp /etc/ipa/ca.crt /etc/sssd/pki/sssd_auth_ca_db.pem</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Certificate authentication needs to be enabled in\n<a href=\"./cockpit.conf.5.html\">cockpit.conf</a> explicitly:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>[WebService]\nClientCertAuthentication = yes</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>When enabling this mode,\n<a href=\"https://github.com/cockpit-project/cockpit/blob/main/doc/authentication.md\">other\nauthentication types</a> commonly get disabled, so that <em>only</em> client\ncertificate authentication will be accepted. By default, after a failed\ncertificate authentication attempt, Cockpit&#8217;s normal login page will\nappear and permit other login types such as <code>basic</code> (passwords) or\n<code>negotiate</code> (Kerberos). For example, password authentication gets\ndisabled with:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>[basic]\naction = none</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"certauth-server-resourcelimits\">Cockpit web server resource limits</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>When using certificate authentication, all requests with a particular\ncertificate will be handled by a separate and isolated instance of the\n<a href=\"./cockpit-ws.8.html\">cockpit-ws</a> web server. This protects against\npossible vulnerabilities in the web server and prevents an attacker from\nimpersonating another user. However, this introduces a potential Denial\nof Service: Some remote attacker could create a large number of\ncertificates and send a large number of http requests to Cockpit with\nthese.</p>\n</div>\n<div class=\"paragraph\">\n<p>To mitigate that, all <code>cockpit-ws</code> instances run in a\n<code>system-cockpithttps.slice</code>\n<a href=\"https://www.freedesktop.org/software/systemd/man/systemd.slice.html\">systemd\nslice unit</a> which\n<a href=\"https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html\">limits\nthe collective resources</a> of these web server instances: by default,\nthis slice sets a limit of 200 threads (roughly 100 instances of\n<code>cockpit-ws</code>&#8201;&#8212;&#8201;in other words, a maximum of 100 parallel user\nsessions with different certificates) and a 75% (soft)/90% (hard) memory\nlimit.</p>\n</div>\n<div class=\"paragraph\">\n<p>You are welcome to adjust these limits to your need through a\n<a href=\"https://www.freedesktop.org/software/systemd/man/systemd.unit.html\">drop-in</a>.\nFor example:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre># systemctl edit system-cockpithttps.slice\n\n[Slice]\n# change existing value\nTasksMax=100\n# add new restriction\nCPUQuota=30%</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"certauth-forwarding\">Authentication to other services like sudo and ssh</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Once you logged into Cockpit with a certificate, you likely need to\nswitch to administrative mode (root privileges through sudo), or connect\nto remote machines through SSH. If your user account has a password,\nthat can be used for authenticating to sudo or ssh as usual.</p>\n</div>\n<div class=\"paragraph\">\n<p><em>Supported with FreeIPA only:</em> As an alternative to password\nauthentication, you can also declare the initial Cockpit certificate\nauthentication as trusted for authenticating to SSH, sudo, or other\nservices. For that purpose, Cockpit automatically creates an\n<a href=\"https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/bde93b0e-f3c9-4ddf-9f44-e1453be7af5a\">S4U2Proxy\nKerberos ticket</a> in the user session:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ klist\nTicket cache: FILE:/run/user/1894000001/cockpit-session-3692.ccache\nDefault principal: user@EXAMPLE.COM\n\nValid starting     Expires            Service principal\n07/30/21 09:19:06  07/31/21 09:19:06  HTTP/myhost.example.com@EXAMPLE.COM\n07/30/21 09:19:06  07/31/21 09:19:06  krbtgt/EXAMPLE.COM@EXAMPLE.COM\n    for client HTTP/myhost.example.com@EXAMPLE.COM</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>You can set up\n<a href=\"https://www.freeipa.org/page/V4/Service_Constraint_Delegation\">constrained\ndelegation rules</a> to enumerate which hosts (including its own) that\nticket is trusted to access. For example, if the cockpit session runs on\nhost <code>myhost.example.com</code> and should be trusted to access its own host\n(through sudo) and another host <code>remote.example.com</code> (through ssh),\ncreate a delegation like this:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre># a list of target machines which can be accessed by a particular rule\nipa servicedelegationtarget-add cockpit-target\nipa servicedelegationtarget-add-member cockpit-target \\\n  --principals=host/myhost.example.com@EXAMPLE.COM \\\n  --principals=host/remote.example.com@EXAMPLE.COM\n\n# allow cockpit sessions (HTTP/ principal) to access that host list\nipa servicedelegationrule-add cockpit-delegation\nipa servicedelegationrule-add-member cockpit-delegation \\\n  --principals=HTTP/myhost.example.com@EXAMPLE.COM\nipa servicedelegationrule-add-target cockpit-delegation \\\n  --servicedelegationtargets=cockpit-target</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>In addition, you need to enable GSS (Kerberos) authentication in the\ncorresponding services.</p>\n</div>\n<div class=\"ulist\">\n<ul>\n<li>\n<p>For SSH, enable <code>GSSAPIAuthentication yes</code> in\n<a href=\"https://linux.die.net/man/5/sshd_config\">/etc/ssh/sshd_config</a>.</p>\n</li>\n<li>\n<p>For sudo, enable <code>pam_sss_gss</code> as described in the\n<a href=\"https://www.mankier.com/8/pam_sss_gss\">manpage</a>: In\n<code>/etc/sssd/sssd.conf</code>: Add an entry for your domain:</p>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>[domain/example.com]\npam_gssapi_services = sudo, sudo-i</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>In <code>/etc/pam.d/sudo</code>, enable the module in the first line:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>auth sufficient pam_sss_gss.so</pre>\n</div>\n</div>\n</li>\n</ul>\n</div>\n<div class=\"paragraph\">\n<p><em>Caveat:</em> The delegated S4U ticket is not yet forwarded to remote SSH\nhosts when connecting to them from Cockpit, so authenticating to sudo on\nthe remote host with that ticket does not work. This will be provided in\na future version.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-bridge.1.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit-bridge(1)</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit-bridge(1)</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_name\">Name</a></li>\n<li><a href=\"#_synopsis\">Synopsis</a></li>\n<li><a href=\"#_description\">Description</a></li>\n<li><a href=\"#_options\">Options</a></li>\n<li><a href=\"#_bugs\">Bugs</a></li>\n<li><a href=\"#_author\">Author</a></li>\n<li><a href=\"#_see_also\">See also</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"_name\">Name</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>cockpit-bridge - Cockpit Host Bridge</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_synopsis\">Synopsis</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><strong>cockpit-bridge</strong> [<strong>--help</strong>] [<strong>--packages</strong>]</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_description\">Description</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The <strong>cockpit-bridge</strong> program is used by Cockpit to relay messages and\ncommands from the Web front end to the server. Among other things it\nrelays DBus, and spawns processes on behalf of the Web user interface.</p>\n</div>\n<div class=\"paragraph\">\n<p>This program is not routinely run by users or administrators. It is in\nthe <strong>$PATH</strong> so that Cockpit can find it when connecting between hosts.\nHowever there are some diagnostics available when running from the\ncommand line.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_options\">Options</h2>\n<div class=\"sectionbody\">\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>--help</strong></dt>\n<dd>\n<p>Show help options.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--interact</strong>=<em>boundary</em></dt>\n<dd>\n<p>Interact with the raw cockpit1 protocol. Useful for debugging and\ntesting. Specify a <em>boundary</em> which should be on an empty line\nbetween messages.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--packages</strong></dt>\n<dd>\n<p>List all available Cockpit packages and exit. Note this includes\npackages available to the user running this command.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--version</strong></dt>\n<dd>\n<p>Show Cockpit version information.</p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_bugs\">Bugs</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_author\">Author</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_see_also\">See also</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><strong>cockpit-ws(8)</strong></p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-cache.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit.js: Object Caching</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.js: Object Caching</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#cockpit-cache-func\">cockpit.cache()</a></li>\n<li><a href=\"#cockpit-cache-close\">cache.close()</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>If the same information is displayed by multiple components in Cockpit,\n<code>cockpit.cache()</code> provides a way to share data between them. The\nshared data should be simple objects, arrays, and values, and not\ncontain functions or other objects.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-cache-func\">cockpit.cache()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cache = cockpit.cache(key, provider, consumer)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new cache object. The <code>key</code> should be a globally unique\nstring that describes the data being cached. This string must describe\nthe data, across all machines and all versions of cockpit. It is\ncustomary to include a version number in the <code>key</code> string.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>function provider(result, key) {\n    result(\"myvalue\");\n\n    return {\n        close: function() {\n            /* closed */\n        }\n    };\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <code>provider</code> is a function that will be invoked to start retrieving\ndata for the cache. It will be passed a <code>result</code> function as its first\nargument. The <code>result</code> should be invoked whenever new data is\navailable. The <code>key</code> argument matches the key string the cache was\ncreated with.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>provider</code> can return an object with a <code>close</code> method. This\nmethod will be invoked when the cache no longer needs data from the\nprovider.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>function consumer(value, key) {\n    /* ... */\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <code>consumer</code> is a function that will be passed new values when they\nare available, whether they come from the <code>provider</code> or a source in a\ndifferent component/frame.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-cache-close\">cache.close()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cache.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close a cache and stop calling its <code>consumer</code>. If the <code>provider</code> was\ninvoked, then the <code>close()</code> method it returned will be invoked.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-channels.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit.js: Raw Channels</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.js: Raw Channels</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#cockpit-channels-channel\">cockpit.channel()</a></li>\n<li><a href=\"#cockpit-channels-binary\">channel.binary</a></li>\n<li><a href=\"#cockpit-channels-options\">channel.options</a></li>\n<li><a href=\"#cockpit-channels-valid\">channel.valid</a></li>\n<li><a href=\"#cockpit-channels-send\">channel.send()</a></li>\n<li><a href=\"#cockpit-channels-control\">channel.control()</a></li>\n<li><a href=\"#cockpit-channels-wait\">channel.wait()</a></li>\n<li><a href=\"#cockpit-channels-close\">channel.close()</a></li>\n<li><a href=\"#cockpit-channels-message\">channel.onmessage</a></li>\n<li><a href=\"#cockpit-channels-oncontrol\">channel.oncontrol</a></li>\n<li><a href=\"#cockpit-channels-onready\">channel.onready</a></li>\n<li><a href=\"#cockpit-channels-close-ev\">channel.onclose</a></li>\n<li><a href=\"#cockpit-transport-origin\">cockpit.transport.origin</a></li>\n<li><a href=\"#cockpit-transport-host\">cockpit.transport.host</a></li>\n<li><a href=\"#cockpit-transport-csrf-token\">cockpit.transport.csrf_token</a></li>\n<li><a href=\"#cockpit-transport-options\">cockpit.transport.options</a></li>\n<li><a href=\"#cockpit-transport-wait\">cockpit.transport.wait()</a></li>\n<li><a href=\"#cockpit-transport-close\">cockpit.transport.close()</a></li>\n<li><a href=\"#cockpit-transport-filter\">cockpit.transport.filter()</a></li>\n<li><a href=\"#cockpit-transport-inject\">cockpit.transport.inject()</a></li>\n<li><a href=\"#cockpit-base64-encode\">cockpit.base64_encode()</a></li>\n<li><a href=\"#cockpit-base64-decode\">cockpit.base64_decode()</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>At a low level Cockpit communicates with the system via messages passed\nthrough various channels. These are usually exposed via higher level\nAPIs, such as the <code>cockpit.spawn()</code> function. It is rare to use raw\nchannels directly.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-channels-channel\">cockpit.channel()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel = cockpit.channel(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This function creates a new channel for communication with the system.\nIt returns a new channel object. The <code>options</code> argument is a plain\nobject. At least the <code>\"payload\"</code> option is required, and based on the\npayload type, other options may be required.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"binary\"</code></dt>\n<dd>\n<p>Set to <code>true</code> to transfer binary payloads. Both messages sent via\n<a href=\"#cockpit-channels-send\"><code>channel.send()</code></a> and those received via\n<a href=\"#cockpit-channels-message\"><code>channel.onmessage</code></a> should be arrays\nof bytes, either <code>Uint8Array</code> or <code>Array</code> depending on browser\nsupport.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"payload\"</code></dt>\n<dd>\n<p>The payload type for the channel. Only specific payload types are\nsupported.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to open this channel as root. If the currently\nlogged in user is not permitted to become root (eg: via <code>pkexec</code>)\nthen the <code>channel</code> will immediately be\n<a href=\"#cockpit-channels-close-ev\">closed</a> with a <code>\"access-denied\"</code>\nproblem code.\n+\nSet to <code>\"try\"</code> to try to open the channel as root, but if that\nfails, then fall back to an unprivileged channel.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The channel object returned has the following fields and methods and\nevents. You should call the <code>channel.close()</code> method when done with\nthe channel.</p>\n</div>\n<div class=\"paragraph\">\n<p>A valid channel will always be returned and the is ready to\n<code>channel.send()</code>. The channel may\n<a href=\"#cockpit-channels-close-ev\">close shortly afterword</a> due to a\nfailure.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-channels-binary\">channel.binary</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Will be <code>true</code> for an binary channel. Will be set to <code>false</code> if the\nchannel is textual.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-channels-options\">channel.options</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The options used to open this channel. This should not be changed.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-channels-valid\">channel.valid</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Will be <code>true</code> for an open channel. Will be set to <code>false</code> if the\nchannel closes.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-channels-send\">channel.send()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.send(data)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Send a message over the channel. The contents of the message depends on\nthe payload type of the channel. If a binary channel, then <code>data</code> is\nexpected to be an <code>Array</code> of bytes or a <code>Uint8Array</code>. If not binary,\nthen the <code>data</code> will be converted to a string if not already a string.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-channels-control\">channel.control()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.control(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Notify the channel to tune certain parameters on the fly. The\n<code>options</code> is a plain javascript object, and the contents depend on the\n<code>\"payload\"</code> of the channel.</p>\n</div>\n<div class=\"paragraph\">\n<p>One common operation is to set <code>\"command\"</code> to <code>\"done\"</code> in the\noptions field. To indicate that no further messages will be sent through\nthe channel.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-channels-wait\">channel.wait()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = channel.wait([callback])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Returns a <code>promise</code> that is ready when the channel is ready, or fails\nif the client closes. If a <code>callback</code> is specified, it is attached to\nthe promise. The promise will be rejected or resolved with the contents\n<code>options</code> passed to the\n<a href=\"#cockpit-channels-onready\">channel.onready</a> and\n<a href=\"#cockpit-channels-close-ev\">channel.onclose</a> events respectively.</p>\n</div>\n<div class=\"paragraph\">\n<p>In general it&#8217;s not necessary to wait for the channel before starting to\nuse the channel.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-channels-close\">channel.close()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.close([options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the channel.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>options</code> is present it can be a plain javascript object containing\nadditional channel close options to send to the peer. If closing for\nbecause of a problem, set the <code>\"problem\"</code> field to a\n<a href=\"#cockpit-problems\">problem code</a>. If <code>options</code> is not an object it\nwill be treated as a <code>\"problem\"</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-channels-close-ev\">close event</a> will fire. A channel\ncan also be closed by a peer or if the underlying transport closes.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-channels-message\">channel.onmessage</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"message\", function(event, data) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the channel receives a message. The message is\npassed as a string to the handler in the <code>data</code>. In the case of binary\nchannels <code>data</code> is an <code>Uint8Array</code> or an <code>Array</code> of bytes if the\nformer is not supported by the browser. The contents of the message\ndepends on the payload type of the channel.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-channels-oncontrol\">channel.oncontrol</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"control\", function(event, options) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the channel receives an control message in the\nmiddle of the flow. One particular use is when the <code>command</code> is set to\n<code>\"done\"</code> then no further messages will be received in the channel. The\nexact form of these messages depend on the <code>\"payload\"</code> of the channel.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-channels-onready\">channel.onready</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"ready\", function(event, options) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the other end of the channel is ready to start\nprocessing messages. This indicates the channel is completely open. It\nis possible to start sending messages on the channel before this point.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-channels-close-ev\">channel.onclose</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"close\", function(event, options) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the channel closes. This can happen either\nbecause <a href=\"#cockpit-channels-close\">channel.close()</a> function was\ncalled, or if the peer closed the channel, or the underlying transport\ncloses.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> will contain various close information, including a\n<code>\"problem\"</code> field which will be set if the channel was closed because\nof a problem.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-transport-origin\">cockpit.transport.origin</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.origin</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The HTTP origin that is being used by the underlying channel transport.\nThis is read-only, you should not assign a value. If the browser\nsupports <code>window.location.origin</code> then this will be identical to that\nvalue.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-transport-host\">cockpit.transport.host</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.host</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The host that this transport is going to talk to by default. This is\nread-only, you should not assign a value. If the value is null that\nmeans that the transport has not been setup yet.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-transport-csrf-token\">cockpit.transport.csrf_token</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.csrf_token</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>A cross site request forgery token for use with external channels. This\nbecomes valid once the connection is properly established.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-transport-options\">cockpit.transport.options</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.options</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Initialization options received over the underlying channel transport.\nThese will be empty until connection is properly established.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-transport-wait\">cockpit.transport.wait()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.wait(callback)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Call the <code>callback</code> function once the underlying channel transport is\ninitialized. This will start the initialization if not already in\nprogress or completed. If the channel transport is already initialized,\nthen <code>callback</code> will be called immediately.</p>\n</div>\n<div class=\"paragraph\">\n<p>In general it&#8217;s not necessary to wait for the transport before starting\nto open channels.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-transport-close\">cockpit.transport.close()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the underlying channel transport. All channels open channels will\nclose. The <code>problem</code> argument should be a problem code string. If not\nspecified it will default to <code>\"disconnected\"</code>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-transport-filter\">cockpit.transport.filter()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.filter((message, channelid, control) =&gt;  { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Add a filter to the underlying channel transport. All incoming messages\nwill be passed to each of the filter callbacks that are registered.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is rarely used.</p>\n</div>\n<div class=\"paragraph\">\n<p>Filter callbacks are called in the order they are registered. If a\nfilter callback returns <code>false</code> then the message will not be\ndispatched further, whether to other filters, or to channels, etc.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>message</code> is the string or array with the raw message including,\nthe framing. The <code>channelid</code> is the channel identifier or an empty\nstring for control messages. If <code>control</code> is set then this is a\ncontrol message,d and the <code>control</code> argument contains the parsed JSON\nobject of the control message.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-transport-inject\">cockpit.transport.inject()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.inject(message, [out])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Inject a message into the underlying channel transport. The <code>message</code>\nshould be a <code>string</code> or an array of bytes, and should be valid\naccording to the Cockpit message protocol. If the <code>out</code> argument is\nequal to <code>false</code> then the message will be injected as an incoming\nmessage as if it was received on the underlying channel transport.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is rarely used. In general you should only <code>inject()</code>\nmessages you got from a <code>filter()</code>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-base64-encode\">cockpit.base64_encode()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.base64_encode(data)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Encode binary data into a string using the Base64 encoding. The <code>data</code>\nargument can either be a <code>string</code>, an <code>Array</code>, an <code>ArrayBuffer</code> or\na <code>Uint8Array</code>. The return value is a string.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-base64-decode\">cockpit.base64_decode()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>data = cockpit.base64_decode(string, [constructor])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Decode binary data from a Base64 encoded string. The <code>string</code> argument\nshould be a javascript string. The returned <code>data</code>&gt; will be an array\nof bytes.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can pass <code>Uint8Array</code>, <code>Array</code> or <code>String</code> as an alternate\n<code>constructor</code> if you want the decoded data in an alternate form. The\ndefault is to return an <code>Array</code>. Note that if you use a <code>String</code> for\nthe decoded data, then you must guarantee that the data does not contain\nbytes that would be invalid for a string.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-dbus.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit.js: DBus Client</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.js: DBus Client</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#cockpit-dbus-types\">DBus Types</a></li>\n<li><a href=\"#cockpit-dbus-dbus\">cockpit.dbus()</a></li>\n<li><a href=\"#cockpit-dbus-wait\">client.wait()</a></li>\n<li><a href=\"#cockpit-dbus-close\">client.close()</a></li>\n<li><a href=\"#cockpit-dbus-onclose\">client.onclose</a></li>\n<li><a href=\"#cockpit-dbus-onowned\">client.onowner</a></li>\n<li><a href=\"#cockpit-dbus-options\">client.options</a></li>\n<li><a href=\"#cockpit-dbus-unique-name\">client.unique_name</a></li>\n<li><a href=\"#cockpit-dbus-proxy\">client.proxy()</a></li>\n<li><a href=\"#cockpit-dbus-proxy-client\">proxy.client</a></li>\n<li><a href=\"#cockpit-dbus-proxy-path\">proxy.path</a></li>\n<li><a href=\"#cockpit-dbus-proxy-iface\">proxy.iface</a></li>\n<li><a href=\"#cockpit-dbus-proxy-valid\">proxy.valid</a></li>\n<li><a href=\"#cockpit-dbus-proxy-data\">proxy.data</a></li>\n<li><a href=\"#cockpit-dbus-proxy-call\">proxy.call()</a></li>\n<li><a href=\"#cockpit-dbus-proxy-wait\">proxy.wait()</a></li>\n<li><a href=\"#cockpit-dbus-proxy-onchanged\">proxy.onchanged</a></li>\n<li><a href=\"#cockpit-dbus-proxy-signal\">proxy.onsignal</a></li>\n<li><a href=\"#cockpit-dbus-proxies\">client.proxies()</a></li>\n<li><a href=\"#cockpit-dbus-proxies-wait\">proxies.wait()</a></li>\n<li><a href=\"#cockpit-dbus-proxies-client\">proxies.client</a></li>\n<li><a href=\"#cockpit-dbus-proxies-iface\">proxies.iface</a></li>\n<li><a href=\"#cockpit-dbus-proxies-path_namespace\">proxies.path_namespace</a></li>\n<li><a href=\"#cockpit-dbus-proxies-onadded\">proxies.onadded</a></li>\n<li><a href=\"#cockpit-dbus-proxies-onchanged\">proxies.onchanged</a></li>\n<li><a href=\"#cockpit-dbus-proxies-onremoved\">proxies.onremoved</a></li>\n<li><a href=\"#cockpit-dbus-call\">client.call()</a></li>\n<li><a href=\"#cockpit-dbus-then\">invocation.then()</a></li>\n<li><a href=\"#cockpit-dbus-catch\">invocation.catch()</a></li>\n<li><a href=\"#cockpit-dbus-subscribe\">client.subscribe()</a></li>\n<li><a href=\"#cockpit-dbus-remove\">subscription.remove()</a></li>\n<li><a href=\"#cockpit-dbus-watch\">client.watch()</a></li>\n<li><a href=\"#cockpit-dbus-watch-then\">watch.then()</a></li>\n<li><a href=\"#cockpit-dbus-watch-catch\">watch.catch()</a></li>\n<li><a href=\"#cockpit-dbus-watch-remove\">watch.remove()</a></li>\n<li><a href=\"#cockpit-dbus-onnotify\">client.onnotify</a></li>\n<li><a href=\"#cockpit-dbus-notify\">client.notify()</a></li>\n<li><a href=\"#cockpit-dbus-onmeta\">client.onmeta</a></li>\n<li><a href=\"#cockpit-dbus-variant\">cockpit.variant()</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit allows access to DBus services via this API.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-types\">DBus Types</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>DBus values are represented as javascript values and objects as follows:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>BYTE 'y'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>BOOLEAN 'b'</code></dt>\n<dd>\n<p>Javascript boolean.</p>\n</dd>\n<dt class=\"hdlist1\"><code>INT16 'n'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>UINT16 'q'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>INT32 'i'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>UINT32 'u'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>INT64 'x'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>UINT64 't'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>DOUBLE 'd'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>STRING 's'</code></dt>\n<dd>\n<p>Javascript string.</p>\n</dd>\n<dt class=\"hdlist1\"><code>OBJECT_PATH 'o'</code></dt>\n<dd>\n<p>Javascript string.</p>\n</dd>\n<dt class=\"hdlist1\"><code>SIGNATURE 'g'</code></dt>\n<dd>\n<p>Javascript string.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of BYTE 'ay'</code></dt>\n<dd>\n<p>A string containing base64 encoded data.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of DICT_ENTRY with STRING keys 'a{s?}'</code></dt>\n<dd>\n<p>A javascript plain object with the keys as property names.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of DICT_ENTRY with other keys 'a{??}'</code></dt>\n<dd>\n<p>A javascript plain object each key JSON encoded into a string property\nname.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of other</code></dt>\n<dd>\n<p>A javascript array.</p>\n</dd>\n<dt class=\"hdlist1\"><code>VARIANT</code></dt>\n<dd>\n<p>A javascript plain object with the <code>\"t\"</code> property set to a DBus type\nstring, and the <code>\"v\"</code> property set to a value.</p>\n</dd>\n<dt class=\"hdlist1\"><code>HANDLE 'h'</code></dt>\n<dd>\n<p>A javascript object that describes a cockpit channel which represents\nthe passed file descriptor. The <code>payload</code> is always set to\n<code>stream</code>. Pass it to\n<a href=\"#cockpit-channels-channel\">cockpit.channel()</a> to create the\nchannel and start reading or writing on it. Handles can only be\nreceived, not sent from within cockpit.</p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-dbus\">cockpit.dbus()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client = cockpit.dbus(name, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a DBus client for the given bus <code>name</code> (eg: service name). Use\nthe following functions to make DBus method calls, watch for events,\netc. The optional <code>options</code> argument is a javascript plain object, and\nmay include:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"bus\"</code></dt>\n<dd>\n<p>The DBus bus to connect to. Specifying <code>\"session\"</code> will connect to\nthe DBus user session bus, <code>\"user\"</code> will connect to the user bus (on\nsome systems this is identical to the session bus), <code>\"system\"</code> will\nconnect to the DBus system bus, and <code>\"none\"</code> to the non-standard bus\nspecified with the <code>address</code> option. This defaults to \"system\" if\nnot present.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"address\"</code></dt>\n<dd>\n<p>The bus address to connect to in case <code>bus</code> is <code>\"none\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to talk to this service as root. The DBus service\nwill see the DBus method calls and accesses as coming from root,\nrather than the logged in user. This is useful for talking to services\nthat do not correctly use\n<a href=\"https://www.freedesktop.org/software/polkit\">polkit</a> to authorize\nadministrative users. If the currently logged in user is not permitted\nto become root (eg: via <code>pkexec</code>) then the <code>client</code> will\nimmediately be <a href=\"#cockpit-dbus-onclose\">closed</a> with a\n<code>\"access-denied\"</code> problem code.\n+\nSet to <code>\"try\"</code> to try to talk as root, but if that fails, fall back\nto unprivileged.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"track\"</code></dt>\n<dd>\n<p>It is valid for a DBus service to exit, and be restarted in such a way\nthat clients continue to talk to it across the restart. Some services\nare not written with this in mind. If the <code>\"track\"</code> option is set to\n<code>true</code> then the channel will close when the service exits and/or\ndisconnects from the DBus bus.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>If the <code>name</code> argument is null, and no options other than <code>\"bus\"</code>\nare specified, then a shared DBus <code>client</code> is created. When using such\na client with a DBus bus, a <code>\"name\"</code> option must be specified on\nvarious other methods in order to specify which client to talk to.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-wait\">client.wait()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = client.wait([callback])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Returns a <code>promise</code> that is ready when the client is ready, or fails\nif the client closes. If a <code>callback</code> is specified, it is attached to\nthe promise.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-close\">client.close()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the DBus client. If <code>problem</code> is specified it should be a\n<a href=\"#cockpit-problems\">problem code</a> string.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-onclose\">client.onclose</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.addEventListener(\"close\", options =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the DBus client closes. This can happen either\nbecause <a href=\"#cockpit-dbus-close\">client.close()</a> function was called, or\nthe DBus service went away, or some other problem or disconnection.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> will contain various close information, including a\n<code>\"problem\"</code> field which will be set if the channel was closed because\nof a problem.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-onowned\">client.onowner</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.addEventListener(\"owner\", (event, owner) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the owner of the DBus name changes. The owner\nvalue will be the id of the name owner on the bus or null if the name is\nunowned. The absence of an owner should not be treated as a\ndisconnection. However this makes it possible to take some action based\non the actual status of the service, for example disconnecting a pending\nsignal handler.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-options\">client.options</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Set to the options used when creating the client. Will not change for\nthe life of the client.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-unique-name\">client.unique_name</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The unique DBus name of the client. Initially null, and becomes valid\nonce the the client is ready.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxy\">client.proxy()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy = client.proxy([interface, path], [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create proxy javascript object for a DBus <code>interface</code>. At the\nspecified DBus object <code>path</code>. The proxy will have properties, methods\nand signals from to the DBus interface, and allows for natural\ninteraction. If no <code>interface</code> is specified then the DBus bus name of\nthe client is used. If no <code>path</code> is specified, then the DBus name of\nthe client is converted to a path.</p>\n</div>\n<div class=\"paragraph\">\n<p>If creating lots of proxies for a given <code>interface</code> it is more\nefficient to use the <a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a>\nfunction.</p>\n</div>\n<div class=\"paragraph\">\n<p>The proxy is loaded when the\n<a href=\"#cockpit-dbus-proxy-valid\"><code>proxy.valid</code></a> field is <code>true</code>, and\nit is set to <code>false</code> if the underlying <code>interface</code> and/or <code>path</code>\ndon&#8217;t or no longer exist, or the <code>client</code> has closed. You can wait for\nproxy to become valid by passing a callback to its\n<a href=\"#cockpit-dbus-proxy-wait\"><code>proxy.wait()</code></a> function. The\n<a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a> event will also\nfire when the proxy becomes valid or invalid. DBus properties and\nmethods on the proxy are not defined until the proxy becomes valid.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>value = proxy.Prop1\nproxy.WritableProp = value</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>All DBus properties on the <code>interface</code> that start with an upper case\nletter (as is convention) will be automatically defined on this proxy,\nand will update their values as the DBus property values change. In\naddition the <a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a>\nevent will fire every time the properties change.</p>\n</div>\n<div class=\"paragraph\">\n<p>If you assign a value to a writable property on the proxy, the proxy\nwill try to set that property on the DBus <code>interface</code> at <code>path</code>. The\nactual proxy property value will not update until the DBus service has\nnotified the proxy of the change. If setting a property fails a warning\nwill be logged. In order to have more reliable setting of properties, or\ntrack when they have been set, or if setting fails, use the\n<a href=\"#cockpit-dbus-call\"><code>client.call()</code></a> directly. It should be noted\nthat DBus service implementations may also be inconsistent in their\nbehavior when setting a property fails.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can access the raw property data using the\n<a href=\"#cockpit-dbus-proxy-data\"><code>proxy.data</code></a> field, including data for\nproperties that do not start with an upper case letter.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.Method(arg1, arg2)\n    .then((retval1, retval2) =&gt; {\n        ...\n    })\n    .catch(ex =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>All DBus methods on the <code>interface</code> that start with an upper case\nletter (as is convention) will be automatically defined on this proxy.\nThese methods are called with arguments as normal javascript arguments.\nA\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the method returns, or fail if an\nerror occurs. The return values from the DBus method will be passed to\nthe <code>then</code> handler function directly.</p>\n</div>\n<div class=\"paragraph\">\n<p>Methods that do not start with an upper case letter can be invoked by\nusing the usual <a href=\"#cockpit-dbus-proxy-call\"><code>proxy.call()</code></a>\ndirectly.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.addEventListener(\"signal\", (event, arg1, arg2) =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>All DBus signals on the <code>interface</code> that start with an upper case\nletter (as is convention) will be automatically emit events on this\nproxy. These events will contain the signal arguments after the standard\n<code>event</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>Signals that do not start with an upper case letter can be subscribed to\nby using <a href=\"#cockpit-dbus-proxy-signal\"><code>proxy.onsignal</code></a> directly.</p>\n</div>\n<div class=\"paragraph\">\n<p>Usually a proxy asks the <code>client</code> to watch and notify it of changes to\nthe relevant object or path. You can pass an <code>options</code> argument with\nthe <code>watch</code> field set to <code>false</code> to prevent this.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxy-client\">proxy.client</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Set to the DBus client of the proxy. Will not change for the life of the\nproxy.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxy-path\">proxy.path</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Set to the DBus object path of the proxy. Will not change for the life\nof the proxy.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxy-iface\">proxy.iface</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Set to the DBus interface name of the proxy. Will not change for the\nlife of the proxy.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxy-valid\">proxy.valid</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Set to <code>true</code> when the proxy&#8217;s DBus interface is present at its DBus\npath, and all information for the proxy has loaded. Is set to <code>false</code>\nwhile loading, and after the proxy no longer refers a DBus interface and\npath. Also set to <code>false</code> if the <code>client</code> closes.</p>\n</div>\n<div class=\"paragraph\">\n<p>Use the by <a href=\"#cockpit-dbus-proxy-wait\"><code>proxy.wait()</code></a> function to\nwait for a proxy to load. The\n<a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a> event will also\nbe emitted when the proxy becomes valid or invalid. DBus properties and\nmethods on the proxy are not defined until the proxy becomes valid.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxy-data\">proxy.data</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>A plain javascript object containing all the raw property data that this\nproxy has loaded. This will be updated automatically as the proxy is\nnotified of property changes from the DBus service. The\n<a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a> event will be\nemitted when it changes.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxy-call\">proxy.call()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation = proxy.call(method, args, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Make a DBus method call on this proxy.</p>\n</div>\n<div class=\"paragraph\">\n<p>For DBus methods that start with an upper case letter, is usually more\nconvenient <a href=\"#cockpit-dbus-proxy\">to call the method directly on the\nproxy</a>. However if methods that do not follow the usual DBus convention,\nor specify additional options, or the caller cannot be sure that the\nmethod actually exists, you can use this method.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function also works on proxies that have are still loading and have\nnot become valid yet.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>method</code> should be a DBus method name, and the <code>args</code> should be\nan array of arguments to pass to the method. The <code>options</code> are\n<a href=\"#cockpit-dbus-call\">described elsewhere</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The returned value is identical to the one returned from\n<a href=\"#cockpit-dbus-call\">client.call()</a>. It is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the method returns, or fail if an\nerror occurs.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxy-wait\">proxy.wait()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = proxy.wait()\nproxy.wait(() =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Wait for a proxy to finish loading. This function returns a promise. If\na callback function is passed as an argument then that function will be\ninvoked when the proxy is ready. If this method is called after a proxy\nhas already loaded, then the promise will be resolved immediately, and\nany callback will be invoked immediately. Use the promise or\n<code>proxy.valid</code> to determine whether the proxy is valid.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxy-onchanged\">proxy.onchanged</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.addEventListener(\"changed\", (event, data) =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when the proxy&#8217;s properties change.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> has the following form, and will only include properties\nthat have changed:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n    \"Prop1\": \"value\",\n    \"Prop2\": 5\n}</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxy-signal\">proxy.onsignal</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.addEventListener(\"signal\", (event, name, args) =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when the proxy&#8217;s emits an event.</p>\n</div>\n<div class=\"paragraph\">\n<p>For most events, that have names which start with an upper case letter,\nyou can just <a href=\"#cockpit-dbus-proxy\">connect to that event as a signal\ndirectly</a>. However if you wish to be notified when any signal is\nemitted, or for signals that do not follow the usual DBus convention,\nyou can connect to this event.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>name</code> is the DBus signal name, and the <code>args</code> is an array of\narguments that were emitted with the signal.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxies\">client.proxies()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies = client.proxies([interface], [path_namespace], [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create <a href=\"#cockpit-dbus-proxy\">proxy javascript objects</a> for a DBus\ninterfaces. The proxies will have properties, methods and signals from\nthe DBus <code>interface</code>, and allow for natural interaction. If no\n<code>interface</code> is specified then the DBus bus name of the client is used.\nIf no <code>path_namespace</code> is provided then <code>\"/\"</code> will be used.</p>\n</div>\n<div class=\"paragraph\">\n<p>Proxies will be automatically created for instances of the <code>interface</code>\navailable at the DBus service. The optional <code>path_namespace</code> argument\ncan be used to restrict the proxies for instances that have DBus paths\nwhich have the namespace path prefix.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy1 = proxies[\"/dbus/path1\"];\nproxy2 = proxies[\"/dbus/path2\"];\nfor (proxy in proxies) {\n    ...\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The returned <code>proxies</code> object will is used as a dictionary, and will\nhave values containing proxies for DBus interface instances, with the\nkeys being the DBus paths of those instances. It is possible to\nenumerate over the returned <code>proxies</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>Proxies will be automatically added and removed from the <code>proxies</code>\nobject as they appear and disappear in the service. The\n<a href=\"#cockpit-dbus-proxies-onadded\"><code>proxies.onadded</code></a> and\n<a href=\"#cockpit-dbus-proxies-onremoved\"><code>proxies.onremoved</code></a> events will\nbe emitted. DBus services may not support notifications of paths\ndisappearing.</p>\n</div>\n<div class=\"paragraph\">\n<p>Use the <code>proxies.wait()</code> function to be notified when the initial set\nof proxies has been populated.</p>\n</div>\n<div class=\"paragraph\">\n<p>Usually a proxies ask the <code>client</code> to watch and be notified of changes\nto the relevant object or path. You can pass an <code>options</code> argument\nwith the <code>watch</code> field set to <code>false</code> to prevent this.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxies-wait\">proxies.wait()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = proxies.wait()\nproxies.wait(() =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Wait for a <code>proxies</code> object to populate its initial set of proxies.\nThis function returns a promise. If a callback function is passed as an\nargument then that function will be invoked when the proxies are ready.\nIf this method is called after the proxies have populated, then the\npromise will be resolved immediately, and any callback will be invoked\nimmediately.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxies-client\">proxies.client</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Set to the DBus client of the proxies. Will not change.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxies-iface\">proxies.iface</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Set to the DBus interface name of the proxies. Will not change.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxies-path_namespace\">proxies.path_namespace</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Set to the DBus path namespace used which the proxies must have as a\nDBus path prefix. Will not change.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxies-onadded\">proxies.onadded</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies.addEventListener(\"added\", (event, proxy) =&gt; {\n    ...\n})</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when a proxy is added to the <code>proxies</code> object.\nThe proxy will already have loaded.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxies-onchanged\">proxies.onchanged</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies.addEventListener(\"changed\", (event, proxy) =&gt; {\n    ...\n})</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when one of the proxy in the <code>proxies</code> object\nchanges its properties.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-proxies-onremoved\">proxies.onremoved</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies.addEventListener(\"removed\", (event, proxy) =&gt; {\n    ...\n})</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when a proxy is removed to the <code>proxies</code> object.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-call\">client.call()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation = client.call(path, interface, method, args, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Make a DBus method call.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>path</code> is the DBus object path to make the call on, <code>interface</code>\nis the DBus interface for the method and <code>method</code> is the name of the\nmethod to call. The <code>args</code> is an array of arguments to pass to the\nmethod, each of which must be appropriate for the expected\n<a href=\"#cockpit-dbus\">DBus type</a> of that argument. The <code>args</code> may be\n<code>null</code> if no arguments are to be sent.</p>\n</div>\n<div class=\"paragraph\">\n<p>The returned value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the method returns, or fail if an\nerror occurs.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>options</code> is specified it should be a plain javascript object,\nwhich may contain the following properties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>flags</code></dt>\n<dd>\n<p>A string containing DBus message flags. The character <code>\"i\"</code>\nindicates to the dbus service that interactive authentication is\nallowed. If the entire <code>flags</code> field is missing, then <code>\"i\"</code> is set\nby default.</p>\n</dd>\n<dt class=\"hdlist1\"><code>type</code></dt>\n<dd>\n<p>A valid DBus type signature to use when calling the method. In the\nabsence of this, the DBus service will be introspected (and the result\ncached) to ask what the method type signature is.</p>\n</dd>\n<dt class=\"hdlist1\"><code>timeout</code></dt>\n<dd>\n<p>The timeout of the call in milliseconds. The call will fail with the\n<code>\"timeout\"</code> problem code. If \"timeout\" is not given, the call will\nnever time out.</p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-then\">invocation.then()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation.then((args, options) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the DBus method call\nfinishes successfully.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>args</code> argument is an array of return values from the DBus method.\nEach of them will be converted to an appropriate\n<a href=\"#cockpit-dbus\">javascript type</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> argument may contain additional information about the\nreply. If the <code>type</code> option was specified when performing the method\ncall, then the <code>options</code> in the reply here will also contain a\n<code>type</code> field containing the DBus type signature of the output. If the\n<code>flags</code> option was specified when performing the call then the\n<code>options</code> in the reply here will contain message flags. Possible out\nmessage flags are:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>&gt;</code></dt>\n<dd>\n<p>A big endian message.</p>\n</dd>\n<dt class=\"hdlist1\"><code>&lt;</code></dt>\n<dd>\n<p>A little endian message.</p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-catch\">invocation.catch()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation.catch(exception =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the DBus method call\nfails.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>exception</code> object passed to the handler can have the following\nproperties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>problem</code></dt>\n<dd>\n<p>A <a href=\"#cockpit-problems\">problem code</a> string when a problem occurred\nstarting or communicating with the DBus service. This is <code>null</code> in\nthe cases where an actual DBus error was occurred.</p>\n</dd>\n<dt class=\"hdlist1\"><code>name</code></dt>\n<dd>\n<p>The DBus error name. This will be <code>null</code> in cases where the failure\nwas not due to a DBus error.</p>\n</dd>\n<dt class=\"hdlist1\"><code>message</code></dt>\n<dd>\n<p>A DBus error message. This will be <code>null</code> in cases where the failure\nwas not due to a DBus error.</p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-subscribe\">client.subscribe()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>subscription = client.subscribe(match, (path, interface, signal, args) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Subscribe to signals. The <code>match</code> argument is a javascript plain\nobject which defines what signals to subscribe to. Each property in the\n<code>match</code> argument restricts signals subscribed to. If a property is not\npresent then it is treated as a wildcard, matching anything. If an empty\nobject is specified as <code>match</code> then all signals will be subscribed to.\nThe <code>match</code> argument may contain the following properties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>interface</code></dt>\n<dd>\n<p>A DBus interface to match.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path</code></dt>\n<dd>\n<p>A DBus object path to match. May not be used together with the\n<code>path_namespace</code> property. It should be a valid DBus object path,\nthat is, it should have no trailing slash.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path_namespace</code></dt>\n<dd>\n<p>A DBus object path prefix to match. Any paths in the hierarchy below\nthis top path will match. May not be used together with the <code>path</code>\nproperty.</p>\n</dd>\n<dt class=\"hdlist1\"><code>member</code></dt>\n<dd>\n<p>The DBus signal name to match.</p>\n</dd>\n<dt class=\"hdlist1\"><code>arg0</code></dt>\n<dd>\n<p>Matches the first argument of a DBus message, which must be a string.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The handler passed as the second argument will be invoked when the\nsignal is received. A <code>subscription</code> is returned which can be used to\nremove the subscription by calling its <code>subscription.remove()</code> method.</p>\n</div>\n<div class=\"paragraph\">\n<p>It is not a problem to subscribe to the same signals more than once,\nwith identical or slightly different <code>match</code> arguments.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-remove\">subscription.remove()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>subscription.remove()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Unsubscribe from the DBus signal subscription.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-watch\">client.watch()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch = client.watch(path)\nwatch = client.watch({ \"path_namespace\": path_namespace, \"interface\": interface })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Watch for property and interface changes on the given DBus object\n<code>path</code> DBus <code>path_namespace</code>. If <code>interface</code> is specified only\nproperties on that DBus interface will be watched.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-dbus-proxy\"><code>client.proxy()</code></a> and\n<a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a> functions and the\nobjects they return are high level wrappers around <code>client.watch()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The property and interface changes will be available in raw form on the\n<a href=\"#cockpit-dbus-onnotify\"><code>client.onnotify</code></a> event.</p>\n</div>\n<div class=\"paragraph\">\n<p>Property and interface changes that are caused by a method call or\nsignal will show up before that method call reply is received, or signal\nevent is triggered. It should be possible to rely on this guarantee,\nunless the DBus service in question behaves incorrectly. Internally\nthese watches work well with code that implements the\n<a href=\"https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager\">ObjectManager</a>\nportion of the DBus specification. If no ObjectManager implementation is\navailable, the watch falls back to using DBus\n<a href=\"https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-introspectable\">Introspection</a>\nalong with the usual\n<a href=\"https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties\">PropertiesChanged</a>\nsignal. If the DBus service implements none of these, or implements them\nin an inconsistent manner, then this function will provide inconsistent\nor unexpected results.</p>\n</div>\n<div class=\"paragraph\">\n<p>The parameter is either a DBus <code>path</code> or a plain javascript object\nwith zero or more of the following fields. If an empty javascript object\nis used as an argument, then all paths, interfaces and properties will\nbe watched.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>interface</code></dt>\n<dd>\n<p>Watch properties on this DBus interface.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path</code></dt>\n<dd>\n<p>Watch interfaces and properties at this DBus path. May not be used\ntogether with the <code>path_namespace</code> property.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path_namespace</code></dt>\n<dd>\n<p>Watch interfaces and properties under this DBus path. It should be a\nvalid DBus object path, that is, it should have no trailing slash. If\nan ObjectManager implementation is available at this interface, then\nit is used. May not be used together with the <code>path</code> property.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The returned value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the watch has populated its initial\nset of properties and interfaces, and these have been notified via\n<a href=\"#cockpit-dbus-onnotify\"><code>client.onnotify</code></a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>A watch can be removed by calling the\n<a href=\"#cockpit-dbus-watch-remove\"><code>watch.remove()</code></a> method on the\nreturned value. If identical watches are added more than once, then they\nmust also be removed the same number of times before the removal takes\neffect.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-watch-then\">watch.then()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch.then(() =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the watch has populated\nits initial properties and interfaces.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-watch-catch\">watch.catch()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch.catch(ex =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called if the watch fails to populate\nits initial properties and interfaces. Note that a watch will only fail\nif the DBus client closes or is somehow disconnected. It does not fail\nin the case of missing interfaces or properties.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-watch-remove\">watch.remove()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch.remove()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Remove the watch. This may not have any immediate effect if other\nwatches are in place. In particular, if identical watches are added more\nthan once, then they must also be removed the same number of times\nbefore the removal takes effect.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-onnotify\">client.onnotify</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.addEventListener(\"notify\", data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when <a href=\"#cockpit-dbus-watch\">watched</a> properties or\ninterfaces change.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-dbus-proxy\"><code>client.proxy()</code></a> and\n<a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a> functions and the\nobjects they return are high level wrappers around the <code>data</code> provided\nby this event.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> has the following form:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n    \"/path1\": {\n        \"org.Interface1\": {\n            \"Prop1\": \"value\",\n            \"Prop2\": 5\n        },\n        \"org.Interface2\": null\n    }\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Multiple paths may be present, each of which may have multiple\ninterfaces, each of which may have multiple properties. The first time a\ngiven path and interface is emitted from this signal, it will have all\nits properties and interfaces. Thereafter only changes are noted. If an\ninterface is set to <code>null</code>, then that interface has disappeared.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-notify\">client.notify()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.notify(data)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Emits a synthetic <a href=\"#cockpit-dbus-onnotify\"><code>notify</code></a> event. The\n<code>data</code> argument should follow the same layout as described for the\n<code>notify</code> event.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-onmeta\">client.onmeta</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.onmeta = (ev, data) =&gt; { ... }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the meta data about\n<a href=\"#cockpit-dbus-watch\">watched</a> interfaces is loaded.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-dbus-proxy\"><code>client.proxy()</code></a> and\n<a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a> functions and the\nobjects they return are high level wrappers around the <code>data</code> provided\nby this event.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> has the following form:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>  {\n      \"org.Interface\": {\n          \"methods\": {\n              \"Method1\": {\n                  \"in\": [ \"s\", \"v\" ],\n                  \"out\": [ \"i\" ]\n              },\n              \"Method2\": { }\n          },\n          \"signals\": {\n              \"Signal\": {\n                  \"in\": [ \"b\", \"s\" ]\n              }\n          },\n          \"properties\": {\n              \"Prop1\": {\n                  \"flags\": \"rw\",\n                  \"type\": \"s\"\n              },\n              \"Prop2\": {\n                  \"flags\": \"r\",\n                  \"type\": \"b\"\n              }\n          }\n      }\n  }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Multiple interfaces may be present, each of which may have methods and\nproperties. This is emitted before the first\n<a href=\"#cockpit-dbus-proxy\"><code>client.onnotify</code></a> event for the relevant\ninterface.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-dbus-variant\">cockpit.variant()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>variant = cockpit.variant(type, value)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>A DBus variant is represented as a plain javascript object with a\n<code>\"t\"</code> property represesting the full DBus type of the variant, and a\n<code>\"v\"</code> property containing the variant value.</p>\n</div>\n<div class=\"paragraph\">\n<p>This is a helper function for creating such a variant object.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-desktop.1.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit-desktop(1)</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit-desktop(1)</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_name\">Name</a></li>\n<li><a href=\"#_synopsis\">Synopsis</a></li>\n<li><a href=\"#_description\">Description</a></li>\n<li><a href=\"#_environment\">Environment</a></li>\n<li><a href=\"#_bugs\">Bugs</a></li>\n<li><a href=\"#_author\">Author</a></li>\n<li><a href=\"#_see_also\">See also</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"_name\">Name</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>cockpit-desktop - Cockpit Desktop integration</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_synopsis\">Synopsis</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><strong>cockpit-desktop</strong> <em>URLPATH</em> [<em>SSH_HOST</em>]</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_description\">Description</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The <strong>cockpit-desktop</strong> program provides secure access to Cockpit pages\nin an already running desktop session. It starts a web server\n(<strong>cockpit-ws</strong>) and a web browser in an isolated network namespace, and\na <strong>cockpit-bridge(8)</strong> in the running user session.</p>\n</div>\n<div class=\"paragraph\">\n<p>This avoids having to log into Cockpit, and having to enable\n<strong>cockpit.socket</strong> system-wide. The network isolation ensures that no\nother user, and not even other processes in the user&#8217;s session, can\naccess this local web server.</p>\n</div>\n<div class=\"paragraph\">\n<p><strong>URLPATH</strong> is the Cockpit page to open, i. e. the path component of\nCockpit URLs. It is highly recommended to only open a\n<a href=\"https://cockpit-project.org/guide/latest/embedding.html\">particular page frame</a>, not the entire Cockpit navigation and menu. For example, the\npath <code>/cockpit/@localhost/storage/index.html</code> will open the Storage\npage. It is also possible to give abbreviated forms of urls, such as\n&#8220;/storage&#8221; or &#8220;/network/firewall&#8221;.</p>\n</div>\n<div class=\"paragraph\">\n<p><em>SSH_HOST</em> is an optional SSH remote host specification (<em>hostname</em>\nor <em>username@hostname</em>). If given, <strong>cockpit-bridge</strong> will be started\non the remote host through <strong>ssh(1)</strong> instead, i. e. the Cockpit web\nbrowser will show that remote host. Note that this is more of an\nexperimental/demo feature.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_environment\">Environment</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The <strong>BROWSER</strong> environment variable specifies the browser command (and\npossibly options) that will be used to open the requested Cockpit page.\nIf not set, <strong>cockpit-desktop</strong> attempts to use an internal minimalistic\nWebKit browser, and failing that, will attempt to detect some reasonable\nalternatives.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_bugs\">Bugs</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_author\">Author</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_see_also\">See also</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><strong>cockpit-ws(8)</strong>, <strong>cockpit-bridge(1)</strong></p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-error.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<meta name=\"author\" content=\"cockpit.js: Errors\">\n<title>cockpit.js: Errors</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.js: Errors</h1>\n<div class=\"details\">\n<span id=\"author\" class=\"author\">cockpit.js: Errors</span><br>\n</div>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#cockpit-problems\">Problem Codes</a></li>\n<li><a href=\"#cockpit-messages\">cockpit.message()</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Problem codes and messages</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-problems\">Problem Codes</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit represents problems with standardized problem string codes.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"access-denied\"</code></dt>\n<dd>\n<p>The user is not permitted to perform the action in question.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"authentication-failed\"</code></dt>\n<dd>\n<p>User authentication failed.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"internal-error\"</code></dt>\n<dd>\n<p>An unexpected internal error without further info. This should not\nhappen during the normal course of operations.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"no-cockpit\"</code></dt>\n<dd>\n<p>The system does not have a compatible version of Cockpit installed or\ninstalled properly.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"no-session\"</code></dt>\n<dd>\n<p>Cockpit is not logged in.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"not-found\"</code></dt>\n<dd>\n<p>Something specifically requested was not found, such as a file,\nexecutable etc.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"terminated\"</code></dt>\n<dd>\n<p>Something was terminated forcibly, such as a connection, process\nsession, etc.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"timeout\"</code></dt>\n<dd>\n<p>Something timed out.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"unknown-hostkey\"</code></dt>\n<dd>\n<p>The remote host had an unexpected or unknown key.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"no-forwarding\"</code></dt>\n<dd>\n<p>Could not forward authentication credentials to the remote host.</p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-messages\">cockpit.message()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>message = cockpit.message(problem)\nmessage = cockpit.message(exception)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Return a message for the <code>exception</code> or <code>problem</code> code passed as an\nargument. If the argument is an object with a <code>\"message\"</code> property, as\nis the case with most exceptions, that will be returned directly. If the\nargument is an object with a <code>\"problem\"</code> property, then it will be\nused as the problem code. An appropriate message will be returned for\nproblem codes.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-file.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit.js: File Access</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.js: File Access</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#cockpit-file-simple\">Simple reading and writing</a></li>\n<li><a href=\"#cockpit-file-format\">File format</a></li>\n<li><a href=\"#cockpit-file-binary\">Binary files</a></li>\n<li><a href=\"#cockpit-file-atomic\">Atomic modifications</a></li>\n<li><a href=\"#cockpit-file-notify\">Change notifications</a></li>\n<li><a href=\"#cockpit-file-path\">file.path</a></li>\n<li><a href=\"#cockpit-file-close\">Closing</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The <code>cockpit.file</code> API lets you read, write, and watch regular files\nin their entirety. It cannot efficiently do random access in a big file\nor read non-regular files such as <code>/dev/random</code>.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>file = cockpit.file(path,\n                    { syntax: syntax_object,\n                      binary: boolean,\n                      max_read_size: int,\n                      superuser: string,\n                    })\n\npromise = file.read()\npromise\n    .then((content, tag) =&gt; { ... })\n    .catch(error =&gt; { ... })\n\npromise = file.replace(content, [ expected_tag ])\npromise\n    .then(new_tag =&gt; { ... })\n    .catch(error =&gt; { ... })\n\npromise = file.modify(callback, [ initial_content, initial_tag ]\npromise\n    .then((new_content, new_tag) =&gt; { ... })\n    .catch(error =&gt; { ... })\n\nfile.watch((content, tag, [error]) =&gt; { }, [ { read: boolean } ])\n\nfile.close()</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-file-simple\">Simple reading and writing</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>You can read a file with code like this:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.file(\"/path/to/file\").read()\n    .then((content, tag) =&gt; {\n        ...\n    })\n    .catch(error =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>It is recommended to use absolute paths. Relative paths are resolved\nagainst <code>/</code>. To work with the current user&#8217;s files\n<a href=\"#cockpit-user\">cockpit.user()</a> can be used to get the user&#8217;s home\ndirectory.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>read()</code> method returns a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>When successful, the promise will be resolved with the content of the\nfile. Unless you specify options to change this (see below), the file is\nassumed to be text in the UTF-8 encoding, and <code>content</code> will be a\nstring.</p>\n</div>\n<div class=\"paragraph\">\n<p>The tag that is passed to the <code>then()</code> callback is a short string that\nis associated with the file and changes whenever the content of the file\nchanges. It is meant to be used with <code>replace()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>It is not an error when the file does not exist. In this case, the\n<code>then()</code> callback will be called with a <code>null</code> value for <code>content</code>\nand <code>tag</code> is <code>\"-\"</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>superuser</code> option can be used the same way as described in the\n<a href=\"#cockpit-channels-channel\">cockpit.channel()</a> to provide a different\naccess level to the file.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can use the <code>max_read_size</code> option to limit the amount of data\nthat is read. If the file is larger than the given number of bytes, no\ndata is read and the channel is closed with problem code <code>too-large</code>.\nThe default limit is 16 MiB. The limit can be completely removed by\nsetting it to -1.</p>\n</div>\n<div class=\"paragraph\">\n<p>To write to a file, use code like this:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.file(\"/path/to/file\").replace(\"my new content\\n\")\n    .then(tag =&gt; {\n        ...\n    })\n    .catch(error =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <code>replace()</code> method returns a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>When the promise is resolved, the file has been atomically replaced (via\nthe <code>rename()</code> syscall) with the new content. As with <code>read()</code>, by\ndefault the new content is a string and will be written to the file as\nUTF-8. The returned tag corresponds to the new content of the file.</p>\n</div>\n<div class=\"paragraph\">\n<p>When the promise is rejected because of an error, the file or its meta\ndata has not been changed in any way.</p>\n</div>\n<div class=\"paragraph\">\n<p>As a special case, passing the value <code>null</code> to <code>replace()</code> will\nremove the file.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>replace()</code> method can also check for conflicting changes to a\nfile. You can pass a tag (as returned by <code>read()</code> or <code>replace()</code>) to\n<code>replace()</code>, and the file will only be replaced if it still has the\ngiven tag. If the tag of the file has changed, <code>replace()</code> will fail\nwith an error object that has <code>error.problem == \"change-conflict\"</code>.\nSee <code>modify()</code> below for a convenient way to achieve transactional\nupdates to a file.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-file-format\">File format</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>By default, a file is assumed to be text encoded in UTF-8, and the\n<code>read()</code> and <code>replace()</code> functions use strings to represent the\ncontent.</p>\n</div>\n<div class=\"paragraph\">\n<p>By specifying the <code>syntax.parser()</code> and <code>syntax.stringify()</code>\noptions, you can cause <code>read()</code> to parse the content before passing it\nback to you, and <code>replace()</code> to unparse it before writing.</p>\n</div>\n<div class=\"paragraph\">\n<p>The main idea is to be able to write <code>{ syntax: JSON }</code>, of course,\nbut you can easily pass in individual functions or make your own\nparser/unparser object:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.file(\"/path/to/file.json\", { syntax: JSON })\n\nvar syntax_object = {\n    parse:     my_parser,\n    stringify: my_unparser\n};\n\ncockpit.file(\"/path/to/file\", { syntax: syntax_object })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Any exceptions thrown by the <code>parse()</code> and <code>stringify()</code> functions\nare caught and reported as read or write errors.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>null</code> value that is used to represent the content of a\nnon-existing file (see \"Simple reading and writing\", above) is not\npassed through the <code>parse()</code> and <code>stringify()</code> functions.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-file-binary\">Binary files</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>By default the content of the file is assumed to be text encoded as\nUTF-8 and it can not contain zero bytes. The content is represented as a\nJavaScript string with <code>read()</code>, <code>replace()</code>, etc. By setting the\n<code>binary</code> option to true when creating the proxy, no assumptions are\nplaced on the content, and it is represented as a <code>Uint8Array</code> in\nJavaScript.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-file-atomic\">Atomic modifications</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Use <code>modify()</code> to modify the content of the file safely. A call to\n<code>modify()</code> will read the content of the file, call <code>callback</code> on the\ncontent, and then replace the content of the file with the return value\nof the callback.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>modify()</code> method uses the <code>read()</code> and <code>replace()</code> methods\ninternally in the obvious way. Thus, the <code>syntax.parse()</code> and\n<code>syntax.stringify()</code> options work as expected, <code>null</code> represents a\nnon-existing file, and the watch callbacks are fired.</p>\n</div>\n<div class=\"paragraph\">\n<p>It will do this one or more times, until no other conflicting changes\nhave been made to the file between reading and replacing it.</p>\n</div>\n<div class=\"paragraph\">\n<p>The callback is called like this</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>new_content = callback (old_content)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The callback is allowed to mutate <code>old_content</code>, but note that this\nwill also mutate the objects that are passed to the watch callbacks.\nReturning <code>undefined</code> from the proxy is the same as returning\n<code>old_content</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>modify()</code> method returns a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The promise will be resolved with the new content and its tag, like so</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>function shout(old_content) {\n    return old_content.toUpperCase();\n}\n\ncockpit.file(\"/path/to/file\").modify(shout)\n    .then((content, tag) =&gt; {\n        ...\n    })\n    .catch(error =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If you have cached the last content and tag results of the <code>read()</code> or\n<code>modify()</code> method, or the last values passed to a watch callback, you\ncan pass them to <code>modify()</code> as the second and third argument. In this\ncase, <code>modify()</code> will skip the initial read and start with the given\nvalues.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-file-notify\">Change notifications</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Calling <code>watch()</code> will start monitoring the file for external changes.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>handle = file.watch(callback);\n\nhandle_no_read = file.watch(callback, { read: false });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Whenever a change occurs, the <code>callback()</code> is called with the new\ncontent and tag of the file. This might happen because of external\nchanges, but also as part of calls to <code>read()</code>, <code>replace()</code>, and\n<code>modify()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>When a read error occurs, the <code>callback()</code> is called with an error as\na third argument. Write errors are not reported via the watch callback.</p>\n</div>\n<div class=\"paragraph\">\n<p>Calling <code>watch()</code> will also automatically call <code>read()</code> to get the\ninitial content of the file. Thus, you normally don&#8217;t need to call\n<code>read()</code> at all when using <code>watch()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>To disable the automatic reading, e.g. for large files or unreadable\nfile system objects, set the <code>read</code> option to <code>false</code>. The first\n<code>content</code> argument of the callback will then always be <code>null</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>To free the resources used for monitoring, call <code>handle.remove()</code>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-file-path\">file.path</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>A string containing the path that was passed to the <code>cockpit.file()</code>\nmethod.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-file-close\">Closing</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Call the <code>close()</code> method on a file proxy to cancel all ongoing\noperations, such as reading, writing, and monitoring. The proxy should\nnot be used after closing it.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-http.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit.js: HTTP Client</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.js: HTTP Client</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#cockpit-http-constructor\">cockpit.http()</a></li>\n<li><a href=\"#cockpit-http-get\">http.get()</a></li>\n<li><a href=\"#cockpit-http-post\">http.post()</a></li>\n<li><a href=\"#cockpit-http-request\">http.request()</a></li>\n<li><a href=\"#cockpit-http-then\">request.then()</a></li>\n<li><a href=\"#cockpit-http-catch\">request.catch()</a></li>\n<li><a href=\"#cockpit-http-response\">request.response()</a></li>\n<li><a href=\"#cockpit-http-stream\">request.stream()</a></li>\n<li><a href=\"#cockpit-http-input\">request.input()</a></li>\n<li><a href=\"#cockpit-http-close\">request.close()</a></li>\n<li><a href=\"#cockpit-http-close-all\">http.close()</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit allows access to local HTTP and REST services via this API.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-http-constructor\">cockpit.http()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>http = cockpit.http(endpoint, [options])\nhttp = cockpit.http(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new HTTP client. The <code>endpoint</code> can be a file path starting\nwith <code>/</code> to connect to a unix socket, or it can be a port number to\nconnect to. The optional <code>options</code> argument is a javascript plain\nobject, and may include:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"address\"</code></dt>\n<dd>\n<p>Connect to an address other than localhost. Must be a valid host name\nor IP address. To use this option you also must provide a port number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"port\"</code></dt>\n<dd>\n<p>Port number to use with \"address\" option, when not given in\n<code>endpoint</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"tls\"</code></dt>\n<dd>\n<p>Object properties for an https connection. See\n<code>http-stream2 TLS options</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"headers\"</code></dt>\n<dd>\n<p>Additional HTTP headers to include with the HTTP request. This is a\nplain javascript object with each key as a header name, and each value\nas the header value.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to open this channel as root. If the currently\nlogged in user is not permitted to become root (eg: via <code>pkexec</code>)\nthen the <code>channel</code> will immediately be\n<a href=\"#cockpit-channels-close-ev\">closed</a> with a <code>\"access-denied\"</code>\nproblem code.\n+\nSet to <code>\"try\"</code> to try to make the request as root, but if that\nfails, fall back to perform an unprivileged request.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"tls\"</code></dt>\n<dd>\n<p>If set to a plain javascript object, then the connection will be an\nHTTPS connection and include TLS encryption. The fields of the <code>tls</code>\nobject declare various TLS configuration and data. All fields are\noptional:\n+</p>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><code>\"authority\"</code>: Certificate authority(s) to expect as signers of\nthe server&#8217;s TLS certificate, represented as a plain javascript\nobject. It should have either a <code>\"file\"</code> field containing a readable\nPEM file on the system containing authorities, or a <code>\"data\"</code> with\nPEM encoded certificate data.</p>\n</li>\n<li>\n<p><code>\"certificate\"</code>: A client certificate to use, represented as a\nplain javascript object. It should have either a <code>\"file\"</code> field\ncontaining a readable PEM file on the system to use as a certificate,\nor a <code>\"data\"</code> with PEM encoded certificate data.</p>\n</li>\n<li>\n<p><code>\"key\"</code>: A client key to use, represented as a plain javascript\nobject. It should have either a <code>\"file\"</code> field containing a readable\nPEM file on the system to use as a key, or a <code>\"data\"</code> with PEM\nencoded key data.</p>\n</li>\n<li>\n<p><code>\"validate\"</code>: A boolean that describes whether to validate the\nserver&#8217;s TLS certificate or not. By default local connections are not\nvalidated, and remote connections are validated.</p>\n</li>\n</ul>\n</div>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Here is a somewhat complex example of using most of the above\n<code>options</code> when when calling <code>cockpit.http()</code>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>http = cockpit.http({\n    \"address\": \"localhost\",\n    \"headers\": {\n        \"Authorization\": \"Basic dXNlcjpwYXNzd29yZA==\"\n    },\n    \"port\": 443,\n    \"tls\": {\n        \"validate\": true,\n        \"authority\": {\n            \"file\": \"/etc/pki/tls/certs/ca-bundle.crt\",\n        },\n        \"certificate\": {\n            \"data\": \"-----BEGIN CERTIFICATE-----\\nMIIDsDCCA...\"\n        },\n        \"key\": {\n            \"data\": \"-----BEGIN RSA PRIVATE KEY-----\\nMIIEogIBA...\"\n        }\n    }\n});</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-http-get\">http.get()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request = http.get(path, [params, [headers]])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Perform an HTTP GET request for the given <code>path</code>. If the <code>params</code> is\nspecified it should be a plain javascript object, which will be turned\ninto a query string.</p>\n</div>\n<div class=\"paragraph\">\n<p>Optionally a plain javascript object containing headers can be included\nin the <code>headers</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>The return value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete if the request happens successfully, or fail if\nthere&#8217;s a problem.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-http-post\">http.post()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request = http.post(path, body, [headers])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Perform an HTTP POST request for the given <code>path</code>. The <code>body</code> can be\na string, or a javascript plain object, which will be encoded as JSON\ndata. If <code>body</code> is <code>undefined</code> or <code>null</code> then an empty HTTP body\nwill be sent.</p>\n</div>\n<div class=\"paragraph\">\n<p>Optionally a plain javascript object containing headers can be included\nin the <code>headers</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>The return value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete if the request happens successfully, or fail if\nthere&#8217;s a problem.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-http-request\">http.request()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request = http.request(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Perform an HTTP request. The <code>options</code> can contain the following:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"body\"</code></dt>\n<dd>\n<p>The HTTP request body. If you do not specify a body, then you must\ncall <a href=\"#cockpit-http-input\">request.input()</a> to complete the body\nand allow the request to start.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"headers\"</code></dt>\n<dd>\n<p>A javascript plain object containing HTTP headers.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"method\"</code></dt>\n<dd>\n<p>The HTTP method. Defaults to <code>\"GET\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"params\"</code></dt>\n<dd>\n<p>A javascript plain object containing query string parameters.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"path\"</code></dt>\n<dd>\n<p>The HTTP path. Defaults to <code>/</code>.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The return value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete if the request happens successfully, or fail if\nthere&#8217;s a problem.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-http-then\">request.then()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.then(data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the request finishes\nsuccessfully.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> argument contains the body result of the request. If it a\nstring, unless the process was opened in binary mode, in which case the\n<code>data</code> is an array of bytes. If a <code>request.stream()</code> handler is set\nup, then any standard output data consumed by the handler will not be\nincluded in the <code>data</code> argument.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-http-catch\">request.catch()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.catch((exception[, data]) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the request fails, or\nreturns an error code.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>exception</code> object passed to the handler can have the following\nfields:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>problem</code></dt>\n<dd>\n<p>A <a href=\"#cockpit-problems\">problem code</a> string when a problem occurred\nstarting or communicating with the server. This is <code>null</code> if the\nprocess exited or was terminated.</p>\n</dd>\n<dt class=\"hdlist1\"><code>status</code></dt>\n<dd>\n<p>The numeric status of the response. This is <code>null</code> if no response\nwas received.</p>\n</dd>\n<dt class=\"hdlist1\"><code>reason</code></dt>\n<dd>\n<p>A string reason returned in the response. This is <code>null</code> if no\nresponse was received.</p>\n</dd>\n<dt class=\"hdlist1\"><code>message</code></dt>\n<dd>\n<p>A string message returned in the response. This is <code>null</code> if no\nresponse was received.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>If the request returned a response body, it will be available in the\n<code>data</code> argument. Otherwise this argument will be <code>undefined</code>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-http-response\">request.response()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.response((status, headers) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This sets up a handler to be called when the HTTP request gets the\ninitial response from the server. The <code>status</code> argument is the HTTP\nstatus integer, and the <code>headers</code> is a plain javascript object\ncontaining the headers of the response.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-http-stream\">request.stream()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.stream(data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This sets up a handler to be called when the request returns output\ndata. The handler will be called multiple times.</p>\n</div>\n<div class=\"paragraph\">\n<p>Only one handler may be registered at a time. Registering an additional\nhandler replaces the previous one. The handler receives either string\n<code>data</code> or an array of binary bytes as its argument. A stream handler\nmay return a number, which indicates the number of characters or bytes\nconsumed from <code>data</code>. Any data not consumed will be included again the\nnext time the handler is called.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>request.stream()</code> handler is set up, then the <code>request.then()</code>\nhandlers will only get any remaining data not consumed by the stream\nhandler.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-http-input\">request.input()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.input(data, [stream])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This method writes <code>data</code> to the HTTP request body. It is only valid\nif no <code>\"body\"</code> has been specified in\n<a href=\"#cockpit-http-request\">http.request()</a> options. If <code>stream</code> is\n<code>true</code> then this function can be called again to provide further data.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-http-close\">request.close()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cancel the request. If <code>problem</code> is specified it should be a standard\n<a href=\"#cockpit-problems\">problem code</a> string.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-http-close-all\">http.close()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>http.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cancel all outstanding requests with the given problem code. This is\nuseful when you know that the server is going down soon.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-locale.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit.js: Localization</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.js: Localization</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#cockpit-locale-language\">cockpit.language</a></li>\n<li><a href=\"#cockpit-locale-locale\">cockpit.locale()</a></li>\n<li><a href=\"#cockpit-locale-gettext\">cockpit.gettext()</a></li>\n<li><a href=\"#cockpit-locale-noop\">cockpit.noop()</a></li>\n<li><a href=\"#cockpit-locale-ngettext\">cockpit.ngettext()</a></li>\n<li><a href=\"#cockpit-locale-translate\">cockpit.translate()</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit provides a <a href=\"https://www.gnu.org/software/gettext/\"><code>gettext()</code></a>\nlike API for easy translation of strings.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-locale-language\">cockpit.language</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The current locale language code. This is set based on the\n<a href=\"#cockpit-locale-locale\"><code>cockpit.locale()</code></a> data loaded.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-locale-locale\">cockpit.locale()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.locale(po)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Load locale information for a given <code>po</code> data. The data should be JSON\ndata in the <a href=\"https://www.npmjs.org/package/po2json\">po2json</a> format. The\ndata will be loaded globally. If <code>po</code> data has already been loaded,\nthen this will extend that loaded data with additional strings. Any\nidentical translations strings will be replaced with the new strings. A\n<code>null</code> argument clears all the locale information previously loaded.</p>\n</div>\n<div class=\"paragraph\">\n<p>Various methods such as\n<a href=\"#cockpit-locale-gettext\"><code>cockpit.gettext()</code></a> make use of the\nloaded data.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-locale-gettext\">cockpit.gettext()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>translated = cockpit.gettext([context], string)\nvar _ = cockpit.gettext\nvar C_ = cockpit.gettext\ntranslated = _(\"string\")\ntranslated = C_(\"context\", \"string\")</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Lookup <code>string</code> for translation in the loaded locale data. The\ntranslated string will be returned, or <code>string</code> will be returned if no\nsuch translated string is present. The <code>context</code> argument is an\noptional string used to qualify the string.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function can be assigned to a variable called <code>_</code> (underscore)\nwhich will make your code work with the typical <code>_(\"string\")</code> syntax.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-locale-noop\">cockpit.noop()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>var N_ = cockpit.noop\nvar NC_ = cockpit.noop</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>A noop function suitable for assigning to <code>N_</code> or <code>NC_</code> so that\ngettext scanners will be able to find translatable strings. More\nspecifically this function returns its last argument.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-locale-ngettext\">cockpit.ngettext()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>translated = cockpit.ngettext([context], string1, stringN, number)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Lookup a string appropriate for a pluralization form of the <code>number</code>.\nVarious languages have complex pluralization forms that go far between\nthe singular and plural forms speakers of English are familiar with. If\nno such translated string is found then either one of <code>string1</code> or\n<code>stringN</code> is returned according to simple pluralization rules.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>context</code> argument is an optional string used to qualify the\nstring.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-locale-translate\">cockpit.translate()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.translate()\ncockpit.translate(element, ...)\ncockpit.translate(selection)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The document will be scanned for <code>translate</code> tags and they will be\ntranslated according to the strings in loaded locale data. One or more\n<code>element</code> arguments may be specified. These are DOM elements for\nspecific parts of the document to be translated. If no <code>element</code> is\nspecified then the entire document is translated.</p>\n</div>\n<div class=\"paragraph\">\n<p>If an array or array-like object is passed as a <code>selection</code> then all\nDOM elements in the array will be treated as parts of the document to be\ntranslated.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-location.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit.js: Page Location and Jumping</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.js: Page Location and Jumping</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#cockpit-location-general\">Page location</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-location-href\">location.href</a></li>\n<li><a href=\"#cockpit-location-path\">location.path</a></li>\n<li><a href=\"#cockpit-location-options\">location.options</a></li>\n<li><a href=\"#cockpit-location-go\">location.go()</a></li>\n<li><a href=\"#cockpit-location-replace\">location.replace()</a></li>\n<li><a href=\"#cockpit-location-decode\">location.decode()</a></li>\n<li><a href=\"#cockpit-location-encode\">location.encode()</a></li>\n<li><a href=\"#cockpit-location-changed\">cockpit.onlocationchanged</a></li>\n</ul>\n</li>\n<li><a href=\"#cockpit-jump\">Jumping between components</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-jump-jump\">cockpit.jump()</a></li>\n<li><a href=\"#cockpit-jump-hidden\">cockpit.hidden</a></li>\n<li><a href=\"#cockpit-jump-visibilitychange\">cockpit.onvisibilitychange</a></li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Page location and navigation between components</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-location-general\">Page location</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>location = cockpit.location\ncockpit.location = \"/path\"</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit components often have different views, without changing the HTML\nfile that is being viewed. These are known as pages.\n<code>cockpit.location</code> is an object that can be used to read the current\npage and to navigate to a different page location. It works by updating\n<code>window.location.hash</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>cockpit.location</code> looks like a HTTP path with a possible query\nstring:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>/path/sub/page?option=value,option2</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-location-path\"><code>location.path</code></a> and\n<a href=\"#cockpit-location-options\"><code>location.options</code></a> contain a parsed\nform of the location. While the location cannot be modified in place, a\nnew one can be created by assigning a string to <code>cockpit.location</code> or\nby calling the <a href=\"#cockpit-location-go\"><code>location.go()</code></a> function.</p>\n</div>\n<div class=\"paragraph\">\n<p><code>cockpit.location</code> is designed similarly to <code>window.location</code> in\nthat the location object is preplaced whenever the current page location\nchanges. To be aware of when the page location changes listen for the\n<a href=\"#cockpit-location-changed\"><code>cockpit.onlocationchanged</code></a> event.</p>\n</div>\n<div class=\"paragraph\">\n<p>Using the location object as a string will result in the\n<a href=\"#cockpit-location-href\"><code>location.href</code></a>.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-location-href\">location.href</h3>\n<div class=\"paragraph\">\n<p>The string representation of this page location, including any options.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-location-path\">location.path</h3>\n<div class=\"paragraph\">\n<p>An array of path segments, parsed and decoded appropriately. An empty\narray denotes the root path.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-location-options\">location.options</h3>\n<div class=\"paragraph\">\n<p>A javascript object containing the various options present in the\nlocation.</p>\n</div>\n<div class=\"paragraph\">\n<p>If an option appears more than once, its value will be an array.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-location-go\">location.go()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>location.go(path, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Changes the current location to the given <code>path</code> and <code>options</code>. If\nthe <code>path</code> argument is a string, it will be parsed into a path. If it\nis a relative path, then the result will be relative to the current\n<code>location.path</code>. If the <code>path</code> argument is an array of path\nsegments, it will be treated as a full parsed absolute path.</p>\n</div>\n<div class=\"paragraph\">\n<p>Any options found in a <code>path</code> will be added to those in the optional\n<code>options</code> argument, and used in the result.</p>\n</div>\n<div class=\"paragraph\">\n<p>The location change will only take effect if the location has not\nchanged in the meantime. This can be to good effect by saving a\n<code>cockpit.location</code> object and doing a conditional navigation, by\ncalling the saved <code>location.go()</code> method later. This will only\nnavigate if the user or other code has not navigated in the meantime.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-location-replace\">location.replace()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>location.replace(path, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Similar to <a href=\"#cockpit-location-go\"><code>location.go()</code></a> except the\nlocation change will not result in a navigation change in the browser&#8217;s\nhistory.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-location-decode\">location.decode()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>path = location.decode(href, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Decode a cockpit href into its <code>path</code> array. If the <code>options</code>\nargument is specified, then it will be populated with options found in\nthe href.</p>\n</div>\n<div class=\"paragraph\">\n<p>If href is a relative path it will be resolved relative to\n<code>location.href</code>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-location-encode\">location.encode()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>href = location.encode(path, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Encode the given <code>path</code> and <code>options</code> into a cockpit href. The\n<code>path</code> argument may be an array of path segments, or a string path. If\na relative path is passed, it will be resolved relative to\n<code>location.href</code>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-location-changed\">cockpit.onlocationchanged</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.addEventListener(\"locationchanged\", function() { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event emitted when over the <code>cockpit.location</code> changes. Typically a\ncomponent reacts to this event by updating its interface to reflect the\nnew <a href=\"#cockpit-location-path\"><code>cockpit.location.path</code></a> and\n<a href=\"#cockpit-location-options\"><code>cockpit.location.options</code></a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This event is not triggered immediately during a <code>location.go()</code> or\nsimilar call. It will be triggered asynchronously at a later time.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-jump\">Jumping between components</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.jump(\"/system/log\")</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>In Cockpit in there multiple components shown. In order to tell Cockpit\nto jump to and show another component and a certain location within that\ncomponent, use the <code>cockpit.jump()</code> function. Stable component paths\nare documented. Don&#8217;t assume you can navigate into paths that are not\nstable API.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-jump-jump\">cockpit.jump()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.jump(path, [ host ])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Ask Cockpit to jump to another component. The location of the current\ncomponent will not be affected. The <code>path</code> argument can be a string\npath, starting with <code>/</code> or an array containing the parts of a path\nthat will be joined to create a path. If <code>host</code> is not specified, then\nthe component on the same host as the caller will be displayed. If host\nis null, then the host portion of the path will be removed, displaying\nthe component on the host that cockpit is connected directly to.</p>\n</div>\n<div class=\"paragraph\">\n<p>If the calling component is not running within Cockpit, or the calling\ncomponent is not currently displayed, then the jump will not happen, and\nthis function has no effect.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-jump-hidden\">cockpit.hidden</h3>\n<div class=\"paragraph\">\n<p>A boolean property that indicates if the current component page is\nvisible or hidden. When the code or user jumps to another component, the\nprior one remains loaded and initialized but is hidden. Use this\nproperty together with the\n<a href=\"#cockpit-jump-visibilitychange\"><code>cockpit.onvisibilitychange</code></a>\nevent to decide whether or not to perform expensive tasks to update the\ninterface.</p>\n</div>\n<div class=\"paragraph\">\n<p>This property is analogous to the <code>document.hidden</code> page visibility\nAPI, but works with the document and frame implementation of Cockpit.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-jump-visibilitychange\">cockpit.onvisibilitychange</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.onvisibilitychange = function() { ... }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when the\n<a href=\"#cockpit-jump-hidden\"><code>cockpit.hidden</code></a> property changes. This\nevent is similar to the <code>document.onvisibilitychange</code> API, but works\nwith the document and frame implementation of Cockpit.</p>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-login.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit.js: User Session</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.js: User Session</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#cockpit-logout\">cockpit.logout()</a></li>\n<li><a href=\"#cockpit-user\">cockpit.user()</a></li>\n<li><a href=\"#cockpit-permission\">Permission lookup</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-permission-constructor\">cockpit.permission()</a></li>\n<li><a href=\"#cockpit-permission-allowed\">permission.allowed</a></li>\n<li><a href=\"#cockpit-permission-changed\">permission.onchanged</a></li>\n<li><a href=\"#cockpit-permission-close\">permission.close()</a></li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>User information and login session state</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-logout\">cockpit.logout()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.logout([reload])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Logout of Cockpit. Unless <code>reload</code> is <code>false</code> this will also cause\nthe page to be reloaded, so that the user can see the logged out state.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-user\">cockpit.user()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>var promise = cockpit.user();\npromise.then(user =&gt; { ... });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This object contains information about the user that&#8217;s currently logged\ninto cockpit. The following fields are defined:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"id\"</code></dt>\n<dd>\n<p>This is unix user id.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"gid\"</code></dt>\n<dd>\n<p>This is unix user group id.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"name\"</code></dt>\n<dd>\n<p>This is the unix user name like <code>\"root\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"full_name\"</code></dt>\n<dd>\n<p>This is a readable name for the user.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"groups\"</code></dt>\n<dd>\n<p>This is an array of group names to which the user belongs. Since\nversion 318, the first item in this list is the primary group.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"home\"</code></dt>\n<dd>\n<p>This is user&#8217;s home directory.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"shell\"</code></dt>\n<dd>\n<p>This is unix user shell.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Returns a promise that completes once the user information is available.</p>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p><code>cockpit.user()</code> is soft-deprecated since Cockpit 336, if your page\ndoes not need to maintain compatibility with older Cockpit versions you\ncan use<a href=\"#cockpit-info\">cockpit.info</a> to obtain the user information.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-permission\">Permission lookup</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit provides a mechanism for checking if the current user satisfies\na given criteria. This is meant for updating UI elements based on what\nactions the user can perform. It is <em>not an access control mechanism</em>.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-permission-constructor\">cockpit.permission()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>permission = cockpit.permission([options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new permission object to check if the current user has a\nparticular permission specified by <code>options</code>:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>admin: true</code></dt>\n<dd>\n<p>True if the session has superuser privileges, i.e. can run channels as\nroot with <code>{ superuser: \"require\" }</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>group:</code> <em>name</em></dt>\n<dd>\n<p>True if the currently logged user is a member of group <em>name</em>.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The permission result is always true for the \"root\" user. When\n<code>options</code> is not given, check if the current user is root.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-permission-allowed\">permission.allowed</h3>\n<div class=\"paragraph\">\n<p>A boolean value which indicates if the permission is allowed or not.\nThis will be <code>null</code> if the permission is unknown, or there was an\nerror checking the permission or the permission data has not yet loaded.\nThis property will update asynchronously and if you wish to be notified\nof changes connect to the\n<a href=\"#cockpit-permission-changed\">permission.onchanged</a> event.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-permission-changed\">permission.onchanged</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>permission.addEventListener(\"changed\", function() { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is fired when the permission changes. In particular the\n<a href=\"#cockpit-permission-allowed\">permission.allowed</a> property.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-permission-close\">permission.close()</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>permission.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Closes the permission object and tears down any registered callbacks and\ndbus subscriptions.</p>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-manifest.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit.js: Manifests</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.js: Manifests</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#cockpit-manifest-loading\">Loading Manifests</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"cockpit-manifest-loading\">Loading Manifests</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>For a convenient access to all page manifests, include\n<code>&lt;script src=\"../manifests.js\"&gt;&lt;/script&gt;</code> into your page to register\nthe manifests at the <code>cockpit.manifests</code> global variable.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can also load <code>../manifests.json</code> directly in your page, with\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch\"><code>fetch()</code></a>.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-manual.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Manual pages</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"cockpit-manual\" class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>Manual pages</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_cockpit1\">cockpit(1)</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_name\">Name</a></li>\n<li><a href=\"#_description\">Description</a></li>\n<li><a href=\"#_components\">Components</a></li>\n<li><a href=\"#_bugs\">Bugs</a></li>\n<li><a href=\"#_author\">Author</a></li>\n<li><a href=\"#_see_also\">See also</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_conf5\">cockpit.conf(5)</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_name_2\">Name</a></li>\n<li><a href=\"#_description_2\">Description</a></li>\n<li><a href=\"#_webservice\">WebService</a></li>\n<li><a href=\"#_log\">Log</a></li>\n<li><a href=\"#_oauth\">OAuth</a></li>\n<li><a href=\"#_session\">Session</a></li>\n<li><a href=\"#_bugs_2\">Bugs</a></li>\n<li><a href=\"#_author_2\">Author</a></li>\n<li><a href=\"#_see_also_2\">See also</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_ws8\">cockpit-ws(8)</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_name_3\">Name</a></li>\n<li><a href=\"#_synopsis\">Synopsis</a></li>\n<li><a href=\"#_description_3\">Description</a></li>\n<li><a href=\"#_transport_security\">Transport security</a></li>\n<li><a href=\"#_timeout\">Timeout</a></li>\n<li><a href=\"#_options\">Options</a></li>\n<li><a href=\"#_environment\">Environment</a></li>\n<li><a href=\"#_bugs_3\">Bugs</a></li>\n<li><a href=\"#_author_3\">Author</a></li>\n<li><a href=\"#_see_also_3\">See also</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_tls8\">cockpit-tls(8)</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_name_4\">Name</a></li>\n<li><a href=\"#_synopsis_2\">Synopsis</a></li>\n<li><a href=\"#_description_4\">Description</a></li>\n<li><a href=\"#_transport_security_2\">Transport security</a></li>\n<li><a href=\"#_options_2\">Options</a></li>\n<li><a href=\"#_environment_2\">Environment</a></li>\n<li><a href=\"#_bugs_4\">Bugs</a></li>\n<li><a href=\"#_author_4\">Author</a></li>\n<li><a href=\"#_see_also_4\">See also</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_desktop1\">cockpit-desktop(1)</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_name_5\">Name</a></li>\n<li><a href=\"#_synopsis_3\">Synopsis</a></li>\n<li><a href=\"#_description_5\">Description</a></li>\n<li><a href=\"#_environment_3\">Environment</a></li>\n<li><a href=\"#_bugs_5\">Bugs</a></li>\n<li><a href=\"#_author_5\">Author</a></li>\n<li><a href=\"#_see_also_5\">See also</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_bridge1\">cockpit-bridge(1)</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_name_6\">Name</a></li>\n<li><a href=\"#_synopsis_4\">Synopsis</a></li>\n<li><a href=\"#_description_6\">Description</a></li>\n<li><a href=\"#_options_3\">Options</a></li>\n<li><a href=\"#_bugs_6\">Bugs</a></li>\n<li><a href=\"#_author_6\">Author</a></li>\n<li><a href=\"#_see_also_6\">See also</a></li>\n</ul>\n</li>\n<li><a href=\"#_pam_ssh_add8\">pam_ssh_add(8)</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_name_7\">Name</a></li>\n<li><a href=\"#_description_7\">Description</a></li>\n<li><a href=\"#_options_4\">Options</a></li>\n<li><a href=\"#_examples\">Examples</a></li>\n<li><a href=\"#_bugs_7\">Bugs</a></li>\n<li><a href=\"#_author_7\">Author</a></li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"_cockpit1\">cockpit(1)</h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"_name\">Name</h3>\n<div class=\"paragraph\">\n<p>cockpit - Cockpit</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_description\">Description</h3>\n<div class=\"paragraph\">\n<p>Cockpit is a web accessible interactive admin interface for Linux\nmachines. Cockpit can usually be accessed on port <code>9090</code> of the\nmachine it&#8217;s installed on. Cockpit starts on demand. Use your system\ncredentials to log in.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_components\">Components</h3>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-ws</strong> web service listens on port <code>9090</code> and is started\non demand by <strong>systemd</strong>. The Cockpit web service authenticates the\nuser, loads Cockpit into the browser, and starts <strong>cockpit-bridge</strong> in a\nLinux user session.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-bridge</strong> provides Cockpit in the web browser with access\nto the system APIs. It does this over its standard in and standard out.\nThe bridge is started like a shell once per Linux user session.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_bugs\">Bugs</h3>\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_author\">Author</h3>\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_see_also\">See also</h3>\n<div class=\"paragraph\">\n<p><strong>cockpit-tls(8)</strong> , <strong>cockpit.bridge(1)</strong> , <strong>systemd(1)</strong>, <strong><a href=\"https://cockpit-project.org/guide/latest\">Cockpit guide</a></strong></p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_conf5\">cockpit.conf(5)</h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"_name_2\">Name</h3>\n<div class=\"paragraph\">\n<p>cockpit.conf - Cockpit configuration file</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_description_2\">Description</h3>\n<div class=\"paragraph\">\n<p>Cockpit can be configured via /etc/cockpit/cockpit.conf. If\n<strong>$XDG_CONFIG_DIRS</strong> is set, then the first path containing a\n<strong>../cockpit/cockpit.conf</strong> is used instead. Other configuration files\nand directories are searched for in the same way.</p>\n</div>\n<div class=\"paragraph\">\n<p>This file is not required and may need to be created manually. The file\nhas a INI file syntax and thus contains key / value pairs, grouped into\ntopical groups. See the examples below for details.</p>\n</div>\n<div class=\"paragraph\">\n<p>Note: The port that cockpit listens on cannot be changed in this file.\nTo change the port change the systemd <strong>cockpit.socket</strong> file.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_webservice\">WebService</h3>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>Origins</strong></dt>\n<dd>\n<p>By default cockpit will not accept crossdomain websocket connections.\nUse this setting to allow access from alternate domains. Origins\nshould include scheme, host and port, if necessary. Wildcards and glob\nexpressions are permitted. IPv6 addresses must have their brackets escaped\nwith backslashes (e.g. <code>\\[::1\\]</code>) as they are matched using <code>fnmatch()</code>.\n<br></p>\n</dd>\n</dl>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-ini\" data-lang=\"ini\">[WebService]\nOrigins = https://somedomain1.com https://somedomain2.com:9090 https://*.somedomain3.com https://\\[::1\\]:9090</code></pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>ProtocolHeader</strong></dt>\n<dd>\n<p>Configure cockpit to look at the contents of this header to determine\nif a connection is using tls. This should only be used when cockpit is\nbehind a reverse proxy, and care should be taken to make sure that\nincoming requests cannot set this header.\n<br></p>\n</dd>\n</dl>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-ini\" data-lang=\"ini\">[WebService]\nProtocolHeader = X-Forwarded-Proto</code></pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>ForwardedForHeader</strong></dt>\n<dd>\n<p>Configure cockpit to look at the contents of this header to determine\nthe real origin of a connection. This should only be used when cockpit\nis behind a reverse proxy, and care should be taken to make sure that\nincoming requests cannot set this header.\n<br></p>\n</dd>\n</dl>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-ini\" data-lang=\"ini\">[WebService]\nForwardedForHeader = X-Forwarded-For</code></pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>LoginTitle</strong></dt>\n<dd>\n<p>Set the browser title for the login screen.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>LoginTo</strong></dt>\n<dd>\n<p>When set to <code>true</code> the <em>Connect to</em> option on the login screen is\nvisible and allows logging into another server. When set to <code>false</code>,\ndirect remote logins are disallowed. If this option is not specified\nthen it will be automatically detected based on whether the\n<strong>cockpit-bridge</strong> package is installed and the <strong>ssh</strong> program is\navailable.<br>\n<br>\nIf cockpit-ws is exposed to the public internet, and also has access\nto a private internal network, it is recommended to explicitly set\n<strong>LoginTo=false</strong>. This prevents unauthenticated remote attackers from\nscanning the internal network for existing machines and open ports.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>RequireHost</strong></dt>\n<dd>\n<p>When set to <code>true</code> cockpit will require users to use the <em>Connect\nto</em> option to specify the host to log into.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>AllowMultiHost</strong></dt>\n<dd>\n<p>When set to <code>true</code>, cockpit will allow users to connect to multiple\nhosts in one session. The default is OS specific.<br>\n<br>\nWhen connecting to multiple servers, JavaScript runs without\nisolation. All systems will be vulnerable to potential attacks from\nother connected hosts. Enable this option <em>only</em> when all hosts are\ntrusted.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>MaxStartups</strong></dt>\n<dd>\n<p>Same as the <strong>sshd</strong> configuration option by the same name. Specifies\nthe maximum number of concurrent login attempts allowed. Additional\nconnections will be dropped until authentication succeeds or the\nconnections are closed. Defaults to 10.<br>\n<br>\nAlternatively, random early drop can be enabled by specifying the\nthree colon separated values <strong>start:rate:full</strong> (e.g. \"10:30:60\").\nCockpit will start refusing authentication attempts with a probability\nof <strong>rate/100</strong> (30%) if there are currently <strong>start</strong> (10)\nunauthenticated connections. The probability increases linearly and\nall connection attempts are refused if the number of unauthenticated\nconnections reaches <strong>full</strong> (60).</p>\n</dd>\n<dt class=\"hdlist1\"><strong>AllowUnencrypted</strong></dt>\n<dd>\n<p>If true, cockpit will accept unencrypted HTTP connections. Otherwise,\nit redirects all HTTP connections to HTTPS. Exceptions are connections\nfrom localhost and for certain URLs (like <strong>/ping</strong>). Defaults to\nfalse.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>UrlRoot</strong></dt>\n<dd>\n<p>The root URL where you will be serving cockpit. When provided cockpit\nwill expect all requests to be prefixed with the given url. This is\nmostly useful when you are using cockpit behind a reverse proxy, such\nas nginx. <code>/cockpit/</code> and <code>/cockpit+</code> are reserved and should not\nbe used. For example <code>/cockpit-new/</code> is ok. <code>/cockpit/</code> and\n<code>/cockpit+new/</code> are not.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>ClientCertAuthentication</strong></dt>\n<dd>\n<p>If true, enable TLS client certificates for authenticating users.\nCommonly these are provided by a smart card, but it&#8217;s equally possible\nto import certificates directly into the web browser. Please see the\n<a href=\"https://cockpit-project.org/guide/latest/cert-authentication.html\">Certificate/smart\ncard authentication</a> section in the Cockpit guide for details.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>Shell</strong></dt>\n<dd>\n<p>The relative URL to top level component to display in Cockpit once\nlogged in. Defaults to <code>/shell/index.html</code></p>\n</dd>\n<dt class=\"hdlist1\"><strong>CustomLoginPage</strong></dt>\n<dd>\n<p>Load the login page from an alternative directory. The directory must\ncontain a <code>login.html</code> and optionally a <code>po.js</code> file for translations.\nWhen not set, the hardcoded <code>$prefix/share/cockpit/static</code> directory is used.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_log\">Log</h3>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>Fatal</strong></dt>\n<dd>\n<p>The kind of log messages in the bridge to treat as fatal. Separate\nmultiple values with spaces. Relevant values are: <strong>criticals</strong> and\n<strong>warnings</strong>.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_oauth\">OAuth</h3>\n<div class=\"paragraph\">\n<p>Cockpit can be configured to support the\n<a href=\"https://tools.ietf.org/html/rfc6749#section-4.2\">implicit grant</a> OAuth\nauthorization flow. When successful the resulting oauth token will be\npassed to cockpit-ws using the <strong>Bearer</strong> auth-scheme. For a login to be\nsuccessful, cockpit will also need a to be configured to verify and\nallow <strong>Bearer</strong> tokens.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>URL</strong></dt>\n<dd>\n<p>This is the url that cockpit will redirect the users browser to when\nit needs to obtain an oauth token. Cockpit will add a redirect_uri\nparameter to the url with the location of where the oauth provider\nshould redirect to once a token has been obtained.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>ErrorParam</strong></dt>\n<dd>\n<p>When a oauth provider redirects a user back to cockpit, look for this\nparameter in the querystring or fragment portion of the url to find a\nerror message. When not provided it will default to\n<strong>error_description</strong></p>\n</dd>\n<dt class=\"hdlist1\"><strong>TokenParam</strong></dt>\n<dd>\n<p>When a oauth provider redirects a user back to cockpit, look for this\nparameter in the querystring or fragment portion of the url to find\nthe access token. When not provided it will default to\n<strong>access_token</strong></p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_session\">Session</h3>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>Banner</strong></dt>\n<dd>\n<p>The contents of the specified file (commonly <strong>/etc/issue</strong>) are shown\non the login page. By default, no banner is displayed.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>IdleTimeout</strong></dt>\n<dd>\n<p>Time in minutes after which session expires and user is logged out if\nno user action has been performed in the given time. This idle timeout\nonly applies to interactive password logins. With non-interactive\nauthentication methods like Kerberos, OAuth, or certificate login, the\nbrowser cannot forget credentials, and thus automatic logouts are not\nuseful for protecting credentials of forgotten sessions. Set to <strong>0</strong>\nto disable session timeout.\n<br></p>\n</dd>\n</dl>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-ini\" data-lang=\"ini\">[Session]\nIdleTimeout=15</code></pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"></dt>\n<dd>\n<p>When not specified, there is no idle timeout by default.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>WarnBeforeConnecting</strong></dt>\n<dd>\n<p>Whether to warn before connecting to remote hosts from the Shell.\nDefaults to true.\n<br></p>\n</dd>\n</dl>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-ini\" data-lang=\"ini\">[Session]\nWarnBeforeConnecting=false</code></pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_bugs_2\">Bugs</h3>\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_author_2\">Author</h3>\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_see_also_2\">See also</h3>\n<div class=\"paragraph\">\n<p><strong>cockpit-ws(8)</strong>, <strong>cockpit-tls(8)</strong></p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_ws8\">cockpit-ws(8)</h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"_name_3\">Name</h3>\n<div class=\"paragraph\">\n<p>cockpit-ws - Cockpit web service</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_synopsis\">Synopsis</h3>\n<div class=\"paragraph\">\n<p><strong>cockpit-ws</strong> [<strong>--help</strong>] [<strong>--port</strong> <em>PORT</em>] [<strong>--address</strong> <em>ADDRESS</em>] [<strong>--no-tls</strong>]\n\t\t\t [<strong>--for-tls-proxy</strong>] [<strong>--local-ssh</strong>] [<strong>--local-session</strong> <em>BRIDGE</em>]</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_description_3\">Description</h3>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-ws</strong> program is the web service component used for\ncommunication between the browser application and various configuration\ntools and services like <strong>cockpit-bridge(1)</strong>.</p>\n</div>\n<div class=\"paragraph\">\n<p>Users or administrators should never need to start this program as it\nautomatically started by <strong>systemd(1)</strong> on bootup, through\n<strong>cockpit-tls(8)</strong>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_transport_security\">Transport security</h3>\n<div class=\"paragraph\">\n<p><strong>cockpit-ws</strong> is normally run behind the <strong>cockpit-tls</strong> TLS\nterminating proxy, and only deals with unencrypted HTTP by itself. But\nfor backwards compatibility it can also handle TLS connections by itself\nwhen being run directly. For details how to configure certificates,\nplease refer to the <strong>cockpit-tls(8)</strong> documentation.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_timeout\">Timeout</h3>\n<div class=\"paragraph\">\n<p>When started via <strong>systemd(1)</strong> then <strong>cockpit-ws</strong> will exit after 90\nseconds if nobody logs in, or after the last user is disconnected.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_options\">Options</h3>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>--help</strong></dt>\n<dd>\n<p>Show help options.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--port</strong> <em>PORT</em></dt>\n<dd>\n<p>Serve HTTP requests <em>PORT</em> instead of port <strong>9090</strong>. Usually Cockpit is\nstarted on demand by <strong>systemd</strong> socket activation, and this option\nhas no effect. Update the <strong>ListenStream</strong> directive\n<strong>cockpit.socket</strong> file in the usual <strong>systemd</strong> manner.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--address</strong> <em>ADDRESS</em></dt>\n<dd>\n<p>Bind to address <em>ADDRESS</em> instead of binding to all available\naddresses. Usually Cockpit is started on demand by <strong>systemd</strong> socket\nactivation, and this option has no effect. In that case, update the\n<strong>ListenStream</strong> directive in the <strong>cockpit.socket</strong> file in the usual\n<strong>systemd</strong> manner.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--no-tls</strong></dt>\n<dd>\n<p>Disable http to https redirection.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--for-tls-proxy</strong></dt>\n<dd>\n<p>Tell <strong>cockpit-ws</strong> that it is running behind a local reverse proxy\nthat does the TLS termination. Then Cockpit puts https:// URLs into\nthe default <strong>Content-Security-Policy</strong>, and accepts only https://\norigins, instead of http: ones by default. However, if <strong>Origins</strong> is\nset in the <strong>cockpit.conf(5)</strong> configuration file, it will override\nthis default.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--local-ssh</strong></dt>\n<dd>\n<p>Normally <strong>cockpit-ws</strong> uses <strong>cockpit-session</strong> and PAM to\nauthenticate the user and start a user session. With this option\nenabled, it will instead authenticate via SSH at <strong>127.0.0.1</strong> port\n<strong>22</strong>.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--local-session</strong> <em>BRIDGE</em></dt>\n<dd>\n<p>Skip all authentication and <strong>cockpit-session</strong>, and launch the\n<strong>cockpit-bridge</strong> specified in <em>BRIDGE</em> in the local session. If the\n<em>BRIDGE</em> is specified as <code>-</code> then expect an already running bridge\nthat is connected to stdin and stdout of this <strong>cockpit-ws</strong> process.\nThis allows the web server to run as any unprivileged user in an\nalready running session.<br>\n<br>\nThis mode implies <strong>--no-tls</strong>, thus you need to use http:// URLs with\nthis.</p>\n</dd>\n</dl>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>With <strong>--local-session</strong> <em>BRIDGE</em>, you <em>have to isolate the opened TCP port</em> somehow\n(for example in a network namespace), otherwise all other users (or\neven remote machines if the port is not just listening on localhost)\ncan access the session!</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_environment\">Environment</h3>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-ws</strong> process will use the <strong>XDG_CONFIG_DIRS</strong> environment\nvariable from the\n<a href=\"https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html\">XDG\nbasedir spec</a> to find its <strong>cockpit.conf(5)</strong> configuration file.</p>\n</div>\n<div class=\"paragraph\">\n<p>In addition the <strong>XDG_DATA_DIRS</strong> environment variable from the\n<a href=\"https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html\">XDG\nbasedir spec</a> can be used to override the location to serve static files\nfrom. These are the files that are served to a non-logged in user.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_bugs_3\">Bugs</h3>\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_author_3\">Author</h3>\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_see_also_3\">See also</h3>\n<div class=\"paragraph\">\n<p><strong>cockpit-tls(8)</strong> , <strong>cockpit.conf(5)</strong> , <strong>systemd(1)</strong></p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_tls8\">cockpit-tls(8)</h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"_name_4\">Name</h3>\n<div class=\"paragraph\">\n<p>cockpit-tls - TLS proxy for Cockpit web service</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_synopsis_2\">Synopsis</h3>\n<div class=\"paragraph\">\n<p><strong>cockpit-tls</strong> [<strong>--help</strong>] [<strong>--port</strong> <em>PORT</em>] [<strong>--no-tls</strong>] [<strong>--idle-timeout</strong> <em>SECONDS</em>]</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_description_4\">Description</h3>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-tls</strong> program is a TLS terminating HTTP proxy for\n<strong>cockpit-ws(8)</strong>. It manages a set of isolated cockpit-ws instances,\none per TLS client certificate, plus one for TLS without a client\ncertificate, and one for unencrypted HTTP. With that, one session cannot\ntamper with another one through possible security vulnerability\nexploits.</p>\n</div>\n<div class=\"paragraph\">\n<p>Users or administrators should never need to start this program as it\nautomatically started by <strong>systemd(1)</strong> via socket activation.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_transport_security_2\">Transport security</h3>\n<div class=\"paragraph\">\n<p>To specify the TLS certificate the web service should use, simply drop a\nfile with the extension <strong>.cert</strong> in the <strong>/etc/cockpit/ws-certs.d</strong>\ndirectory, or below <strong>$XDG_CONFIG_DIRS</strong> if set (see\n<a href=\"./cockpit.conf.5.html\">cockpit.conf</a>). If there are multiple files\nin this directory, then the highest priority one is chosen after\nsorting.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <strong>.cert</strong> file should contain at least two OpenSSL style PEM blocks.\nFirst one or more <code>BEGIN CERTIFICATE</code> blocks for the server\ncertificate and intermediate certificate authorities and a second one\ncontaining a <code>BEGIN PRIVATE KEY</code> or similar. The key must not be\nencrypted.</p>\n</div>\n<div class=\"paragraph\">\n<p>If there is no TLS certificate, a self-signed certificate is\nautomatically generated using <strong>sscg</strong> (if available) or <strong>openssl</strong> and\nstored in the <strong>0-self-signed.cert</strong> file.</p>\n</div>\n<div class=\"paragraph\">\n<p>When enrolling into a FreeIPA domain, an SSL certificate is requested\nfrom the IPA server and stored in <strong>10-ipa.cert</strong>.</p>\n</div>\n<div class=\"paragraph\">\n<p>To check which certificate <strong>cockpit-ws</strong> will use, run the following\ncommand.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo /usr/libexec/cockpit-certificate-ensure --check</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Or, on Debian-based systems:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo /usr/lib/cockpit/cockpit-certificate-ensure --check</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If using <strong>certmonger</strong> to manage certificates, following command can be\nused to generate a certificate/key pair:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>CERT_FILE=/etc/cockpit/ws-certs.d/50-certmonger.crt\nKEY_FILE=/etc/cockpit/ws-certs.d/50-certmonger.key\n\ngetcert request -f ${CERT_FILE} -k ${KEY_FILE} -D $(hostname --fqdn)</pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_options_2\">Options</h3>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>--help</strong></dt>\n<dd>\n<p>Show help options.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--port</strong> <em>PORT</em></dt>\n<dd>\n<p>Serve HTTP requests on <em>PORT</em> instead of port 9090. Usually Cockpit is\nstarted on demand by <strong>systemd</strong> socket activation, and this option\nhas no effect. Update the <strong>ListenStream</strong> directive\n<strong>cockpit.socket</strong> file in the usual <strong>systemd</strong> manner.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--no-tls</strong></dt>\n<dd>\n<p>Don&#8217;t use TLS. Certificates will not be read, and https connections\ndenied. Then <strong>cockpit-tls</strong> will only manage a single cockpit-ws\ninstance, and thus not do anything different than running\n<strong>cockpit-ws --no-tls</strong> directly. Only use this for debugging or\ntesting.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--idle-timeout</strong> <em>SECONDS</em></dt>\n<dd>\n<p>If greater than 0, exit if no connections have happened for the given\nnumber of seconds, i. e. the server is idle. If not given, the default\nis 90.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_environment_2\">Environment</h3>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-tls</strong> program expects the <strong>RUNTIME_DIRECTORY</strong>\nenvironment variable to be set to an empty directory (preferably in\n<strong>/run/</strong>) that is only accessible by the system user under which it is\nrunning. This contains the Unix sockets for communicating with the\n<strong>cockpit-ws</strong> instances, and in the future, state information about\nclient certificates. This variable is normally set by the\n<strong>cockpit.service</strong> systemd unit.</p>\n</div>\n<div class=\"paragraph\">\n<p>In addition, <strong>cockpit-tls</strong> will use the <strong>XDG_CONFIG_DIRS</strong>\nenvironment variable from the\n<a href=\"https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html\">XDG\nbasedir spec</a> to find its certificates and the <strong>cockpit.conf(5)</strong>\nconfiguration file.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_bugs_4\">Bugs</h3>\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_author_4\">Author</h3>\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_see_also_4\">See also</h3>\n<div class=\"paragraph\">\n<p><strong>cockpit-ws(8)</strong> , <strong>cockpit.conf(5)</strong> , <strong>systemd(1)</strong></p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_desktop1\">cockpit-desktop(1)</h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"_name_5\">Name</h3>\n<div class=\"paragraph\">\n<p>cockpit-desktop - Cockpit Desktop integration</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_synopsis_3\">Synopsis</h3>\n<div class=\"paragraph\">\n<p><strong>cockpit-desktop</strong> <em>URLPATH</em> [<em>SSH_HOST</em>]</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_description_5\">Description</h3>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-desktop</strong> program provides secure access to Cockpit pages\nin an already running desktop session. It starts a web server\n(<strong>cockpit-ws</strong>) and a web browser in an isolated network namespace, and\na <strong>cockpit-bridge(8)</strong> in the running user session.</p>\n</div>\n<div class=\"paragraph\">\n<p>This avoids having to log into Cockpit, and having to enable\n<strong>cockpit.socket</strong> system-wide. The network isolation ensures that no\nother user, and not even other processes in the user&#8217;s session, can\naccess this local web server.</p>\n</div>\n<div class=\"paragraph\">\n<p><strong>URLPATH</strong> is the Cockpit page to open, i. e. the path component of\nCockpit URLs. It is highly recommended to only open a\n<a href=\"https://cockpit-project.org/guide/latest/embedding.html\">particular page frame</a>, not the entire Cockpit navigation and menu. For example, the\npath <code>/cockpit/@localhost/storage/index.html</code> will open the Storage\npage. It is also possible to give abbreviated forms of urls, such as\n&#8220;/storage&#8221; or &#8220;/network/firewall&#8221;.</p>\n</div>\n<div class=\"paragraph\">\n<p><em>SSH_HOST</em> is an optional SSH remote host specification (<em>hostname</em>\nor <em>username@hostname</em>). If given, <strong>cockpit-bridge</strong> will be started\non the remote host through <strong>ssh(1)</strong> instead, i. e. the Cockpit web\nbrowser will show that remote host. Note that this is more of an\nexperimental/demo feature.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_environment_3\">Environment</h3>\n<div class=\"paragraph\">\n<p>The <strong>BROWSER</strong> environment variable specifies the browser command (and\npossibly options) that will be used to open the requested Cockpit page.\nIf not set, <strong>cockpit-desktop</strong> attempts to use an internal minimalistic\nWebKit browser, and failing that, will attempt to detect some reasonable\nalternatives.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_bugs_5\">Bugs</h3>\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_author_5\">Author</h3>\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_see_also_5\">See also</h3>\n<div class=\"paragraph\">\n<p><strong>cockpit-ws(8)</strong>, <strong>cockpit-bridge(1)</strong></p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_cockpit_bridge1\">cockpit-bridge(1)</h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"_name_6\">Name</h3>\n<div class=\"paragraph\">\n<p>cockpit-bridge - Cockpit Host Bridge</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_synopsis_4\">Synopsis</h3>\n<div class=\"paragraph\">\n<p><strong>cockpit-bridge</strong> [<strong>--help</strong>] [<strong>--packages</strong>]</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_description_6\">Description</h3>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-bridge</strong> program is used by Cockpit to relay messages and\ncommands from the Web front end to the server. Among other things it\nrelays DBus, and spawns processes on behalf of the Web user interface.</p>\n</div>\n<div class=\"paragraph\">\n<p>This program is not routinely run by users or administrators. It is in\nthe <strong>$PATH</strong> so that Cockpit can find it when connecting between hosts.\nHowever there are some diagnostics available when running from the\ncommand line.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_options_3\">Options</h3>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>--help</strong></dt>\n<dd>\n<p>Show help options.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--interact</strong>=<em>boundary</em></dt>\n<dd>\n<p>Interact with the raw cockpit1 protocol. Useful for debugging and\ntesting. Specify a <em>boundary</em> which should be on an empty line\nbetween messages.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--packages</strong></dt>\n<dd>\n<p>List all available Cockpit packages and exit. Note this includes\npackages available to the user running this command.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--version</strong></dt>\n<dd>\n<p>Show Cockpit version information.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_bugs_6\">Bugs</h3>\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_author_6\">Author</h3>\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_see_also_6\">See also</h3>\n<div class=\"paragraph\">\n<p><strong>cockpit-ws(8)</strong></p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_pam_ssh_add8\">pam_ssh_add(8)</h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"_name_7\">Name</h3>\n<div class=\"paragraph\">\n<p>pam_ssh_add - PAM module to auto load ssh keys into an agent</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_description_7\">Description</h3>\n<div class=\"paragraph\">\n<p><strong>pam_ssh_add</strong> provides authentication and session modules that allow users\nto start their session with a running ssh-agent with as many ssh keys\nloaded as possible.</p>\n</div>\n<div class=\"paragraph\">\n<p>If used, the authentication module simply stores the authentication\ntoken for later use by the session module. Because this module performs\nno actual authentication it returns PAM_CRED_INSUFFICIENT on success and\nshould always be accompanied by an actual authentication module in your\npam configuration.</p>\n</div>\n<div class=\"paragraph\">\n<p>By default the session module will start a new ssh-agent and run\nssh-add, loading any keys that exist in the default path for the newly\nlogged in user. If any keys prompt for a password, and a authentication\ntoken was successfully stored, that token will be provided as the\npassword.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_options_4\">Options</h3>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>debug</strong></dt>\n<dd>\n<p>This option will turn on debug logging to syslog.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_examples\">Examples</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>        auth     required  pam_unix.so\n        auth     optional  pam_ssh_add.so\n        session  optional  pam_ssh_add.so</pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_bugs_7\">Bugs</h3>\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_author_7\">Author</h3>\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-metrics.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit.js: Metrics</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.js: Metrics</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#cockpit-metrics-function\">cockpit.metrics()</a></li>\n<li><a href=\"#cockpit-metrics-fetch\">metrics.fetch()</a></li>\n<li><a href=\"#cockpit-metrics-follow\">metrics.follow()</a></li>\n<li><a href=\"#cockpit-metrics-close\">metrics.close()</a></li>\n<li><a href=\"#cockpit-metrics-series\">metrics.series</a></li>\n<li><a href=\"#cockpit-metrics-meta\">metrics.meta</a></li>\n<li><a href=\"#cockpit-metrics-onchanged\">metrics.onchanged</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Metrics about the system can be retrieved from several sources using\n<a href=\"#cockpit-metrics\"><code>cockpit.metrics()</code></a> metrics channels. The\nmetrics are made available as series data, and can be used with the\n<a href=\"#cockpit-series\"><code>cockpit.series()</code></a> and\n<a href=\"#cockpit-grid\"><code>cockpit.grid()</code></a> facilities.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-metrics-function\">cockpit.metrics()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics = cockpit.metrics(interval, options, cache)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Opens a new metrics channel. The data retrieved will be available in the\n<a href=\"#cockpit-metrics-series\"><code>metrics.series</code></a> series sink, and can be\nused together with <a href=\"#cockpit-grid\"><code>cockpit.grid()</code></a> objects.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>interval</code> is in milliseconds, and is the granularity of the\nseries data retrieved. Any grids consuming the data must have the same\ninterval.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>cache</code> argument is a cache identifier. If specified, then this\nmetrics channel will share data with other metrics channels of the same\nidentifier. Make sure to use a globally unique string.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> argument is either a javascript plain object, or an\narray of those. Each object can have the following fields.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"metrics\"</code></dt>\n<dd>\n<p>An array of full metric descriptions, as javascript objects. The\nspecifics of these, and how to determine which ones to use, can\nunfortunately only be found in the low-level protocol documentation.\nThis option is required.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"source\"</code></dt>\n<dd>\n<p>The source to use for real-time data. This is used by the <code>follow</code>\nmethod, see below. Set to <code>\"internal\"</code> to retrieve internal metrics\nread by the bridge. If set to <code>\"direct\"</code> or <code>\"pmcd\"</code> then data\nwill be retrieved from <a href=\"https://pcp.io\">PCP</a>if it is available. The\ndefault is <code>\"internal\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"archive_source\"</code></dt>\n<dd>\n<p>The source to use for retrieving historical data. This is used by the\n<code>fetch</code> method, see below. Set to <code>\"pcp-archive\"</code> to retrieve data\nfrom PCP archives. The default is not to try to retrieve historical\ndata.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>When the <code>options</code> argument is an array of javascript objects, then\nthe metrics channel tries to use them in order until one succeeds. This\nway, you can prefer PCP as the source but fall back to internal metrics\nwhen PCP is not available, for example. The channel gives no indication\nwhich of the options has been used, and <code>fetch</code> and <code>follow</code> might\nuse different entries from the list.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-metrics-fetch\">metrics.fetch()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.fetch(beg, end)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Retrieve archived metrics data between <code>beg</code> and <code>end</code>. The\narguments can either be numbers, in which case they are interval based\noffsets, or they can be javascript Date objects.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-metrics-follow\">metrics.follow()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.follow()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Start retrieving live metrics data as it become available.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-metrics-close\">metrics.close()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Stop the retrieval of metrics and release resources.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-metrics-series\">metrics.series</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The series sink where data retrieved data will be processed.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-metrics-meta\">metrics.meta</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The metrics meta data last received.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-metrics-onchanged\">metrics.onchanged</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.onchanged = function() { }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when one of the properties on this metrics object\nchanges.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-series-data.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit.js: Series Data</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.js: Series Data</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#cockpit-grid\">cockpit.grid()</a></li>\n<li><a href=\"#cockpit-grid-add\">grid.add()</a></li>\n<li><a href=\"#cockpit-grid-remove\">grid.remove()</a></li>\n<li><a href=\"#cockpit-grid-sync\">grid.sync()</a></li>\n<li><a href=\"#cockpit-grid-move\">grid.move()</a></li>\n<li><a href=\"#cockpit-grid-walk\">grid.walk()</a></li>\n<li><a href=\"#cockpit-grid-notify\">grid.notify()</a></li>\n<li><a href=\"#cockpit-grid-onnotify\">grid.onnotify</a></li>\n<li><a href=\"#cockpit-grid-close\">grid.close()</a></li>\n<li><a href=\"#cockpit-grid-interval\">grid.interval</a></li>\n<li><a href=\"#cockpit-grid-beg\">grid.beg</a></li>\n<li><a href=\"#cockpit-grid-end\">grid.end</a></li>\n<li><a href=\"#cockpit-series\">cockpit.series()</a></li>\n<li><a href=\"#cockpit-series-input\">series.input()</a></li>\n<li><a href=\"#cockpit-series-load\">series.load()</a></li>\n<li><a href=\"#cockpit-series-interval\">series.interval</a></li>\n<li><a href=\"#cockpit-series-limit\">series.limit</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Series data consists of values along a continuous (usually time) axis.\nWe can place these in grids which expose a distinct subset of these\nvalues. These are the underlying mechanism for displaying metrics data\nin graphs.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-grid\">cockpit.grid()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid = cockpit.grid(interval, [beg, end])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Creates a grid object to contain series data.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>interval</code> is the granularity of the grid. Usually this is a\nnumber of milliseconds, when used with time series data. The <code>beg</code> and\n<code>end</code> are the bounds of the grid. If omitted they will be set to zero\nfor an initially empty grid.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>beg</code> and/or <code>end</code> are negative (including negative zero) then\nthey are interpreted in number of intervals relative to the current\ntime. Thus cockpit.grid(1000, -300, -0) will create a grid for the most\nrecent 5 minutes.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-grid-add\">grid.add()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>row = grid.add(series, path)\nrow = grid.add(callback, [early])\nrow = grid.add()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Adds a row to the grid. The returned <code>row</code> is a Javascript array that\nwill contain series data. The arguments control how the row is populated\nfrom the series data. The <code>row</code> is a sparse array. Its <code>row.length</code>\nwill not match the expected size of the grid, unless and until the row\nhas been completely filled in. The first index of the <code>row</code> will\ncontain the data from the series data at the\n<a href=\"#cockpit-grid-beg\"><code>grid.beg</code></a> offset.</p>\n</div>\n<div class=\"paragraph\">\n<p>When no arguments are passed, an empty row is added, and it is not\npopulated with data.</p>\n</div>\n<div class=\"paragraph\">\n<p>When called with a <code>series</code> and <code>path</code> argument then the row will be\npopulated directly with series data. The <code>series</code> can either be a\n<a href=\"#cockpit-series\">series object</a> or an object that has an\n<code>obj.series</code> property. The <a href=\"#cockpit-series-interval\">series\ninterval</a> must match the interval of this grid. If <code>path</code> is missing\nor empty, then the series data is placed into the row directly.\nOtherwise <code>path</code> indicates which part of the series data to place in\nthe row. When <code>path</code> is an array, it is used as a set of property\nnames or array indexes to follow into nested series data. When <code>path</code>\nis a dotted string, it is split and used the same way to locate the\ncorrect value in nested series data. The exact format of the series data\ndepends on its producer, and relevant paths will be documented there.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>callback</code> function is specified, then it will be invoked to\nprovide series data for the row. The function is invoked as\n<code>callback(row, index, count)</code>, where the <code>row</code> is the row to fill\nin, the <code>index</code> is the index to start filling in and <code>count</code> is the\nnumber of items to fill in. The <code>this</code> variable will be set to the\ngrid while invoking the <code>callback</code>. The callback is called after other\ndata rows for a given series have been filled in. Callbacks are called\nin the order added, unless the <code>early</code> argument is set to <code>true</code>, in\nwhich case the callback is called earlier than callbacks without the\n<code>early</code> argument set.</p>\n</div>\n<div class=\"paragraph\">\n<p>To remove the row use the <a href=\"#cockpit-grid-remove\"><code>grid.remove()</code>\nmethod.</a></p>\n</div>\n<div class=\"paragraph\">\n<p>The row will start being populated with data when the <code>series</code>\nproduces data. To make this happen right away, use the\n<a href=\"#cockpit-grid-sync\"><code>grid.sync()</code></a> method.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-grid-remove\">grid.remove()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.remove(row)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Remove a previously added <code>row</code> from the grid. The row will no longer\nbe updated with series data.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-grid-sync\">grid.sync()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.sync()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Load or reload data from the series into the rows. This does not clear\nthe rows before populating them. Some data may be populated immediately,\nothers may have to wait until data can be loaded. Internally this\nfunction calls <a href=\"#cockpit-series-load\"><code>series.load()</code></a> for each\nseries.</p>\n</div>\n<div class=\"paragraph\">\n<p>All rows with callbacks will be invoked to regenerate all the data. The\n<a href=\"#cockpit-grid-onnotify\"><code>grid.onnotify</code></a> event will be triggered.\nIt is not necessary to call this function after a call of the\n<a href=\"#cockpit-grid-move\"><code>grid.move()</code></a> method.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-grid-move\">grid.move()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.move(beg[, end])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Move the grid to new <code>beg</code> and <code>end</code> range. Data will be discarded\nfrom the rows and <a href=\"#cockpit-grid-sync\"><code>grid.sync()</code></a> will be\ncalled to load or reload series data for the new range of offsets.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>end</code> is not specified it will be set to <code>beg</code>. If <code>beg</code> and/or\n<code>end</code> are negative (including negative zero) then they will be set to\nthe number of intervals prior to the current time taken as an interval.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>beg</code> and/or <code>end</code> are negative (including negative zero) then\nthey are interpreted in number of intervals relative to the current\ntime. Thus cockpit.grid(1000, -300, -0) will create a grid for the most\nrecent 5 minutes.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-grid-walk\">grid.walk()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.walk()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Move the grid forward every\n<a href=\"#cockpit-grid-interval\"><code>grid.interval</code></a> milliseconds. To stop\nmoving forward, call <a href=\"#cockpit-grid-move\"><code>grid.move()</code></a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-grid-notify\">grid.notify()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.notify(index, count)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This function is called to have rows with callbacks recalculate their\ndata. It is not normally necessary to call this function, as it will be\ninvoked automatically when new series data is available or has been\nloaded. This function triggers the\n<a href=\"#cockpit-grid-onnotify\"><code>grid.onnotify</code></a> event.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-grid-onnotify\">grid.onnotify</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.addEventListener(\"notify\", function(index, count) { ... });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event that is triggered when some part of the series data in grid\nchanges. The <code>index</code> is the row index where things changed, and the\n<code>count</code> is the length of the data that changed.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-grid-close\">grid.close()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the grid, and stop updating the rows.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-grid-interval\">grid.interval</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The granularity of the grid. For time series data this is an interval in\nmilliseconds. In order to use a given <a href=\"#cockpit-grid\">grid</a> and\n<a href=\"#cockpit-series\">series</a> together, their interval properties must\nmatch.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-grid-beg\">grid.beg</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The beginning offset of the series data in the grid. Do not set this\nproperty directly. Use the <a href=\"#cockpit-grid-move\">grid.move()</a> method\ninstead.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-grid-end\">grid.end</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The ending offset of the series data in the grid. Do not set this\nproperty directly. Use the <a href=\"#cockpit-grid-move\">grid.move()</a> method\ninstead.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-series\">cockpit.series()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>series = cockpit.series(interval, [cache, fetch])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new sink of series data. This is usually done by producers of\nseries data, and it is rare to invoke this function directly.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>interval</code> is the granularity of the series data. For time series\ndata this is an interval in milliseconds. If a <code>cache</code> string is\nspecified, series data will be cached across frames for series with the\nsame <code>cache</code> cache identifier to load and/or reload.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>fetch</code> callback is specified, then it will be invoked when grids\nrequest certain ranges of data. The <code>fetch</code> callback is invoked with\n<code>function fetch(beg, end) { ... }</code> range offsets. The\n<a href=\"#cockpit-series-input\">series.input()</a> should be called with data\nretrieved, either immediately or at a later time. The callback may be\ncalled multiple times for the same ranges of data. It is up to the\ncallback to determine when or whether it should retrieve the data more\nthan once.</p>\n</div>\n<div class=\"paragraph\">\n<p>A producer of series data, usually calls this function and creates\nitself a <code>obj.series</code> property containing this series object.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-series-input\">series.input()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>series.input(beg, items[, mapping])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Send series data into the series sink. Any grids that have added rows\nbased on this series, will have data filled in. The <code>beg</code> is the\nbeginning offset of <code>items</code>. The <code>items</code> are an array one or more\nseries data items.</p>\n</div>\n<div class=\"paragraph\">\n<p>Producers may wish to provide additional properties that can be used in\nlookup paths that rows can pull from. This is done in the <code>mapping</code>\nargument. If specified it is a tree of objects. Each sub object should\nhave a property with the name <code>\"\"</code> empty string, which will be used as\nthe property name or index in place of the one used in the lookup path.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-series-load\">series.load()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>series.load(beg, end)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Load data from the series into any grids that have rows based on this\nseries data. Any cached data will be filled in immediately. Any data not\ncached, will be requested from the producer, if possible, and may arrive\nat a later time.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>beg</code> and <code>end</code> denote the range of data to load.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-series-interval\">series.interval</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The granularity of the series. For time series data this is an interval\nin milliseconds. In order to use a given <a href=\"#cockpit-grid\">grid</a> and\n<a href=\"#cockpit-series\">series</a> together, their interval properties must\nmatch.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-series-limit\">series.limit</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The maximum number of items to cache for loading and/or reloading. You\ncan change this value to a different number. Having a number close to\nzero will break certain usage of grids, such as\n<a href=\"#cockpit-grid-walk\"><code>grid.walk()</code></a>.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-spawn.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit.js: Spawning Processes</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.js: Spawning Processes</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#cockpit-spawn-spawn\">cockpit.spawn()</a></li>\n<li><a href=\"#cockpit-spawn-script\">cockpit.script()</a></li>\n<li><a href=\"#cockpit-spawn-then\">process.then()</a></li>\n<li><a href=\"#cockpit-spawn-catch\">process.catch()</a></li>\n<li><a href=\"#cockpit-spawn-stream\">process.stream()</a></li>\n<li><a href=\"#cockpit-spawn-input\">process.input()</a></li>\n<li><a href=\"#cockpit-spawn-close\">process.close()</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>This is the API for spawning a process and receiving its output, as well\nas exit codes.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-spawn-spawn\">cockpit.spawn()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process = cockpit.spawn(args, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Spawns a process on the system.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>args</code> should be an array starting with the executable and\ncontaining all the arguments to pass on the command line. If <code>args</code> is\na string then it is interpreted as an executable name. The optional\n<code>options</code> argument is a javascript plain object and can contain any of\nthe following fields:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"binary\"</code></dt>\n<dd>\n<p>If set to <code>true</code> then handle the input and output of the process as\narrays of binary bytes.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"directory\"</code></dt>\n<dd>\n<p>The directory to spawn the process in.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"err\"</code></dt>\n<dd>\n<p>Controls where the standard error is sent. By default it is logged to\nthe journal. If set to <code>\"out\"</code> it is included in with the output\ndata. If set to <code>\"ignore\"</code> then the error output is discarded. If\nset to <code>\"message\"</code>, then it will be returned as the error message.\nWhen the <code>\"pty\"</code> field is set, this field has no effect.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"environ\"</code></dt>\n<dd>\n<p>An optional array that contains strings to be used as additional\nenvironment variables for the new process. These are <code>\"NAME=VALUE\"</code>\nstrings.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"pty\"</code></dt>\n<dd>\n<p>Launch the process in its own PTY terminal, and send/receive terminal\ninput and output.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"batch\"</code></dt>\n<dd>\n<p>Batch data coming from the process in blocks of at least this size.\nThis is not a guarantee. After a short timeout the data will be sent\neven if the data doesn&#8217;t match the batch size. Defaults to zero.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"latency\"</code></dt>\n<dd>\n<p>The timeout for flushing any cached data in milliseconds.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to spawn the process as root instead of the\nlogged in user. If the currently logged in user is not permitted to\nbecome root (eg: via <code>pkexec</code>) then the <code>client</code> will immediately\nbe <a href=\"#cockpit-dbus-onclose\">closed</a> with a <code>\"access-denied\"</code>\nproblem code.\n+\nSet to <code>\"try\"</code> to try to run the process as root, but if that fails,\nfall back to an unprivileged process.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The spawned process is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">promise</a>\nthat will complete if the process exits successfully, or fail if there&#8217;s\na problem. Some additional methods besides the standard promise methods\nare documented below.</p>\n</div>\n<div class=\"paragraph\">\n<p>The standard output of the process is made available via the spawned\nprocess object. Any non-UTF8 output from the process will be coerced\ninto textual form. It is highly recommended that only textual output be\nproduced by the command. The standard error is logged to the journal.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-spawn-script\">cockpit.script()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process = cockpit.script(script, [args], [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Run a shell script on the system.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function <a href=\"#cockpit-spawn-spawn\">spawns</a> a Bourne shell script\nprocess. The full text of the <code>/bin/sh</code> shell script should be passed\nin as the first argument. The <code>args</code> can be an array of arguments, not\nincluding the executable, which are passed to the script as <code>$1</code>,\n<code>$2</code> and so on. Shebang options are not used or respected.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> is an optional javascript plain object and can include\nany of the fields listed for the\n<a href=\"#cockpit-spawn-spawn\"><code>cockpit.spawn()</code></a> function.</p>\n</div>\n<div class=\"paragraph\">\n<p>The spawned process is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">promise</a>\nthat will complete if the script exits successfully, or fail if there&#8217;s\na problem. Some additional methods besides the standard promise methods\nare documented below.</p>\n</div>\n<div class=\"paragraph\">\n<p>The standard output of the process is made available via the spawned\nprocess object. Any non-UTF8 output from the process will be coerced\ninto textual form. It is highly recommended that only textual output be\nproduced by the command. The standard error is logged to the journal by\ndefault.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-spawn-then\">process.then()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.then((data[, message]) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">promise</a>\nmethod. It sets up a handler to be called when the process finishes\nsuccessfully.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> argument contains the standard output of the process. If it\na string, unless the process was opened in binary mode, in which case\nthe <code>data</code> is an array of bytes. If a <code>process.stream()</code> handler is\nset up, then any standard output data consumed by the handler will not\nbe included in the <code>data</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>If the process was spawned with the <code>\"err\"</code> option set to\n<code>\"message\"</code> then the second argument will contain the standard error\noutput of the process.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-spawn-catch\">process.catch()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.catch((exception[, data]) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the process fails,\nterminates or exits.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>exception</code> object passed to the handler can have the following\nfields:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>message</code></dt>\n<dd>\n<p>A message describing the exception. If the process was spawned with\nthe <code>\"err\"</code> option set to <code>\"message\"</code> then the second argument\nwill contain the standard error output of the process.</p>\n</dd>\n<dt class=\"hdlist1\"><code>problem</code></dt>\n<dd>\n<p>A <a href=\"#cockpit-problems\">problem code</a> string when a problem occurred\nstarting or communicating with the process. This is <code>null</code> if the\nprocess exited or was terminated.</p>\n</dd>\n<dt class=\"hdlist1\"><code>exit_status</code></dt>\n<dd>\n<p>The numeric exit status of the process. This is <code>null</code> if the\nprocess did not exit.</p>\n</dd>\n<dt class=\"hdlist1\"><code>exit_signal</code></dt>\n<dd>\n<p>A string representing a unix signal that caused the process to\nterminate. This is <code>null</code> if the process did not terminate because\nof a signal.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>If the process actually ran and produced output before failing, it will\nbe available in the <code>data</code> argument. Otherwise this argument will be\n<code>undefined</code>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-spawn-stream\">process.stream()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.stream(data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This sets up a handler to be called when the process has standard\noutput. The handler will be called multiple times. The handler will be\ncalled regardless of whether the process ends up exiting successfully or\nnot.</p>\n</div>\n<div class=\"paragraph\">\n<p>Only one handler may be registered at a time. Registering an additional\nhandler replaces the previous one. The handler receives either string\n<code>data</code> or an array of binary bytes as its argument. A stream handler\nmay return a number, which indicates the number of characters or bytes\nconsumed from <code>data</code>. Any data not consumed will be included again the\nnext time the handler is called.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>process.stream()</code> handler is set up, then the <code>process.then()</code>\nhandlers will only get any remaining data not consumed by the stream\nhandler.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-spawn-input\">process.input()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.input(data, [stream])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This method writes <code>data</code> to the standard input of the process. If\n<code>data</code> is <code>null</code> or <code>undefined</code> it is not sent. The <code>data</code>\nshould be a string or an array of bytes if the process was opened in\nbinary mode.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>stream</code> is set to <code>true</code> then this function may be called again\nwith further input. Otherwise the standard input of the process is\nclosed.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-spawn-close\">process.close()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the process by closing its standard input and output. If\n<code>problem</code> is specified it should be a standard\n<a href=\"#cockpit-problems\">problem code</a> string. In this case the process\nwill be terminated with a signal.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-tls.8.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit-tls(8)</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit-tls(8)</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_name\">Name</a></li>\n<li><a href=\"#_synopsis\">Synopsis</a></li>\n<li><a href=\"#_description\">Description</a></li>\n<li><a href=\"#_transport_security\">Transport security</a></li>\n<li><a href=\"#_options\">Options</a></li>\n<li><a href=\"#_environment\">Environment</a></li>\n<li><a href=\"#_bugs\">Bugs</a></li>\n<li><a href=\"#_author\">Author</a></li>\n<li><a href=\"#_see_also\">See also</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"_name\">Name</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>cockpit-tls - TLS proxy for Cockpit web service</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_synopsis\">Synopsis</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><strong>cockpit-tls</strong> [<strong>--help</strong>] [<strong>--port</strong> <em>PORT</em>] [<strong>--no-tls</strong>] [<strong>--idle-timeout</strong> <em>SECONDS</em>]</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_description\">Description</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The <strong>cockpit-tls</strong> program is a TLS terminating HTTP proxy for\n<strong>cockpit-ws(8)</strong>. It manages a set of isolated cockpit-ws instances,\none per TLS client certificate, plus one for TLS without a client\ncertificate, and one for unencrypted HTTP. With that, one session cannot\ntamper with another one through possible security vulnerability\nexploits.</p>\n</div>\n<div class=\"paragraph\">\n<p>Users or administrators should never need to start this program as it\nautomatically started by <strong>systemd(1)</strong> via socket activation.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_transport_security\">Transport security</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>To specify the TLS certificate the web service should use, simply drop a\nfile with the extension <strong>.cert</strong> in the <strong>/etc/cockpit/ws-certs.d</strong>\ndirectory, or below <strong>$XDG_CONFIG_DIRS</strong> if set (see\n<a href=\"./cockpit.conf.5.html\">cockpit.conf</a>). If there are multiple files\nin this directory, then the highest priority one is chosen after\nsorting.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <strong>.cert</strong> file should contain at least two OpenSSL style PEM blocks.\nFirst one or more <code>BEGIN CERTIFICATE</code> blocks for the server\ncertificate and intermediate certificate authorities and a second one\ncontaining a <code>BEGIN PRIVATE KEY</code> or similar. The key must not be\nencrypted.</p>\n</div>\n<div class=\"paragraph\">\n<p>If there is no TLS certificate, a self-signed certificate is\nautomatically generated using <strong>sscg</strong> (if available) or <strong>openssl</strong> and\nstored in the <strong>0-self-signed.cert</strong> file.</p>\n</div>\n<div class=\"paragraph\">\n<p>When enrolling into a FreeIPA domain, an SSL certificate is requested\nfrom the IPA server and stored in <strong>10-ipa.cert</strong>.</p>\n</div>\n<div class=\"paragraph\">\n<p>To check which certificate <strong>cockpit-ws</strong> will use, run the following\ncommand.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo /usr/libexec/cockpit-certificate-ensure --check</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Or, on Debian-based systems:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo /usr/lib/cockpit/cockpit-certificate-ensure --check</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If using <strong>certmonger</strong> to manage certificates, following command can be\nused to generate a certificate/key pair:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>CERT_FILE=/etc/cockpit/ws-certs.d/50-certmonger.crt\nKEY_FILE=/etc/cockpit/ws-certs.d/50-certmonger.key\n\ngetcert request -f ${CERT_FILE} -k ${KEY_FILE} -D $(hostname --fqdn)</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_options\">Options</h2>\n<div class=\"sectionbody\">\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>--help</strong></dt>\n<dd>\n<p>Show help options.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--port</strong> <em>PORT</em></dt>\n<dd>\n<p>Serve HTTP requests on <em>PORT</em> instead of port 9090. Usually Cockpit is\nstarted on demand by <strong>systemd</strong> socket activation, and this option\nhas no effect. Update the <strong>ListenStream</strong> directive\n<strong>cockpit.socket</strong> file in the usual <strong>systemd</strong> manner.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--no-tls</strong></dt>\n<dd>\n<p>Don&#8217;t use TLS. Certificates will not be read, and https connections\ndenied. Then <strong>cockpit-tls</strong> will only manage a single cockpit-ws\ninstance, and thus not do anything different than running\n<strong>cockpit-ws --no-tls</strong> directly. Only use this for debugging or\ntesting.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--idle-timeout</strong> <em>SECONDS</em></dt>\n<dd>\n<p>If greater than 0, exit if no connections have happened for the given\nnumber of seconds, i. e. the server is idle. If not given, the default\nis 90.</p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_environment\">Environment</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The <strong>cockpit-tls</strong> program expects the <strong>RUNTIME_DIRECTORY</strong>\nenvironment variable to be set to an empty directory (preferably in\n<strong>/run/</strong>) that is only accessible by the system user under which it is\nrunning. This contains the Unix sockets for communicating with the\n<strong>cockpit-ws</strong> instances, and in the future, state information about\nclient certificates. This variable is normally set by the\n<strong>cockpit.service</strong> systemd unit.</p>\n</div>\n<div class=\"paragraph\">\n<p>In addition, <strong>cockpit-tls</strong> will use the <strong>XDG_CONFIG_DIRS</strong>\nenvironment variable from the\n<a href=\"https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html\">XDG\nbasedir spec</a> to find its certificates and the <strong>cockpit.conf(5)</strong>\nconfiguration file.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_bugs\">Bugs</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_author\">Author</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_see_also\">See also</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><strong>cockpit-ws(8)</strong> , <strong>cockpit.conf(5)</strong> , <strong>systemd(1)</strong></p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-util.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit.js: Utilities</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.js: Utilities</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#cockpit-format\">cockpit.format()</a></li>\n<li><a href=\"#cockpit-format-number\">cockpit.format_number()</a></li>\n<li><a href=\"#cockpit-format-bytes\">cockpit.format_bytes()</a></li>\n<li><a href=\"#cockpit-format-bytes-per-sec\">cockpit.format_bytes_per_sec()</a></li>\n<li><a href=\"#cockpit-format-bits-per-sec\">cockpit.format_bits_per_sec()</a></li>\n<li><a href=\"#cockpit-init\">cockpit.init()</a></li>\n<li><a href=\"#cockpit-info\">cockpit.info</a></li>\n<li><a href=\"#cockpit-event-target\">cockpit.event_target</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Various utility functions</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-format\">cockpit.format()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format(template, args)\nstring = cockpit.format(template, [arg, ...])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Format a string interpolating <code>args</code> into <code>template</code> using shell\nlike syntax. The <code>args</code> may be either an array or javascript object.\nThe <code>template</code> can contain fields that look like <code>$name</code> or\n<code>${name}</code> or <code>$0</code>. Numeric fields are used with array <code>args</code> and\nstart at zero.</p>\n</div>\n<div class=\"paragraph\">\n<p>In the second form, multiple <code>arg</code> arguments may be passed directly,\nand interpolated as as numeric fields in the <code>template</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>All falsy arguments except the numbers <code>0</code> and `0.0`are replaced by\nan empty string.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-format-number\">cockpit.format_number()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_number(number, [precision])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Formats <code>number</code> into a displayable <code>string</code>. If the number is not\nan integer, it is rounded to the given number of decimal places,\ndefaulting to 3. If the number is near zero, but not quite zero it is\nrounded to the smallest non-zero value of the given precision; i.e.\n±0.001 for default precision 3.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>number</code> is <code>null</code> or <code>undefined</code> an empty string will be\nreturned.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-format-bytes\">cockpit.format_bytes()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_bytes(number, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Formats <code>number</code> into a displayable <code>string</code> with a suffix, such as\n<em>kB</em> or <em>MB</em>.</p>\n</div>\n<div class=\"paragraph\">\n<p>By default, SI units are used. IEC units (1024-based) can be requested\nby including <code>base2: true</code> in <code>options</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>By default, non-integer numbers will be formatted with 3 digits of\nprecision. This can be changed with <code>options.precision</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>number</code> is <code>null</code> or <code>undefined</code> an empty string will be\nreturned.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-format-bytes-per-sec\">cockpit.format_bytes_per_sec()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_bytes_per_sec(number, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Format <code>number</code> of bytes into a displayable speed <code>string</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is mostly equivalent to <code>cockpit.format_bytes()</code> but the\nreturned value contains a unit like <em>kB/s</em> or <em>MB/s</em>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-format-bits-per-sec\">cockpit.format_bits_per_sec()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_bits_per_sec(number, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Format <code>number</code> of bits into a displayable speed <code>string</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is mostly equivalent to <code>cockpit.format_bytes()</code> but the\nreturned value contains a unit like <em>kbps</em> or <em>Mbps</em>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function does not support IEC units. <code>base2</code> may not be passed as\npart of <code>options</code>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-init\">cockpit.init()</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>await cockpit.init();\n\ncockpit.init().then(() =&gt; { ... });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Requests initialization of the Cockpit client library. This will ensure\nthat the transport is connected and we are ready to create channels. It\nalso populates the <code>cockpit.info</code> field.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function returns a promise. Initialization isn&#8217;t complete until the\npromise has resolved. You can either <code>await</code> it or call <code>.then()</code> on\nit.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-info\">cockpit.info</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.info.channels[payload]\n\ncockpit.info.os_release[field]\n\ncockpit.info.user\n\ncockpit.info.ws.version</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This object contains information about Cockpit itself. It is only\navailable after cockpit.init() has been called and awaited.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>channels</code></dt>\n<dd>\n<p>This is a mapping of channel payload types (keys, strings) supported\nby the bridge to capabilities advertised by those channels (values,\nlists of strings). Channels are listed even if they don&#8217;t advertise\nany capabilities, making this useful as a way to determine which\nchannel types are supported by the bridge.</p>\n</dd>\n<dt class=\"hdlist1\"><code>os_release</code></dt>\n<dd>\n<p>This is the data from the <code>/etc/os-release</code> or\n<code>/usr/lib/os-release</code> on the system that the bridge is running on.\nIt is a mapping from the key names to their values. See the\n<a href=\"https://www.freedesktop.org/software/systemd/man/latest/os-release.html\">os-release\nSpecification</a> for information about the available keys.</p>\n</dd>\n<dt class=\"hdlist1\"><code>user</code></dt>\n<dd>\n<p>Contains information about the user we&#8217;re logged in as.</p>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>uid</code></dt>\n<dd>\n<p>This is unix user id as an integer.</p>\n</dd>\n<dt class=\"hdlist1\"><code>gid</code></dt>\n<dd>\n<p>This is unix user group id as an integer.</p>\n</dd>\n<dt class=\"hdlist1\"><code>name</code></dt>\n<dd>\n<p>This is the unix user name like <code>\"root\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>fullname</code></dt>\n<dd>\n<p>This is a readable name for the user, from the GECOS field.</p>\n</dd>\n<dt class=\"hdlist1\"><code>group</code></dt>\n<dd>\n<p>This is the primary group name of the user.</p>\n</dd>\n<dt class=\"hdlist1\"><code>groups</code></dt>\n<dd>\n<p>This is an array of group names to which the user belongs. The first\nitem in this list is the primary group.</p>\n</dd>\n<dt class=\"hdlist1\"><code>home</code></dt>\n<dd>\n<p>This is user&#8217;s home directory.</p>\n</dd>\n<dt class=\"hdlist1\"><code>shell</code></dt>\n<dd>\n<p>This is unix user shell.</p>\n</dd>\n</dl>\n</div>\n</dd>\n<dt class=\"hdlist1\"><code>ws</code></dt>\n<dd>\n<p>Contains information about the webserver Cockpit is being served with.</p>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>version</code></dt>\n<dd>\n<p>The version of the webserver.</p>\n</dd>\n</dl>\n</div>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"cockpit-event-target\">cockpit.event_target</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.event_target(object, [handlers])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Adds an\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/EventTarget\">EventTarget</a>\nimplementation to the <code>object</code>. Optionally store the handlers in\n<code>handlers</code> if its specified.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit-ws.8.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit-ws(8)</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit-ws(8)</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_name\">Name</a></li>\n<li><a href=\"#_synopsis\">Synopsis</a></li>\n<li><a href=\"#_description\">Description</a></li>\n<li><a href=\"#_transport_security\">Transport security</a></li>\n<li><a href=\"#_timeout\">Timeout</a></li>\n<li><a href=\"#_options\">Options</a></li>\n<li><a href=\"#_environment\">Environment</a></li>\n<li><a href=\"#_bugs\">Bugs</a></li>\n<li><a href=\"#_author\">Author</a></li>\n<li><a href=\"#_see_also\">See also</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"_name\">Name</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>cockpit-ws - Cockpit web service</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_synopsis\">Synopsis</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><strong>cockpit-ws</strong> [<strong>--help</strong>] [<strong>--port</strong> <em>PORT</em>] [<strong>--address</strong> <em>ADDRESS</em>] [<strong>--no-tls</strong>]\n\t\t\t [<strong>--for-tls-proxy</strong>] [<strong>--local-ssh</strong>] [<strong>--local-session</strong> <em>BRIDGE</em>]</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_description\">Description</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The <strong>cockpit-ws</strong> program is the web service component used for\ncommunication between the browser application and various configuration\ntools and services like <strong>cockpit-bridge(1)</strong>.</p>\n</div>\n<div class=\"paragraph\">\n<p>Users or administrators should never need to start this program as it\nautomatically started by <strong>systemd(1)</strong> on bootup, through\n<strong>cockpit-tls(8)</strong>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_transport_security\">Transport security</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><strong>cockpit-ws</strong> is normally run behind the <strong>cockpit-tls</strong> TLS\nterminating proxy, and only deals with unencrypted HTTP by itself. But\nfor backwards compatibility it can also handle TLS connections by itself\nwhen being run directly. For details how to configure certificates,\nplease refer to the <strong>cockpit-tls(8)</strong> documentation.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_timeout\">Timeout</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>When started via <strong>systemd(1)</strong> then <strong>cockpit-ws</strong> will exit after 90\nseconds if nobody logs in, or after the last user is disconnected.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_options\">Options</h2>\n<div class=\"sectionbody\">\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>--help</strong></dt>\n<dd>\n<p>Show help options.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--port</strong> <em>PORT</em></dt>\n<dd>\n<p>Serve HTTP requests <em>PORT</em> instead of port <strong>9090</strong>. Usually Cockpit is\nstarted on demand by <strong>systemd</strong> socket activation, and this option\nhas no effect. Update the <strong>ListenStream</strong> directive\n<strong>cockpit.socket</strong> file in the usual <strong>systemd</strong> manner.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--address</strong> <em>ADDRESS</em></dt>\n<dd>\n<p>Bind to address <em>ADDRESS</em> instead of binding to all available\naddresses. Usually Cockpit is started on demand by <strong>systemd</strong> socket\nactivation, and this option has no effect. In that case, update the\n<strong>ListenStream</strong> directive in the <strong>cockpit.socket</strong> file in the usual\n<strong>systemd</strong> manner.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--no-tls</strong></dt>\n<dd>\n<p>Disable http to https redirection.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--for-tls-proxy</strong></dt>\n<dd>\n<p>Tell <strong>cockpit-ws</strong> that it is running behind a local reverse proxy\nthat does the TLS termination. Then Cockpit puts https:// URLs into\nthe default <strong>Content-Security-Policy</strong>, and accepts only https://\norigins, instead of http: ones by default. However, if <strong>Origins</strong> is\nset in the <strong>cockpit.conf(5)</strong> configuration file, it will override\nthis default.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--local-ssh</strong></dt>\n<dd>\n<p>Normally <strong>cockpit-ws</strong> uses <strong>cockpit-session</strong> and PAM to\nauthenticate the user and start a user session. With this option\nenabled, it will instead authenticate via SSH at <strong>127.0.0.1</strong> port\n<strong>22</strong>.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--local-session</strong> <em>BRIDGE</em></dt>\n<dd>\n<p>Skip all authentication and <strong>cockpit-session</strong>, and launch the\n<strong>cockpit-bridge</strong> specified in <em>BRIDGE</em> in the local session. If the\n<em>BRIDGE</em> is specified as <code>-</code> then expect an already running bridge\nthat is connected to stdin and stdout of this <strong>cockpit-ws</strong> process.\nThis allows the web server to run as any unprivileged user in an\nalready running session.<br>\n<br>\nThis mode implies <strong>--no-tls</strong>, thus you need to use http:// URLs with\nthis.</p>\n</dd>\n</dl>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>With <strong>--local-session</strong> <em>BRIDGE</em>, you <em>have to isolate the opened TCP port</em> somehow\n(for example in a network namespace), otherwise all other users (or\neven remote machines if the port is not just listening on localhost)\ncan access the session!</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_environment\">Environment</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The <strong>cockpit-ws</strong> process will use the <strong>XDG_CONFIG_DIRS</strong> environment\nvariable from the\n<a href=\"https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html\">XDG\nbasedir spec</a> to find its <strong>cockpit.conf(5)</strong> configuration file.</p>\n</div>\n<div class=\"paragraph\">\n<p>In addition the <strong>XDG_DATA_DIRS</strong> environment variable from the\n<a href=\"https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html\">XDG\nbasedir spec</a> can be used to override the location to serve static files\nfrom. These are the files that are served to a non-logged in user.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_bugs\">Bugs</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_author\">Author</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_see_also\">See also</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><strong>cockpit-tls(8)</strong> , <strong>cockpit.conf(5)</strong> , <strong>systemd(1)</strong></p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit.1.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit(1)</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit(1)</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_name\">Name</a></li>\n<li><a href=\"#_description\">Description</a></li>\n<li><a href=\"#_components\">Components</a></li>\n<li><a href=\"#_bugs\">Bugs</a></li>\n<li><a href=\"#_author\">Author</a></li>\n<li><a href=\"#_see_also\">See also</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"_name\">Name</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>cockpit - Cockpit</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_description\">Description</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit is a web accessible interactive admin interface for Linux\nmachines. Cockpit can usually be accessed on port <code>9090</code> of the\nmachine it&#8217;s installed on. Cockpit starts on demand. Use your system\ncredentials to log in.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_components\">Components</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The <strong>cockpit-ws</strong> web service listens on port <code>9090</code> and is started\non demand by <strong>systemd</strong>. The Cockpit web service authenticates the\nuser, loads Cockpit into the browser, and starts <strong>cockpit-bridge</strong> in a\nLinux user session.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-bridge</strong> provides Cockpit in the web browser with access\nto the system APIs. It does this over its standard in and standard out.\nThe bridge is started like a shell once per Linux user session.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_bugs\">Bugs</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_author\">Author</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_see_also\">See also</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><strong>cockpit-tls(8)</strong> , <strong>cockpit.bridge(1)</strong> , <strong>systemd(1)</strong>, <strong><a href=\"https://cockpit-project.org/guide/latest\">Cockpit guide</a></strong></p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/cockpit.conf.5.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>cockpit.conf(5)</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>cockpit.conf(5)</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_name\">Name</a></li>\n<li><a href=\"#_description\">Description</a></li>\n<li><a href=\"#_webservice\">WebService</a></li>\n<li><a href=\"#_log\">Log</a></li>\n<li><a href=\"#_oauth\">OAuth</a></li>\n<li><a href=\"#_session\">Session</a></li>\n<li><a href=\"#_bugs\">Bugs</a></li>\n<li><a href=\"#_author\">Author</a></li>\n<li><a href=\"#_see_also\">See also</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"_name\">Name</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>cockpit.conf - Cockpit configuration file</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_description\">Description</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit can be configured via /etc/cockpit/cockpit.conf. If\n<strong>$XDG_CONFIG_DIRS</strong> is set, then the first path containing a\n<strong>../cockpit/cockpit.conf</strong> is used instead. Other configuration files\nand directories are searched for in the same way.</p>\n</div>\n<div class=\"paragraph\">\n<p>This file is not required and may need to be created manually. The file\nhas a INI file syntax and thus contains key / value pairs, grouped into\ntopical groups. See the examples below for details.</p>\n</div>\n<div class=\"paragraph\">\n<p>Note: The port that cockpit listens on cannot be changed in this file.\nTo change the port change the systemd <strong>cockpit.socket</strong> file.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_webservice\">WebService</h2>\n<div class=\"sectionbody\">\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>Origins</strong></dt>\n<dd>\n<p>By default cockpit will not accept crossdomain websocket connections.\nUse this setting to allow access from alternate domains. Origins\nshould include scheme, host and port, if necessary. Wildcards and glob\nexpressions are permitted. IPv6 addresses must have their brackets escaped\nwith backslashes (e.g. <code>\\[::1\\]</code>) as they are matched using <code>fnmatch()</code>.\n<br></p>\n</dd>\n</dl>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-ini\" data-lang=\"ini\">[WebService]\nOrigins = https://somedomain1.com https://somedomain2.com:9090 https://*.somedomain3.com https://\\[::1\\]:9090</code></pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>ProtocolHeader</strong></dt>\n<dd>\n<p>Configure cockpit to look at the contents of this header to determine\nif a connection is using tls. This should only be used when cockpit is\nbehind a reverse proxy, and care should be taken to make sure that\nincoming requests cannot set this header.\n<br></p>\n</dd>\n</dl>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-ini\" data-lang=\"ini\">[WebService]\nProtocolHeader = X-Forwarded-Proto</code></pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>ForwardedForHeader</strong></dt>\n<dd>\n<p>Configure cockpit to look at the contents of this header to determine\nthe real origin of a connection. This should only be used when cockpit\nis behind a reverse proxy, and care should be taken to make sure that\nincoming requests cannot set this header.\n<br></p>\n</dd>\n</dl>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-ini\" data-lang=\"ini\">[WebService]\nForwardedForHeader = X-Forwarded-For</code></pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>LoginTitle</strong></dt>\n<dd>\n<p>Set the browser title for the login screen.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>LoginTo</strong></dt>\n<dd>\n<p>When set to <code>true</code> the <em>Connect to</em> option on the login screen is\nvisible and allows logging into another server. When set to <code>false</code>,\ndirect remote logins are disallowed. If this option is not specified\nthen it will be automatically detected based on whether the\n<strong>cockpit-bridge</strong> package is installed and the <strong>ssh</strong> program is\navailable.<br>\n<br>\nIf cockpit-ws is exposed to the public internet, and also has access\nto a private internal network, it is recommended to explicitly set\n<strong>LoginTo=false</strong>. This prevents unauthenticated remote attackers from\nscanning the internal network for existing machines and open ports.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>RequireHost</strong></dt>\n<dd>\n<p>When set to <code>true</code> cockpit will require users to use the <em>Connect\nto</em> option to specify the host to log into.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>AllowMultiHost</strong></dt>\n<dd>\n<p>When set to <code>true</code>, cockpit will allow users to connect to multiple\nhosts in one session. The default is OS specific.<br>\n<br>\nWhen connecting to multiple servers, JavaScript runs without\nisolation. All systems will be vulnerable to potential attacks from\nother connected hosts. Enable this option <em>only</em> when all hosts are\ntrusted.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>MaxStartups</strong></dt>\n<dd>\n<p>Same as the <strong>sshd</strong> configuration option by the same name. Specifies\nthe maximum number of concurrent login attempts allowed. Additional\nconnections will be dropped until authentication succeeds or the\nconnections are closed. Defaults to 10.<br>\n<br>\nAlternatively, random early drop can be enabled by specifying the\nthree colon separated values <strong>start:rate:full</strong> (e.g. \"10:30:60\").\nCockpit will start refusing authentication attempts with a probability\nof <strong>rate/100</strong> (30%) if there are currently <strong>start</strong> (10)\nunauthenticated connections. The probability increases linearly and\nall connection attempts are refused if the number of unauthenticated\nconnections reaches <strong>full</strong> (60).</p>\n</dd>\n<dt class=\"hdlist1\"><strong>AllowUnencrypted</strong></dt>\n<dd>\n<p>If true, cockpit will accept unencrypted HTTP connections. Otherwise,\nit redirects all HTTP connections to HTTPS. Exceptions are connections\nfrom localhost and for certain URLs (like <strong>/ping</strong>). Defaults to\nfalse.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>UrlRoot</strong></dt>\n<dd>\n<p>The root URL where you will be serving cockpit. When provided cockpit\nwill expect all requests to be prefixed with the given url. This is\nmostly useful when you are using cockpit behind a reverse proxy, such\nas nginx. <code>/cockpit/</code> and <code>/cockpit+</code> are reserved and should not\nbe used. For example <code>/cockpit-new/</code> is ok. <code>/cockpit/</code> and\n<code>/cockpit+new/</code> are not.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>ClientCertAuthentication</strong></dt>\n<dd>\n<p>If true, enable TLS client certificates for authenticating users.\nCommonly these are provided by a smart card, but it&#8217;s equally possible\nto import certificates directly into the web browser. Please see the\n<a href=\"https://cockpit-project.org/guide/latest/cert-authentication.html\">Certificate/smart\ncard authentication</a> section in the Cockpit guide for details.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>Shell</strong></dt>\n<dd>\n<p>The relative URL to top level component to display in Cockpit once\nlogged in. Defaults to <code>/shell/index.html</code></p>\n</dd>\n<dt class=\"hdlist1\"><strong>CustomLoginPage</strong></dt>\n<dd>\n<p>Load the login page from an alternative directory. The directory must\ncontain a <code>login.html</code> and optionally a <code>po.js</code> file for translations.\nWhen not set, the hardcoded <code>$prefix/share/cockpit/static</code> directory is used.</p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_log\">Log</h2>\n<div class=\"sectionbody\">\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>Fatal</strong></dt>\n<dd>\n<p>The kind of log messages in the bridge to treat as fatal. Separate\nmultiple values with spaces. Relevant values are: <strong>criticals</strong> and\n<strong>warnings</strong>.</p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_oauth\">OAuth</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit can be configured to support the\n<a href=\"https://tools.ietf.org/html/rfc6749#section-4.2\">implicit grant</a> OAuth\nauthorization flow. When successful the resulting oauth token will be\npassed to cockpit-ws using the <strong>Bearer</strong> auth-scheme. For a login to be\nsuccessful, cockpit will also need a to be configured to verify and\nallow <strong>Bearer</strong> tokens.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>URL</strong></dt>\n<dd>\n<p>This is the url that cockpit will redirect the users browser to when\nit needs to obtain an oauth token. Cockpit will add a redirect_uri\nparameter to the url with the location of where the oauth provider\nshould redirect to once a token has been obtained.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>ErrorParam</strong></dt>\n<dd>\n<p>When a oauth provider redirects a user back to cockpit, look for this\nparameter in the querystring or fragment portion of the url to find a\nerror message. When not provided it will default to\n<strong>error_description</strong></p>\n</dd>\n<dt class=\"hdlist1\"><strong>TokenParam</strong></dt>\n<dd>\n<p>When a oauth provider redirects a user back to cockpit, look for this\nparameter in the querystring or fragment portion of the url to find\nthe access token. When not provided it will default to\n<strong>access_token</strong></p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_session\">Session</h2>\n<div class=\"sectionbody\">\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>Banner</strong></dt>\n<dd>\n<p>The contents of the specified file (commonly <strong>/etc/issue</strong>) are shown\non the login page. By default, no banner is displayed.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>IdleTimeout</strong></dt>\n<dd>\n<p>Time in minutes after which session expires and user is logged out if\nno user action has been performed in the given time. This idle timeout\nonly applies to interactive password logins. With non-interactive\nauthentication methods like Kerberos, OAuth, or certificate login, the\nbrowser cannot forget credentials, and thus automatic logouts are not\nuseful for protecting credentials of forgotten sessions. Set to <strong>0</strong>\nto disable session timeout.\n<br></p>\n</dd>\n</dl>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-ini\" data-lang=\"ini\">[Session]\nIdleTimeout=15</code></pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"></dt>\n<dd>\n<p>When not specified, there is no idle timeout by default.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>WarnBeforeConnecting</strong></dt>\n<dd>\n<p>Whether to warn before connecting to remote hosts from the Shell.\nDefaults to true.\n<br></p>\n</dd>\n</dl>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-ini\" data-lang=\"ini\">[Session]\nWarnBeforeConnecting=false</code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_bugs\">Bugs</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_author\">Author</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_see_also\">See also</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><strong>cockpit-ws(8)</strong>, <strong>cockpit-tls(8)</strong></p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/development.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Developer Guide</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"development\" class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>Developer Guide</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#embedding\">Embedding and Integrating Cockpit</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#embedding-full\">Embedding the Cockpit Interface</a></li>\n<li><a href=\"#embedding-components\">Integrating Cockpit Components into Web Applications</a></li>\n<li><a href=\"#embedding-deep\">Deep Integration</a></li>\n<li><a href=\"#embedding-cors\">Pinging Cockpit</a></li>\n</ul>\n</li>\n<li><a href=\"#packages\">Cockpit Packages</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#package-layout\">Layout of Package Files</a></li>\n<li><a href=\"#_package_manifest\">Package Manifest</a></li>\n<li><a href=\"#package-manifest-override\">Manifest overrides</a></li>\n<li><a href=\"#package-links\">Package Links and Paths</a></li>\n<li><a href=\"#package-minified\">Content Negotiation</a></li>\n<li><a href=\"#package-api\">Using Cockpit API</a></li>\n<li><a href=\"#package-bridges\">Bridges for specific tasks</a></li>\n<li><a href=\"#package-replace\">Replacing an existing package</a></li>\n</ul>\n</li>\n<li><a href=\"#urls\">Cockpit URLs</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#urls-components\">Component URLs</a></li>\n<li><a href=\"#urls-visible\">Visible URLs</a></li>\n</ul>\n</li>\n<li><a href=\"#_api_base1\">API: base1</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_cockpit_js\">cockpit.js</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#api-cockpit-loading\">Loading cockpit.js</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_object_caching\">cockpit.js: Object Caching</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-cache-func\">cockpit.cache()</a></li>\n<li><a href=\"#cockpit-cache-close\">cache.close()</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_raw_channels\">cockpit.js: Raw Channels</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-channels-channel\">cockpit.channel()</a></li>\n<li><a href=\"#cockpit-channels-binary\">channel.binary</a></li>\n<li><a href=\"#cockpit-channels-options\">channel.options</a></li>\n<li><a href=\"#cockpit-channels-valid\">channel.valid</a></li>\n<li><a href=\"#cockpit-channels-send\">channel.send()</a></li>\n<li><a href=\"#cockpit-channels-control\">channel.control()</a></li>\n<li><a href=\"#cockpit-channels-wait\">channel.wait()</a></li>\n<li><a href=\"#cockpit-channels-close\">channel.close()</a></li>\n<li><a href=\"#cockpit-channels-message\">channel.onmessage</a></li>\n<li><a href=\"#cockpit-channels-oncontrol\">channel.oncontrol</a></li>\n<li><a href=\"#cockpit-channels-onready\">channel.onready</a></li>\n<li><a href=\"#cockpit-channels-close-ev\">channel.onclose</a></li>\n<li><a href=\"#cockpit-transport-origin\">cockpit.transport.origin</a></li>\n<li><a href=\"#cockpit-transport-host\">cockpit.transport.host</a></li>\n<li><a href=\"#cockpit-transport-csrf-token\">cockpit.transport.csrf_token</a></li>\n<li><a href=\"#cockpit-transport-options\">cockpit.transport.options</a></li>\n<li><a href=\"#cockpit-transport-wait\">cockpit.transport.wait()</a></li>\n<li><a href=\"#cockpit-transport-close\">cockpit.transport.close()</a></li>\n<li><a href=\"#cockpit-transport-filter\">cockpit.transport.filter()</a></li>\n<li><a href=\"#cockpit-transport-inject\">cockpit.transport.inject()</a></li>\n<li><a href=\"#cockpit-base64-encode\">cockpit.base64_encode()</a></li>\n<li><a href=\"#cockpit-base64-decode\">cockpit.base64_decode()</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_dbus_client\">cockpit.js: DBus Client</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-dbus-types\">DBus Types</a></li>\n<li><a href=\"#cockpit-dbus-dbus\">cockpit.dbus()</a></li>\n<li><a href=\"#cockpit-dbus-wait\">client.wait()</a></li>\n<li><a href=\"#cockpit-dbus-close\">client.close()</a></li>\n<li><a href=\"#cockpit-dbus-onclose\">client.onclose</a></li>\n<li><a href=\"#cockpit-dbus-onowned\">client.onowner</a></li>\n<li><a href=\"#cockpit-dbus-options\">client.options</a></li>\n<li><a href=\"#cockpit-dbus-unique-name\">client.unique_name</a></li>\n<li><a href=\"#cockpit-dbus-proxy\">client.proxy()</a></li>\n<li><a href=\"#cockpit-dbus-proxy-client\">proxy.client</a></li>\n<li><a href=\"#cockpit-dbus-proxy-path\">proxy.path</a></li>\n<li><a href=\"#cockpit-dbus-proxy-iface\">proxy.iface</a></li>\n<li><a href=\"#cockpit-dbus-proxy-valid\">proxy.valid</a></li>\n<li><a href=\"#cockpit-dbus-proxy-data\">proxy.data</a></li>\n<li><a href=\"#cockpit-dbus-proxy-call\">proxy.call()</a></li>\n<li><a href=\"#cockpit-dbus-proxy-wait\">proxy.wait()</a></li>\n<li><a href=\"#cockpit-dbus-proxy-onchanged\">proxy.onchanged</a></li>\n<li><a href=\"#cockpit-dbus-proxy-signal\">proxy.onsignal</a></li>\n<li><a href=\"#cockpit-dbus-proxies\">client.proxies()</a></li>\n<li><a href=\"#cockpit-dbus-proxies-wait\">proxies.wait()</a></li>\n<li><a href=\"#cockpit-dbus-proxies-client\">proxies.client</a></li>\n<li><a href=\"#cockpit-dbus-proxies-iface\">proxies.iface</a></li>\n<li><a href=\"#cockpit-dbus-proxies-path_namespace\">proxies.path_namespace</a></li>\n<li><a href=\"#cockpit-dbus-proxies-onadded\">proxies.onadded</a></li>\n<li><a href=\"#cockpit-dbus-proxies-onchanged\">proxies.onchanged</a></li>\n<li><a href=\"#cockpit-dbus-proxies-onremoved\">proxies.onremoved</a></li>\n<li><a href=\"#cockpit-dbus-call\">client.call()</a></li>\n<li><a href=\"#cockpit-dbus-then\">invocation.then()</a></li>\n<li><a href=\"#cockpit-dbus-catch\">invocation.catch()</a></li>\n<li><a href=\"#cockpit-dbus-subscribe\">client.subscribe()</a></li>\n<li><a href=\"#cockpit-dbus-remove\">subscription.remove()</a></li>\n<li><a href=\"#cockpit-dbus-watch\">client.watch()</a></li>\n<li><a href=\"#cockpit-dbus-watch-then\">watch.then()</a></li>\n<li><a href=\"#cockpit-dbus-watch-catch\">watch.catch()</a></li>\n<li><a href=\"#cockpit-dbus-watch-remove\">watch.remove()</a></li>\n<li><a href=\"#cockpit-dbus-onnotify\">client.onnotify</a></li>\n<li><a href=\"#cockpit-dbus-notify\">client.notify()</a></li>\n<li><a href=\"#cockpit-dbus-onmeta\">client.onmeta</a></li>\n<li><a href=\"#cockpit-dbus-variant\">cockpit.variant()</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_errors\">cockpit.js: Errors</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-problems\">Problem Codes</a></li>\n<li><a href=\"#cockpit-messages\">cockpit.message()</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_file_access\">cockpit.js: File Access</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-file-simple\">Simple reading and writing</a></li>\n<li><a href=\"#cockpit-file-format\">File format</a></li>\n<li><a href=\"#cockpit-file-binary\">Binary files</a></li>\n<li><a href=\"#cockpit-file-atomic\">Atomic modifications</a></li>\n<li><a href=\"#cockpit-file-notify\">Change notifications</a></li>\n<li><a href=\"#cockpit-file-path\">file.path</a></li>\n<li><a href=\"#cockpit-file-close\">Closing</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_http_client\">cockpit.js: HTTP Client</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-http-constructor\">cockpit.http()</a></li>\n<li><a href=\"#cockpit-http-get\">http.get()</a></li>\n<li><a href=\"#cockpit-http-post\">http.post()</a></li>\n<li><a href=\"#cockpit-http-request\">http.request()</a></li>\n<li><a href=\"#cockpit-http-then\">request.then()</a></li>\n<li><a href=\"#cockpit-http-catch\">request.catch()</a></li>\n<li><a href=\"#cockpit-http-response\">request.response()</a></li>\n<li><a href=\"#cockpit-http-stream\">request.stream()</a></li>\n<li><a href=\"#cockpit-http-input\">request.input()</a></li>\n<li><a href=\"#cockpit-http-close\">request.close()</a></li>\n<li><a href=\"#cockpit-http-close-all\">http.close()</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_localization\">cockpit.js: Localization</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-locale-language\">cockpit.language</a></li>\n<li><a href=\"#cockpit-locale-locale\">cockpit.locale()</a></li>\n<li><a href=\"#cockpit-locale-gettext\">cockpit.gettext()</a></li>\n<li><a href=\"#cockpit-locale-noop\">cockpit.noop()</a></li>\n<li><a href=\"#cockpit-locale-ngettext\">cockpit.ngettext()</a></li>\n<li><a href=\"#cockpit-locale-translate\">cockpit.translate()</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_page_location_and_jumping\">cockpit.js: Page Location and Jumping</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-location-general\">Page location</a></li>\n<li><a href=\"#cockpit-jump\">Jumping between components</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_user_session\">cockpit.js: User Session</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-logout\">cockpit.logout()</a></li>\n<li><a href=\"#cockpit-user\">cockpit.user()</a></li>\n<li><a href=\"#cockpit-permission\">Permission lookup</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_manifests\">cockpit.js: Manifests</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-manifest-loading\">Loading Manifests</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_metrics\">cockpit.js: Metrics</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-metrics-function\">cockpit.metrics()</a></li>\n<li><a href=\"#cockpit-metrics-fetch\">metrics.fetch()</a></li>\n<li><a href=\"#cockpit-metrics-follow\">metrics.follow()</a></li>\n<li><a href=\"#cockpit-metrics-close\">metrics.close()</a></li>\n<li><a href=\"#cockpit-metrics-series\">metrics.series</a></li>\n<li><a href=\"#cockpit-metrics-meta\">metrics.meta</a></li>\n<li><a href=\"#cockpit-metrics-onchanged\">metrics.onchanged</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_series_data\">cockpit.js: Series Data</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-grid\">cockpit.grid()</a></li>\n<li><a href=\"#cockpit-grid-add\">grid.add()</a></li>\n<li><a href=\"#cockpit-grid-remove\">grid.remove()</a></li>\n<li><a href=\"#cockpit-grid-sync\">grid.sync()</a></li>\n<li><a href=\"#cockpit-grid-move\">grid.move()</a></li>\n<li><a href=\"#cockpit-grid-walk\">grid.walk()</a></li>\n<li><a href=\"#cockpit-grid-notify\">grid.notify()</a></li>\n<li><a href=\"#cockpit-grid-onnotify\">grid.onnotify</a></li>\n<li><a href=\"#cockpit-grid-close\">grid.close()</a></li>\n<li><a href=\"#cockpit-grid-interval\">grid.interval</a></li>\n<li><a href=\"#cockpit-grid-beg\">grid.beg</a></li>\n<li><a href=\"#cockpit-grid-end\">grid.end</a></li>\n<li><a href=\"#cockpit-series\">cockpit.series()</a></li>\n<li><a href=\"#cockpit-series-input\">series.input()</a></li>\n<li><a href=\"#cockpit-series-load\">series.load()</a></li>\n<li><a href=\"#cockpit-series-interval\">series.interval</a></li>\n<li><a href=\"#cockpit-series-limit\">series.limit</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_spawning_processes\">cockpit.js: Spawning Processes</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-spawn-spawn\">cockpit.spawn()</a></li>\n<li><a href=\"#cockpit-spawn-script\">cockpit.script()</a></li>\n<li><a href=\"#cockpit-spawn-then\">process.then()</a></li>\n<li><a href=\"#cockpit-spawn-catch\">process.catch()</a></li>\n<li><a href=\"#cockpit-spawn-stream\">process.stream()</a></li>\n<li><a href=\"#cockpit-spawn-input\">process.input()</a></li>\n<li><a href=\"#cockpit-spawn-close\">process.close()</a></li>\n</ul>\n</li>\n<li><a href=\"#_cockpit_js_utilities\">cockpit.js: Utilities</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#cockpit-format\">cockpit.format()</a></li>\n<li><a href=\"#cockpit-format-number\">cockpit.format_number()</a></li>\n<li><a href=\"#cockpit-format-bytes\">cockpit.format_bytes()</a></li>\n<li><a href=\"#cockpit-format-bytes-per-sec\">cockpit.format_bytes_per_sec()</a></li>\n<li><a href=\"#cockpit-format-bits-per-sec\">cockpit.format_bits_per_sec()</a></li>\n<li><a href=\"#cockpit-init\">cockpit.init()</a></li>\n<li><a href=\"#cockpit-info\">cockpit.info</a></li>\n<li><a href=\"#cockpit-event-target\">cockpit.event_target</a></li>\n</ul>\n</li>\n</ul>\n</li>\n<li><a href=\"#_api_shell\">API: shell</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_index_html\">index.html</a></li>\n</ul>\n</li>\n<li><a href=\"#_api_system\">API: system</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#_logs_html\">logs.html</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#api-logs-html-description\">Description</a></li>\n</ul>\n</li>\n<li><a href=\"#_terminal_html\">terminal.html</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#api-terminal-html-description\">Description</a></li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"embedding\">Embedding and Integrating Cockpit</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit can be embedded in other web applications either as a whole or\nspecific Cockpit components can be integrated. Due to frame security\npolicy restrictions, this only works if Cockpit and the web application\nhave the <em>same origin</em>; this is commonly achieved by running both from a\ncommon reverse proxy.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"embedding-full\">Embedding the Cockpit Interface</h3>\n<div class=\"paragraph\">\n<p>Cockpit can be embedded into a larger web page as a frame. To embed the\nentire Cockpit Window use the URI: <code>https://server.example.com:9090/</code></p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-html\" data-lang=\"html\">&lt;html&gt;\n  &lt;head&gt;\n    &lt;title&gt;Embedded Cockpit&lt;/title&gt;\n  &lt;/head&gt;\n  &lt;body&gt;\n    This is Cockpit.\n    &lt;br/&gt;\n    &lt;iframe width=\"800px\" height=\"600px\"\n            src=\"https://server.example.com:9090/\"/&gt;\n  &lt;/body&gt;\n&lt;/html&gt;</code></pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"embedding-components\">Integrating Cockpit Components into Web Applications</h3>\n<div class=\"paragraph\">\n<p>Instead of embedding the entirety of Cockpit, you can integrate specific\ncomponents. Only those components explicitly documented as API should be\nintegrated. Other components can and will change regularly.</p>\n</div>\n<div class=\"paragraph\">\n<p>The component will load from the server in question and a WebSocket\nconnection will be established with the server to relay the component&#8217;s\nmessage stream.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit components are HTML files contained in <a href=\"#packages\">packages</a>.\nThese can be placed in an iframe or web browser window. Each documented\nand stable component has a well-known URL and these are documented in\nthe <a href=\"#development\">API reference</a>. Each component URL begins with the\nstring <code>/cockpit/@localhost/</code> followed a package name, and then the\ncomponent itself.</p>\n</div>\n<div class=\"paragraph\">\n<p>For example the <a href=\"#api-terminal-html\">terminal.html</a> in the\n<a href=\"#api-system\">system</a> package, has this URL:\n<code>/cockpit/@localhost/system/terminal.html</code></p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-html\" data-lang=\"html\">&lt;html&gt;\n  &lt;head&gt;\n    &lt;title&gt;Embedded Terminal&lt;/title&gt;\n  &lt;/head&gt;\n  &lt;body&gt;\n    This is a terminal.\n    &lt;br/&gt;\n    &lt;iframe width=\"800px\" height=\"600px\"\n      src=\"https://server.example.com:9090/cockpit/@localhost/system/terminal.html\"/&gt;\n  &lt;/body&gt;\n&lt;/html&gt;</code></pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"embedding-deep\">Deep Integration</h3>\n<div class=\"paragraph\">\n<p>Most often <a href=\"#embedding-components\">simple integration</a> will be used\nto bring Cockpit components into web applications. However it is also\npossible to do deep integration for embedders who wish to perform\nnon-standard authentication with the server, and relay the component&#8217;s\nmessage stream to the server themselves.</p>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>Deep integration capability is in heavy flux and is not yet documented.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"embedding-cors\">Pinging Cockpit</h3>\n<div class=\"paragraph\">\n<p>When embedding Cockpit or integrating Cockpit components, it may be\nnecessary to check whether Cockpit is available on a server before\nproceeding.</p>\n</div>\n<div class=\"paragraph\">\n<p>To do this perform a <code>/ping</code> request to Cockpit. This is a simple HTTP\nGET request. It returns the following:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>GET: https://server.example.com:9090/ping\n200 OK: { \"service\": \"cockpit\" }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <code>/ping</code> request allows\n<a href=\"https://en.wikipedia.org/wiki/Cross-origin_resource_sharing\">Cross Origin\nResource Sharing</a> headers and as such can be performed from Javascript\ncode with any origin. The request can also be made via plain HTTP\nwithout SSL. It is by design that no further information is present in\nthe response.</p>\n</div>\n<div class=\"paragraph\">\n<p>A complete example of using <code>/ping</code> is available in the Cockpit\nsources in the <code>/examples/ping-server/</code> directory.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"packages\">Cockpit Packages</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit is separated into various packages, each of which brings\nspecific features and/or code.</p>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>In addition, any APIs or behavior not explicitly documented here is an\ninternal API and can be changed at any time.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n<div class=\"sect2\">\n<h3 id=\"package-layout\">Layout of Package Files</h3>\n<div class=\"paragraph\">\n<p>A package consists of one or more files placed in a directory or its\nsubdirectories. It must have a <code>manifest.json</code> file and follow certain\nnaming conventions.</p>\n</div>\n<div class=\"paragraph\">\n<p>The name of a package is the name of the directory.</p>\n</div>\n<div class=\"paragraph\">\n<p>The name of the package must be ASCII alphanumeric, and may contain an\nunderscore. Names of directories and files in the package must consist\nof ASCII alphanumeric along with dash, underscore, dot, and comma. No\nspaces are allowed.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit uses the data directories from the\n<a href=\"https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html\">XDG\nBase Directory Specification</a> to locate packages. The <code>$XDG_DATA_DIRS</code>\nrepresents a colon separate list of system data directories, and\n<code>$XDG_DATA_HOME</code> is a user specific data directory. If the environment\nvariables are not set, defaults are used, according to the spec. If\ncockpit has been built with an alternate <code>--prefix=/path</code> then the\n<code>$prefix/share/cockpit</code> is used by default.</p>\n</div>\n<div class=\"paragraph\">\n<p>A <code>cockpit/</code> subdirectories in any of these data directories is the\nlocation where packages are loaded by Cockpit. If Cockpit finds a\npackage with the same name, in multiple data directories, then the first\none wins. According to the spec the first data directory is\n<code>$XDG_DATA_HOME</code> and then <code>$XDG_DATA_DIRS</code> in order.</p>\n</div>\n<div class=\"paragraph\">\n<p>This means that, by default the following directories are searched for\ncockpit packages, and in this order:</p>\n</div>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><code>~/.local/share/cockpit/</code></p>\n</li>\n<li>\n<p><code>/usr/local/share/cockpit/</code></p>\n</li>\n<li>\n<p><code>/usr/share/cockpit/</code></p>\n</li>\n</ul>\n</div>\n<div class=\"paragraph\">\n<p>Packages placed in <code>$XDG_DATA_HOME</code> are not cached by Cockpit or the\nweb browser. Other packages are cached aggressively, and are accessed\nusing a checksum of the files in the packages and their names.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can use the following command to list the packages installed on a\nserver. You&#8217;ll note that it&#8217;s output may change when you run the command\nas different users, if there are packages installed in the user&#8217;s home\ndirectory.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ cockpit-bridge --packages\n...</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>To further clarify things, here is an example package called\n\"my-package\" and its file layout:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>/usr/share/cockpit/\n    my-package/\n        manifest.json\n        file.html\n        some.js</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Place or symlink packages in your <code>~/.local/share/cockpit</code> directory\n(or appropriate <code>$XDG_DATA_HOME</code> location) that you would like to\nmodify and develop. System installed packages should not change while\nCockpit is running.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_package_manifest\">Package Manifest</h3>\n<div class=\"paragraph\">\n<p>Each package has a <code>manifest.json</code> file. It is a JSON object. The\nfollowing fields may be present in the manifest:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">content-security-policy</dt>\n<dd>\n<p>By default Cockpit serves packages using a strict\n<a href=\"https://en.wikipedia.org/wiki/Content_Security_Policy\">Content Security\nPolicy</a>, which among other things does not allow inline styles or\nscripts. This can be overridden on a per-package basis, with this\nsetting.\n+\nIf the overridden content security policy does not contain a\n<code>default-src</code>, <code>connect-src</code>, <code>base-uri</code>, <code>form-action</code>,\n<code>object-src</code>, or <code>block-all-mixed-content</code> then these will be\nadded to the policy from the manifest.</p>\n</dd>\n<dt class=\"hdlist1\">name</dt>\n<dd>\n<p>An optional string that changes the name of the package. Normally\npackages derive their name from the directory that they are located\nin. This field overrides that name.</p>\n</dd>\n<dt class=\"hdlist1\">priority</dt>\n<dd>\n<p>An optional number that specifies which package is preferred in cases\nwhere there are conflicts. For example given two packages with the\nsame <code>name</code> a package is chosen based on its priority.</p>\n</dd>\n<dt class=\"hdlist1\">conditions</dt>\n<dd>\n<p>An optional list of <code>{\"predicate\": \"value\"}</code> objects. Cockpit will\nonly consider the package if <em>all</em> conditions are met. This is\npreferable to using <code>priority</code>.<br>\n<br>\nCurrently supported predicates are <code>path-exists</code> and <code>path-not-exists</code>\n(since Cockpit 286) and <code>any</code> (since Cockpit 348). <code>any</code> accepts a\nlist of conditions and evaluates to true if <em>at least one</em> of the nested\nconditions is met. Unknown predicates are ignored.</p>\n</dd>\n<dt class=\"hdlist1\">requires</dt>\n<dd>\n<p>An optional JSON object that contains a <code>\"cockpit\"</code> string version\nnumber. The package will only be usable if the Cockpit bridge and\njavascript base are equal or newer than the given version number.</p>\n</dd>\n<dt class=\"hdlist1\">version</dt>\n<dd>\n<p>An informational version number for the package.</p>\n</dd>\n<dt class=\"hdlist1\">preload</dt>\n<dd>\n<p>A list of identifiers of the components that should be preloaded.\nNormally, the files of a component are loaded when the user navigates\nto it for the first time. The files of a preloaded component are\nloaded immediately after the user logs in, and the initialization code\nof the component is invoked.\n+\nThe value of this field is an array of strings, where each string is\none of the keys used in the <code>dashboard</code>, <code>menu</code>, or <code>tool</code>\nfields that are explained below.</p>\n</dd>\n<dt class=\"hdlist1\">parent</dt>\n<dd>\n<p>This option is used when module does not have its own menu item but is\na part of a different module. This is described by JSON object with\nproperties <code>component</code> which takes name of the superordinate\ncomponent and <code>docs</code> with list of documentation URLs for the given\npage. See below for structure of <code>docs</code> property.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>In addition, the following keys contain information about where\ncomponents of the package should appear in Cockpit&#8217;s user interface.\nEach of these keys is optional and contains an object mapping unique\nidentifiers to menu items, which are described below. (The naming of\nthese fields doesn&#8217;t perfectly match the current user interface for\nhistorical reasons.)</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">dashboard</dt>\n<dd>\n<p>Dashboard items appear in the menu under the section <em>Apps</em>.</p>\n</dd>\n<dt class=\"hdlist1\">menu</dt>\n<dd>\n<p>These items appear in the menu under the section <em>System</em>. This\nsection is roughly ordered into these categories (with their <em>order</em>\nin parentheses):\n+</p>\n<div class=\"ulist\">\n<ul>\n<li>\n<p>System Information (10)</p>\n</li>\n<li>\n<p>Logs (20)</p>\n</li>\n<li>\n<p>Configuring major subsystems (30-40)</p>\n</li>\n<li>\n<p>Things running on the machine (VMs, Containers - 50-60)</p>\n</li>\n<li>\n<p>Implementation Details (Accounts, Services - 70-100)</p>\n</li>\n</ul>\n</div>\n</dd>\n<dt class=\"hdlist1\">tools</dt>\n<dd>\n<p>These items appear in the menu under the section <em>Tools</em>.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Menu items and tools are registered using JSON objects that have the\nfollowing properties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">label</dt>\n<dd>\n<p>The label for the menu item or tool.</p>\n</dd>\n<dt class=\"hdlist1\">order</dt>\n<dd>\n<p>An optional order number to place this menu item or tool. Lower\nnumbers are listed first.</p>\n</dd>\n<dt class=\"hdlist1\">path</dt>\n<dd>\n<p>The relative path to the HTML file within the package that implements\nthe menu item or tool.</p>\n</dd>\n<dt class=\"hdlist1\">docs</dt>\n<dd>\n<p>List of documentation URLs for the given page. Each item is an object\ncontaining <code>label</code> and <code>url</code>.</p>\n</dd>\n<dt class=\"hdlist1\">keywords</dt>\n<dd>\n<p>Keywords that describe the page and which are used for searching.\nThese keywords should be lowercase. Keywords is a list containing\nkeyword items as described below. Page label is prepended as first\nkeyword in the first keyword item.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Keyword items are registered using JSON objects that have the following\nproperties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">matches</dt>\n<dd>\n<p>List of keywords to be matched.</p>\n</dd>\n<dt class=\"hdlist1\">goto</dt>\n<dd>\n<p>Optional path that is used for all keywords in this item. When this\nargument starts with slash, then it is used as pathname, otherwise it\nis used as hash. Defining <code>goto:\"page_hash\"</code> in page with\n<code>path:\"/page_path\"</code> would redirect to <code>/page_path#page_hash</code>,\nwhile <code>goto:\"/page_path\"</code> would redirect to <code>/page_path</code> ignoring\ndefault page path.</p>\n</dd>\n<dt class=\"hdlist1\">weight</dt>\n<dd>\n<p>How much keywords are prioritized over others. Default is 3.</p>\n</dd>\n<dt class=\"hdlist1\">translate</dt>\n<dd>\n<p><code>false</code> when keywords should not be localized. Default is <code>true</code>.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>An example manifest.json with some optional properties set:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"version\": 0,\n  \"require\": {\n      \"cockpit\": \"120\"\n  },\n  \"tools\": {\n     \"mytool\": {\n        \"label\": \"My Tool\",\n        \"path\": \"tool.html\"\n     }\n  }\n}</pre>\n</div>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"version\": 0,\n  \"require\": {\n    \"cockpit\": \"120\"\n  },\n  \"conditions\": [\n    {\"path-exists\": \"/usr/bin/mytool\"},\n    {\"path-exists\": \"/etc/mytool.conf\"},\n    {\"path-not-exist\": \"/etc/incompatible-tool\"}\n  ],\n  \"tools\": {\n     \"mytool\": {\n        \"label\": \"My Tool\",\n        \"path\": \"tool.html\"\n     }\n  }\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The following example shows how to use disjunctive conditions with <code>any</code>\nto specify alternative requirements (available since Cockpit 348). This\npackage will be available if either <code>/usr/bin/alt1</code> or <code>/usr/bin/alt2</code>\nexists. In any case, <code>/etc/incompatible-tool</code> must not exist.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>\"conditions\": [\n  {\"any\": [{\"path-exists\": \"/usr/bin/alt1\"}, {\"path-exists\": \"/usr/bin/alt2\"}]},\n  {\"path-not-exists\": \"/etc/incompatible-tool\"}\n]</pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"package-manifest-override\">Manifest overrides</h3>\n<div class=\"paragraph\">\n<p>To change a manifest system-wide, a file\n<code>&lt;package-directory-name&gt;.override.json</code> may be placed into\n<code>/etc/cockpit/</code>, or below <code>$XDG_CONFIG_DIRS</code> if set (see\n<a href=\"./cockpit.conf.5.html\">cockpit.conf</a>). To change it for a particular\nuser only, put the override into <code>~/.config/cockpit</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>These override the information in the manifest in the simple\n<a href=\"https://tools.ietf.org/html/rfc7386\">JSON Merge Patch</a> format.</p>\n</div>\n<div class=\"paragraph\">\n<p>This can be used to hide or modify menu items of an existing package.\nFor example <code>/etc/cockpit/systemd.override.json</code> or\n<code>~/.config/cockpit/systemd.override.json</code> could hide the <em>Logs</em> menu\nitem and move the <em>Services</em> menu item to the top of the menu.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"menu\": {\n    \"logs\": null,\n    \"services\": {\n      \"order\": -1\n    }\n  }\n}</pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"package-links\">Package Links and Paths</h3>\n<div class=\"paragraph\">\n<p>When referring to files in your package, such as in a hyperlink or a\n<code>&lt;style&gt;</code> tag or <code>&lt;script&gt;</code> tag, simply use a relative path, and\nrefer to the files in the same directory. When you need to refer to\nfiles in another package use a relative link.</p>\n</div>\n<div class=\"paragraph\">\n<p>For example here&#8217;s how to include the base <code>cockpit.js</code> script in your\nHTML from the <code>latest</code> package:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;script src=\"../base1/cockpit.js\"&gt;&lt;/script&gt;</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Do not assume you can link to any file in any other package. Refer to\nthe <a href=\"#development\">list of API packages</a> for those that are available\nfor use.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"package-minified\">Content Negotiation</h3>\n<div class=\"paragraph\">\n<p>In order to support gzipped and/or minified data, the files in a package\nare loaded using content negotiation logic. A HTTP request for the file\n<code>test.js</code> in the package named <code>mypackage</code> will return\n<code>mypackage/test.js</code> or <code>mypackage/test.js.gz</code> (in undefined\npreference). If neither exists, then it returns\n<code>mypackage/test.js.min</code> or <code>mypackage/test.js.min.gz</code> (again in\nundefined preference).</p>\n</div>\n<div class=\"paragraph\">\n<p>When packages are loaded from a system directory, Cockpit optimizes the\nfile system lookups above, by pre-listing the files. This is one of the\nreasons that you should never change packages installed to a system\ndirectory while Cockpit is running.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"package-api\">Using Cockpit API</h3>\n<div class=\"paragraph\">\n<p>Cockpit has API available for writing packages. There is no API\navailable for external callers to invoke via HTTP, REST or otherwise.</p>\n</div>\n<div class=\"paragraph\">\n<p>API from various packages can be used to implement Cockpit packages.\nEach package listed here has some API available for use. Only the API\nexplicitly documented should be used.</p>\n</div>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><a href=\"#development\">API Listing</a></p>\n</li>\n</ul>\n</div>\n<div class=\"paragraph\">\n<p>To include javascript from the API, simply load it into your HTML using\na script tag. Alternatively you can use an javascript loader.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"package-bridges\">Bridges for specific tasks</h3>\n<div class=\"paragraph\">\n<p>On the server side the <a href=\"#cockpit-bridge.1\"><code>cockpit-bridge</code></a>\nconnects to various system APIs that the front end UI requests it to.\nThere are additional bridges for specific tasks that the main\n<code>cockpit-bridge</code> cannot handle, such as using the PCP C library API.</p>\n</div>\n<div class=\"paragraph\">\n<p>These additional bridges can be registered in a <code>\"bridges\"</code> section of\na package&#8217;s <code>manifest.json</code> file. Building such a bridge is a complex\ntasks, and we will skip over that here. However it is useful to adjust\nhow these additional bridges are called, and so we&#8217;ll look at how they\nare registered.</p>\n</div>\n<div class=\"paragraph\">\n<p>An example <code>manifest.json</code> with a bridges section:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n    \"bridges\": [\n        {\n            \"match\": { \"payload\": \"metrics1\" },\n            \"spawn\": [ \"/usr/libexec/cockpit-pcp\" ]\n        }\n    ]\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The bridges are considered in the order they are listed in the array.\nUse the <code>manifest.json`</code>\"priority\"` field to control order between\npackages. The bridges are registered using JSON objects that have the\nfollowing properties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">environ</dt>\n<dd>\n<p>Optional, additional environment variables to pass to the bridge\ncommand.</p>\n</dd>\n<dt class=\"hdlist1\">match</dt>\n<dd>\n<p>The <code>\"match\"</code> object describes which channel open command options\nneed to match for a given channel to be handed over to this bridge.</p>\n</dd>\n<dt class=\"hdlist1\">privileged</dt>\n<dd>\n<p>If set to <code>true</code>, this marks the bridge as a superuser bridge.\nCockpit will start one of these explicitly when trying to escalate the\nprivileges of a session. A privileged bridge can not have a\n<code>\"match\"</code> property.</p>\n</dd>\n<dt class=\"hdlist1\">label</dt>\n<dd>\n<p>Setting this enables selection of privileged bridges in the UI. When\nno privileged bridge has a <code>label</code>, then Cockpit will start the\nbridge that runs <code>sudo</code>. This is the case in a default Cockpit\ninstallation. When at least one privileged bridge has a <code>label</code> then\nthe user can select one of them when escalating privileges. As a\nspecial case, if only one bridge has a <code>label</code>, then the step of\nselecting a bridge is omitted in the UI and that one bridge is always\nstarted.\n+\nThus, if you add a privileged bridge with a <code>label</code> in a new\nmanifest, Cockpit will use that bridge the next time a user opens the\n\"Administrative access\" dialog. If you want the user to choose between\nthe <code>sudo</code> method and your new one, you need to duplicate the\n<code>sudo</code> bridge definition in your manifest and give it a label.</p>\n</dd>\n<dt class=\"hdlist1\">problem</dt>\n<dd>\n<p>If a problem is specified, and this bridge fails to start up then\nchannels will be closed with this problem code. Otherwise later\nbridges or internal handlers for the channel will be invoked.</p>\n</dd>\n<dt class=\"hdlist1\">spawn</dt>\n<dd>\n<p>The command and arguments to invoke.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The <code>spawn</code> and <code>environ</code> values can be dynamically taken from a\nmatching open command values. When a value in either the <code>spawn</code> or\n<code>environ</code> array contains a named variable wrapped in <code>${}</code>, the\nvariable will be replaced with the value contained in the matching open\ncommand. Only named variables are supported and name can only contain\nletters, numbers and the following symbols: <code>._-</code></p>\n</div>\n<div class=\"paragraph\">\n<p>For example a bridges section like:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"bridges\": [\n    {\n      \"match\": { \"payload\": \"example\" },\n      \"environ\": [ \"TAG=${tag}\" ],\n      \"spawn: [ \"/example-bridge\", \"--tag\", \"${tag}\" ],\n      \"problem\": \"access-denied\"\n    }\n  ]\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>when a open command is received with a payload of <code>example</code> with\n<code>tag</code> value of <code>tag1</code>. The following command will be spawned</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>TAG=tag1 /example-bridge --tag tag1</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Processes that are reused so if another open command with a \"tag\" of\n<code>tag1</code> is received. The open command will be passed to existing\nprocess, rather than spawning a new one. However a open command with an\ntag of <code>tag2</code> will spawn a new command:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>TAG=tag2 /example-bridge --tag tag2</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If you need to include <code>${}</code>, as an actual value in your arguments you\ncan escape it by prefixing it with a <code>\\</code></p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"package-replace\">Replacing an existing package</h3>\n<div class=\"paragraph\">\n<p>If the functionality in a package replaces that of another package then\nit can replace that package by claiming the same <code>name</code> and a higher\n<code>priority</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>For example, a package in the <code>/usr/share/cockpit/disks</code> directory\ncould replace Cockpit&#8217;s <em>storage</em> package with a <code>manifest.json</code> like\nthis:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"version\": 0,\n  \"name\": \"storage\",\n  \"priority\": 10,\n  \"menu\": {\n     \"index\": {\n        \"label\": \"Disk Storage\",\n        \"order\": 15\n     }\n  }\n}</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"urls\">Cockpit URLs</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit URLs follow a specific structure, related to the components they\nare loading. Various components are loaded in <code>&lt;iframe&gt;</code> tags. The\nURLs for these components are described first. Further down below you\ncan find information about the top level bookmarkable Cockpit address\nURLs.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"urls-components\">Component URLs</h3>\n<div class=\"paragraph\">\n<p>Cockpit components are HTML documents. They are organized into\n<a href=\"#packages\">packages</a>. Each package contains information about which\nHTML components are available in that package. Components should always\nuse relative URLs to access resources, such as images, scripts or CSS\nfiles, even if they refer to a resource in another package.</p>\n</div>\n<div class=\"paragraph\">\n<p>The following are valid component URLs, each bit will be discussed\nbelow:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>/cockpit/@localhost/package/component.html#/hash\n/cockpit/$checksum/package/component.html#/hash\n/cockpit/@server.example.com/package/component.html#/hash\n/cockpit+embedder/@localhost/package/component.html#/hash</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>All resource URLs are under the <code>/cockpit</code> namespace. In cases where a\nCockpit component is being <a href=\"#embedding\">embedded</a> the <code>/cockpit</code>\nmay be followed by a plus sign and another <code>embedder</code> specific\nidentifier.</p>\n</div>\n<div class=\"paragraph\">\n<p>What follows is either a <code>@host</code> or <code>$checksum</code> which tells cockpit\nwhere to <a href=\"#packages\">find the package</a>. Checksums are used when more\nthan one host has identical packages and the resources can be cached.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>package</code> name is next, followed by the <code>component</code> HTML path\ninside that package. And lastly a hash allows for navigation within a\nsingle component. The hash should follow a URL path and/or query string\nform.</p>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>Never assume that the <code>@host</code> or <code>$checksum</code> portion is predictable.\nOnly refer to resources in packages on the same host.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"urls-visible\">Visible URLs</h3>\n<div class=\"paragraph\">\n<p>The above Component URLs are usually not visible to the user. Instead\nthe Cockpit Web Service wraps the components in a shell which allows\nnavigation, and provides bookmarkable clean URLs to the component. These\nURLs do not affect <a href=\"#embedding\">embedders</a> or\n<a href=\"#packages\">components</a> directly.</p>\n</div>\n<div class=\"paragraph\">\n<p>If no path is present then the Cockpit will redirect to the default page\nfor the server.</p>\n</div>\n<div class=\"paragraph\">\n<p>If the first segment of the path begins with an <code>@</code> sign, then the\ncomponent is being shown from a non-local host.</p>\n</div>\n<div class=\"paragraph\">\n<p>The next segment of the path, (or first if the component is being shown\non the local host) is the <a href=\"#packages\">package name</a>. The remainder of\nthe path is a component file in the package. If no further path segments\nare present, a default <code>index.html</code> component in the package is\nloaded. An extension of <code>.html</code> is automatically appended.</p>\n</div>\n<div class=\"paragraph\">\n<p>The hash portion of the path is automatically transferred to the\ncomponent as the hash of its <a href=\"#urls-components\">resource URL</a>.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_api_base1\">API: base1</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>This package contains basic support API available to other packages.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_cockpit_js\">cockpit.js</h3>\n<div class=\"paragraph\">\n<p>Basic cockpit API to interact with the system</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"api-cockpit-loading\">Loading cockpit.js</h4>\n<div class=\"paragraph\">\n<p><code>cockpit.js</code> should be loaded via a script tag.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;script src=\"../base1/cockpit.js\"&gt;</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_cockpit_js_object_caching\">cockpit.js: Object Caching</h3>\n<div class=\"paragraph\">\n<p>If the same information is displayed by multiple components in Cockpit,\n<code>cockpit.cache()</code> provides a way to share data between them. The\nshared data should be simple objects, arrays, and values, and not\ncontain functions or other objects.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-cache-func\">cockpit.cache()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cache = cockpit.cache(key, provider, consumer)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new cache object. The <code>key</code> should be a globally unique\nstring that describes the data being cached. This string must describe\nthe data, across all machines and all versions of cockpit. It is\ncustomary to include a version number in the <code>key</code> string.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>function provider(result, key) {\n    result(\"myvalue\");\n\n    return {\n        close: function() {\n            /* closed */\n        }\n    };\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <code>provider</code> is a function that will be invoked to start retrieving\ndata for the cache. It will be passed a <code>result</code> function as its first\nargument. The <code>result</code> should be invoked whenever new data is\navailable. The <code>key</code> argument matches the key string the cache was\ncreated with.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>provider</code> can return an object with a <code>close</code> method. This\nmethod will be invoked when the cache no longer needs data from the\nprovider.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>function consumer(value, key) {\n    /* ... */\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <code>consumer</code> is a function that will be passed new values when they\nare available, whether they come from the <code>provider</code> or a source in a\ndifferent component/frame.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-cache-close\">cache.close()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cache.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close a cache and stop calling its <code>consumer</code>. If the <code>provider</code> was\ninvoked, then the <code>close()</code> method it returned will be invoked.</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_cockpit_js_raw_channels\">cockpit.js: Raw Channels</h3>\n<div class=\"paragraph\">\n<p>At a low level Cockpit communicates with the system via messages passed\nthrough various channels. These are usually exposed via higher level\nAPIs, such as the <code>cockpit.spawn()</code> function. It is rare to use raw\nchannels directly.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-channels-channel\">cockpit.channel()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel = cockpit.channel(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This function creates a new channel for communication with the system.\nIt returns a new channel object. The <code>options</code> argument is a plain\nobject. At least the <code>\"payload\"</code> option is required, and based on the\npayload type, other options may be required.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"binary\"</code></dt>\n<dd>\n<p>Set to <code>true</code> to transfer binary payloads. Both messages sent via\n<a href=\"#cockpit-channels-send\"><code>channel.send()</code></a> and those received via\n<a href=\"#cockpit-channels-message\"><code>channel.onmessage</code></a> should be arrays\nof bytes, either <code>Uint8Array</code> or <code>Array</code> depending on browser\nsupport.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"payload\"</code></dt>\n<dd>\n<p>The payload type for the channel. Only specific payload types are\nsupported.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to open this channel as root. If the currently\nlogged in user is not permitted to become root (eg: via <code>pkexec</code>)\nthen the <code>channel</code> will immediately be\n<a href=\"#cockpit-channels-close-ev\">closed</a> with a <code>\"access-denied\"</code>\nproblem code.\n+\nSet to <code>\"try\"</code> to try to open the channel as root, but if that\nfails, then fall back to an unprivileged channel.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The channel object returned has the following fields and methods and\nevents. You should call the <code>channel.close()</code> method when done with\nthe channel.</p>\n</div>\n<div class=\"paragraph\">\n<p>A valid channel will always be returned and the is ready to\n<code>channel.send()</code>. The channel may\n<a href=\"#cockpit-channels-close-ev\">close shortly afterword</a> due to a\nfailure.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-channels-binary\">channel.binary</h4>\n<div class=\"paragraph\">\n<p>Will be <code>true</code> for an binary channel. Will be set to <code>false</code> if the\nchannel is textual.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-channels-options\">channel.options</h4>\n<div class=\"paragraph\">\n<p>The options used to open this channel. This should not be changed.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-channels-valid\">channel.valid</h4>\n<div class=\"paragraph\">\n<p>Will be <code>true</code> for an open channel. Will be set to <code>false</code> if the\nchannel closes.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-channels-send\">channel.send()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.send(data)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Send a message over the channel. The contents of the message depends on\nthe payload type of the channel. If a binary channel, then <code>data</code> is\nexpected to be an <code>Array</code> of bytes or a <code>Uint8Array</code>. If not binary,\nthen the <code>data</code> will be converted to a string if not already a string.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-channels-control\">channel.control()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.control(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Notify the channel to tune certain parameters on the fly. The\n<code>options</code> is a plain javascript object, and the contents depend on the\n<code>\"payload\"</code> of the channel.</p>\n</div>\n<div class=\"paragraph\">\n<p>One common operation is to set <code>\"command\"</code> to <code>\"done\"</code> in the\noptions field. To indicate that no further messages will be sent through\nthe channel.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-channels-wait\">channel.wait()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = channel.wait([callback])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Returns a <code>promise</code> that is ready when the channel is ready, or fails\nif the client closes. If a <code>callback</code> is specified, it is attached to\nthe promise. The promise will be rejected or resolved with the contents\n<code>options</code> passed to the\n<a href=\"#cockpit-channels-onready\">channel.onready</a> and\n<a href=\"#cockpit-channels-close-ev\">channel.onclose</a> events respectively.</p>\n</div>\n<div class=\"paragraph\">\n<p>In general it&#8217;s not necessary to wait for the channel before starting to\nuse the channel.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-channels-close\">channel.close()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.close([options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the channel.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>options</code> is present it can be a plain javascript object containing\nadditional channel close options to send to the peer. If closing for\nbecause of a problem, set the <code>\"problem\"</code> field to a\n<a href=\"#cockpit-problems\">problem code</a>. If <code>options</code> is not an object it\nwill be treated as a <code>\"problem\"</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-channels-close-ev\">close event</a> will fire. A channel\ncan also be closed by a peer or if the underlying transport closes.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-channels-message\">channel.onmessage</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"message\", function(event, data) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the channel receives a message. The message is\npassed as a string to the handler in the <code>data</code>. In the case of binary\nchannels <code>data</code> is an <code>Uint8Array</code> or an <code>Array</code> of bytes if the\nformer is not supported by the browser. The contents of the message\ndepends on the payload type of the channel.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-channels-oncontrol\">channel.oncontrol</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"control\", function(event, options) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the channel receives an control message in the\nmiddle of the flow. One particular use is when the <code>command</code> is set to\n<code>\"done\"</code> then no further messages will be received in the channel. The\nexact form of these messages depend on the <code>\"payload\"</code> of the channel.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-channels-onready\">channel.onready</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"ready\", function(event, options) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the other end of the channel is ready to start\nprocessing messages. This indicates the channel is completely open. It\nis possible to start sending messages on the channel before this point.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-channels-close-ev\">channel.onclose</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"close\", function(event, options) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the channel closes. This can happen either\nbecause <a href=\"#cockpit-channels-close\">channel.close()</a> function was\ncalled, or if the peer closed the channel, or the underlying transport\ncloses.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> will contain various close information, including a\n<code>\"problem\"</code> field which will be set if the channel was closed because\nof a problem.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-transport-origin\">cockpit.transport.origin</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.origin</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The HTTP origin that is being used by the underlying channel transport.\nThis is read-only, you should not assign a value. If the browser\nsupports <code>window.location.origin</code> then this will be identical to that\nvalue.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-transport-host\">cockpit.transport.host</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.host</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The host that this transport is going to talk to by default. This is\nread-only, you should not assign a value. If the value is null that\nmeans that the transport has not been setup yet.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-transport-csrf-token\">cockpit.transport.csrf_token</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.csrf_token</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>A cross site request forgery token for use with external channels. This\nbecomes valid once the connection is properly established.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-transport-options\">cockpit.transport.options</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.options</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Initialization options received over the underlying channel transport.\nThese will be empty until connection is properly established.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-transport-wait\">cockpit.transport.wait()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.wait(callback)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Call the <code>callback</code> function once the underlying channel transport is\ninitialized. This will start the initialization if not already in\nprogress or completed. If the channel transport is already initialized,\nthen <code>callback</code> will be called immediately.</p>\n</div>\n<div class=\"paragraph\">\n<p>In general it&#8217;s not necessary to wait for the transport before starting\nto open channels.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-transport-close\">cockpit.transport.close()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the underlying channel transport. All channels open channels will\nclose. The <code>problem</code> argument should be a problem code string. If not\nspecified it will default to <code>\"disconnected\"</code>.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-transport-filter\">cockpit.transport.filter()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.filter((message, channelid, control) =&gt;  { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Add a filter to the underlying channel transport. All incoming messages\nwill be passed to each of the filter callbacks that are registered.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is rarely used.</p>\n</div>\n<div class=\"paragraph\">\n<p>Filter callbacks are called in the order they are registered. If a\nfilter callback returns <code>false</code> then the message will not be\ndispatched further, whether to other filters, or to channels, etc.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>message</code> is the string or array with the raw message including,\nthe framing. The <code>channelid</code> is the channel identifier or an empty\nstring for control messages. If <code>control</code> is set then this is a\ncontrol message,d and the <code>control</code> argument contains the parsed JSON\nobject of the control message.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-transport-inject\">cockpit.transport.inject()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.inject(message, [out])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Inject a message into the underlying channel transport. The <code>message</code>\nshould be a <code>string</code> or an array of bytes, and should be valid\naccording to the Cockpit message protocol. If the <code>out</code> argument is\nequal to <code>false</code> then the message will be injected as an incoming\nmessage as if it was received on the underlying channel transport.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is rarely used. In general you should only <code>inject()</code>\nmessages you got from a <code>filter()</code>.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-base64-encode\">cockpit.base64_encode()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.base64_encode(data)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Encode binary data into a string using the Base64 encoding. The <code>data</code>\nargument can either be a <code>string</code>, an <code>Array</code>, an <code>ArrayBuffer</code> or\na <code>Uint8Array</code>. The return value is a string.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-base64-decode\">cockpit.base64_decode()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>data = cockpit.base64_decode(string, [constructor])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Decode binary data from a Base64 encoded string. The <code>string</code> argument\nshould be a javascript string. The returned <code>data</code>&gt; will be an array\nof bytes.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can pass <code>Uint8Array</code>, <code>Array</code> or <code>String</code> as an alternate\n<code>constructor</code> if you want the decoded data in an alternate form. The\ndefault is to return an <code>Array</code>. Note that if you use a <code>String</code> for\nthe decoded data, then you must guarantee that the data does not contain\nbytes that would be invalid for a string.</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_cockpit_js_dbus_client\">cockpit.js: DBus Client</h3>\n<div class=\"paragraph\">\n<p>Cockpit allows access to DBus services via this API.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-types\">DBus Types</h4>\n<div class=\"paragraph\">\n<p>DBus values are represented as javascript values and objects as follows:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>BYTE 'y'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>BOOLEAN 'b'</code></dt>\n<dd>\n<p>Javascript boolean.</p>\n</dd>\n<dt class=\"hdlist1\"><code>INT16 'n'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>UINT16 'q'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>INT32 'i'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>UINT32 'u'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>INT64 'x'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>UINT64 't'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>DOUBLE 'd'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>STRING 's'</code></dt>\n<dd>\n<p>Javascript string.</p>\n</dd>\n<dt class=\"hdlist1\"><code>OBJECT_PATH 'o'</code></dt>\n<dd>\n<p>Javascript string.</p>\n</dd>\n<dt class=\"hdlist1\"><code>SIGNATURE 'g'</code></dt>\n<dd>\n<p>Javascript string.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of BYTE 'ay'</code></dt>\n<dd>\n<p>A string containing base64 encoded data.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of DICT_ENTRY with STRING keys 'a{s?}'</code></dt>\n<dd>\n<p>A javascript plain object with the keys as property names.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of DICT_ENTRY with other keys 'a{??}'</code></dt>\n<dd>\n<p>A javascript plain object each key JSON encoded into a string property\nname.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of other</code></dt>\n<dd>\n<p>A javascript array.</p>\n</dd>\n<dt class=\"hdlist1\"><code>VARIANT</code></dt>\n<dd>\n<p>A javascript plain object with the <code>\"t\"</code> property set to a DBus type\nstring, and the <code>\"v\"</code> property set to a value.</p>\n</dd>\n<dt class=\"hdlist1\"><code>HANDLE 'h'</code></dt>\n<dd>\n<p>A javascript object that describes a cockpit channel which represents\nthe passed file descriptor. The <code>payload</code> is always set to\n<code>stream</code>. Pass it to\n<a href=\"#cockpit-channels-channel\">cockpit.channel()</a> to create the\nchannel and start reading or writing on it. Handles can only be\nreceived, not sent from within cockpit.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-dbus\">cockpit.dbus()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client = cockpit.dbus(name, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a DBus client for the given bus <code>name</code> (eg: service name). Use\nthe following functions to make DBus method calls, watch for events,\netc. The optional <code>options</code> argument is a javascript plain object, and\nmay include:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"bus\"</code></dt>\n<dd>\n<p>The DBus bus to connect to. Specifying <code>\"session\"</code> will connect to\nthe DBus user session bus, <code>\"user\"</code> will connect to the user bus (on\nsome systems this is identical to the session bus), <code>\"system\"</code> will\nconnect to the DBus system bus, and <code>\"none\"</code> to the non-standard bus\nspecified with the <code>address</code> option. This defaults to \"system\" if\nnot present.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"address\"</code></dt>\n<dd>\n<p>The bus address to connect to in case <code>bus</code> is <code>\"none\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to talk to this service as root. The DBus service\nwill see the DBus method calls and accesses as coming from root,\nrather than the logged in user. This is useful for talking to services\nthat do not correctly use\n<a href=\"https://www.freedesktop.org/software/polkit\">polkit</a> to authorize\nadministrative users. If the currently logged in user is not permitted\nto become root (eg: via <code>pkexec</code>) then the <code>client</code> will\nimmediately be <a href=\"#cockpit-dbus-onclose\">closed</a> with a\n<code>\"access-denied\"</code> problem code.\n+\nSet to <code>\"try\"</code> to try to talk as root, but if that fails, fall back\nto unprivileged.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"track\"</code></dt>\n<dd>\n<p>It is valid for a DBus service to exit, and be restarted in such a way\nthat clients continue to talk to it across the restart. Some services\nare not written with this in mind. If the <code>\"track\"</code> option is set to\n<code>true</code> then the channel will close when the service exits and/or\ndisconnects from the DBus bus.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>If the <code>name</code> argument is null, and no options other than <code>\"bus\"</code>\nare specified, then a shared DBus <code>client</code> is created. When using such\na client with a DBus bus, a <code>\"name\"</code> option must be specified on\nvarious other methods in order to specify which client to talk to.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-wait\">client.wait()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = client.wait([callback])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Returns a <code>promise</code> that is ready when the client is ready, or fails\nif the client closes. If a <code>callback</code> is specified, it is attached to\nthe promise.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-close\">client.close()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the DBus client. If <code>problem</code> is specified it should be a\n<a href=\"#cockpit-problems\">problem code</a> string.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-onclose\">client.onclose</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.addEventListener(\"close\", options =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the DBus client closes. This can happen either\nbecause <a href=\"#cockpit-dbus-close\">client.close()</a> function was called, or\nthe DBus service went away, or some other problem or disconnection.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> will contain various close information, including a\n<code>\"problem\"</code> field which will be set if the channel was closed because\nof a problem.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-onowned\">client.onowner</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.addEventListener(\"owner\", (event, owner) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the owner of the DBus name changes. The owner\nvalue will be the id of the name owner on the bus or null if the name is\nunowned. The absence of an owner should not be treated as a\ndisconnection. However this makes it possible to take some action based\non the actual status of the service, for example disconnecting a pending\nsignal handler.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-options\">client.options</h4>\n<div class=\"paragraph\">\n<p>Set to the options used when creating the client. Will not change for\nthe life of the client.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-unique-name\">client.unique_name</h4>\n<div class=\"paragraph\">\n<p>The unique DBus name of the client. Initially null, and becomes valid\nonce the the client is ready.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxy\">client.proxy()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy = client.proxy([interface, path], [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create proxy javascript object for a DBus <code>interface</code>. At the\nspecified DBus object <code>path</code>. The proxy will have properties, methods\nand signals from to the DBus interface, and allows for natural\ninteraction. If no <code>interface</code> is specified then the DBus bus name of\nthe client is used. If no <code>path</code> is specified, then the DBus name of\nthe client is converted to a path.</p>\n</div>\n<div class=\"paragraph\">\n<p>If creating lots of proxies for a given <code>interface</code> it is more\nefficient to use the <a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a>\nfunction.</p>\n</div>\n<div class=\"paragraph\">\n<p>The proxy is loaded when the\n<a href=\"#cockpit-dbus-proxy-valid\"><code>proxy.valid</code></a> field is <code>true</code>, and\nit is set to <code>false</code> if the underlying <code>interface</code> and/or <code>path</code>\ndon&#8217;t or no longer exist, or the <code>client</code> has closed. You can wait for\nproxy to become valid by passing a callback to its\n<a href=\"#cockpit-dbus-proxy-wait\"><code>proxy.wait()</code></a> function. The\n<a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a> event will also\nfire when the proxy becomes valid or invalid. DBus properties and\nmethods on the proxy are not defined until the proxy becomes valid.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>value = proxy.Prop1\nproxy.WritableProp = value</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>All DBus properties on the <code>interface</code> that start with an upper case\nletter (as is convention) will be automatically defined on this proxy,\nand will update their values as the DBus property values change. In\naddition the <a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a>\nevent will fire every time the properties change.</p>\n</div>\n<div class=\"paragraph\">\n<p>If you assign a value to a writable property on the proxy, the proxy\nwill try to set that property on the DBus <code>interface</code> at <code>path</code>. The\nactual proxy property value will not update until the DBus service has\nnotified the proxy of the change. If setting a property fails a warning\nwill be logged. In order to have more reliable setting of properties, or\ntrack when they have been set, or if setting fails, use the\n<a href=\"#cockpit-dbus-call\"><code>client.call()</code></a> directly. It should be noted\nthat DBus service implementations may also be inconsistent in their\nbehavior when setting a property fails.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can access the raw property data using the\n<a href=\"#cockpit-dbus-proxy-data\"><code>proxy.data</code></a> field, including data for\nproperties that do not start with an upper case letter.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.Method(arg1, arg2)\n    .then((retval1, retval2) =&gt; {\n        ...\n    })\n    .catch(ex =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>All DBus methods on the <code>interface</code> that start with an upper case\nletter (as is convention) will be automatically defined on this proxy.\nThese methods are called with arguments as normal javascript arguments.\nA\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the method returns, or fail if an\nerror occurs. The return values from the DBus method will be passed to\nthe <code>then</code> handler function directly.</p>\n</div>\n<div class=\"paragraph\">\n<p>Methods that do not start with an upper case letter can be invoked by\nusing the usual <a href=\"#cockpit-dbus-proxy-call\"><code>proxy.call()</code></a>\ndirectly.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.addEventListener(\"signal\", (event, arg1, arg2) =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>All DBus signals on the <code>interface</code> that start with an upper case\nletter (as is convention) will be automatically emit events on this\nproxy. These events will contain the signal arguments after the standard\n<code>event</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>Signals that do not start with an upper case letter can be subscribed to\nby using <a href=\"#cockpit-dbus-proxy-signal\"><code>proxy.onsignal</code></a> directly.</p>\n</div>\n<div class=\"paragraph\">\n<p>Usually a proxy asks the <code>client</code> to watch and notify it of changes to\nthe relevant object or path. You can pass an <code>options</code> argument with\nthe <code>watch</code> field set to <code>false</code> to prevent this.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxy-client\">proxy.client</h4>\n<div class=\"paragraph\">\n<p>Set to the DBus client of the proxy. Will not change for the life of the\nproxy.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxy-path\">proxy.path</h4>\n<div class=\"paragraph\">\n<p>Set to the DBus object path of the proxy. Will not change for the life\nof the proxy.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxy-iface\">proxy.iface</h4>\n<div class=\"paragraph\">\n<p>Set to the DBus interface name of the proxy. Will not change for the\nlife of the proxy.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxy-valid\">proxy.valid</h4>\n<div class=\"paragraph\">\n<p>Set to <code>true</code> when the proxy&#8217;s DBus interface is present at its DBus\npath, and all information for the proxy has loaded. Is set to <code>false</code>\nwhile loading, and after the proxy no longer refers a DBus interface and\npath. Also set to <code>false</code> if the <code>client</code> closes.</p>\n</div>\n<div class=\"paragraph\">\n<p>Use the by <a href=\"#cockpit-dbus-proxy-wait\"><code>proxy.wait()</code></a> function to\nwait for a proxy to load. The\n<a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a> event will also\nbe emitted when the proxy becomes valid or invalid. DBus properties and\nmethods on the proxy are not defined until the proxy becomes valid.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxy-data\">proxy.data</h4>\n<div class=\"paragraph\">\n<p>A plain javascript object containing all the raw property data that this\nproxy has loaded. This will be updated automatically as the proxy is\nnotified of property changes from the DBus service. The\n<a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a> event will be\nemitted when it changes.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxy-call\">proxy.call()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation = proxy.call(method, args, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Make a DBus method call on this proxy.</p>\n</div>\n<div class=\"paragraph\">\n<p>For DBus methods that start with an upper case letter, is usually more\nconvenient <a href=\"#cockpit-dbus-proxy\">to call the method directly on the\nproxy</a>. However if methods that do not follow the usual DBus convention,\nor specify additional options, or the caller cannot be sure that the\nmethod actually exists, you can use this method.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function also works on proxies that have are still loading and have\nnot become valid yet.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>method</code> should be a DBus method name, and the <code>args</code> should be\nan array of arguments to pass to the method. The <code>options</code> are\n<a href=\"#cockpit-dbus-call\">described elsewhere</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The returned value is identical to the one returned from\n<a href=\"#cockpit-dbus-call\">client.call()</a>. It is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the method returns, or fail if an\nerror occurs.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxy-wait\">proxy.wait()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = proxy.wait()\nproxy.wait(() =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Wait for a proxy to finish loading. This function returns a promise. If\na callback function is passed as an argument then that function will be\ninvoked when the proxy is ready. If this method is called after a proxy\nhas already loaded, then the promise will be resolved immediately, and\nany callback will be invoked immediately. Use the promise or\n<code>proxy.valid</code> to determine whether the proxy is valid.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxy-onchanged\">proxy.onchanged</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.addEventListener(\"changed\", (event, data) =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when the proxy&#8217;s properties change.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> has the following form, and will only include properties\nthat have changed:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n    \"Prop1\": \"value\",\n    \"Prop2\": 5\n}</pre>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxy-signal\">proxy.onsignal</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.addEventListener(\"signal\", (event, name, args) =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when the proxy&#8217;s emits an event.</p>\n</div>\n<div class=\"paragraph\">\n<p>For most events, that have names which start with an upper case letter,\nyou can just <a href=\"#cockpit-dbus-proxy\">connect to that event as a signal\ndirectly</a>. However if you wish to be notified when any signal is\nemitted, or for signals that do not follow the usual DBus convention,\nyou can connect to this event.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>name</code> is the DBus signal name, and the <code>args</code> is an array of\narguments that were emitted with the signal.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxies\">client.proxies()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies = client.proxies([interface], [path_namespace], [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create <a href=\"#cockpit-dbus-proxy\">proxy javascript objects</a> for a DBus\ninterfaces. The proxies will have properties, methods and signals from\nthe DBus <code>interface</code>, and allow for natural interaction. If no\n<code>interface</code> is specified then the DBus bus name of the client is used.\nIf no <code>path_namespace</code> is provided then <code>\"/\"</code> will be used.</p>\n</div>\n<div class=\"paragraph\">\n<p>Proxies will be automatically created for instances of the <code>interface</code>\navailable at the DBus service. The optional <code>path_namespace</code> argument\ncan be used to restrict the proxies for instances that have DBus paths\nwhich have the namespace path prefix.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy1 = proxies[\"/dbus/path1\"];\nproxy2 = proxies[\"/dbus/path2\"];\nfor (proxy in proxies) {\n    ...\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The returned <code>proxies</code> object will is used as a dictionary, and will\nhave values containing proxies for DBus interface instances, with the\nkeys being the DBus paths of those instances. It is possible to\nenumerate over the returned <code>proxies</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>Proxies will be automatically added and removed from the <code>proxies</code>\nobject as they appear and disappear in the service. The\n<a href=\"#cockpit-dbus-proxies-onadded\"><code>proxies.onadded</code></a> and\n<a href=\"#cockpit-dbus-proxies-onremoved\"><code>proxies.onremoved</code></a> events will\nbe emitted. DBus services may not support notifications of paths\ndisappearing.</p>\n</div>\n<div class=\"paragraph\">\n<p>Use the <code>proxies.wait()</code> function to be notified when the initial set\nof proxies has been populated.</p>\n</div>\n<div class=\"paragraph\">\n<p>Usually a proxies ask the <code>client</code> to watch and be notified of changes\nto the relevant object or path. You can pass an <code>options</code> argument\nwith the <code>watch</code> field set to <code>false</code> to prevent this.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxies-wait\">proxies.wait()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = proxies.wait()\nproxies.wait(() =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Wait for a <code>proxies</code> object to populate its initial set of proxies.\nThis function returns a promise. If a callback function is passed as an\nargument then that function will be invoked when the proxies are ready.\nIf this method is called after the proxies have populated, then the\npromise will be resolved immediately, and any callback will be invoked\nimmediately.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxies-client\">proxies.client</h4>\n<div class=\"paragraph\">\n<p>Set to the DBus client of the proxies. Will not change.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxies-iface\">proxies.iface</h4>\n<div class=\"paragraph\">\n<p>Set to the DBus interface name of the proxies. Will not change.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxies-path_namespace\">proxies.path_namespace</h4>\n<div class=\"paragraph\">\n<p>Set to the DBus path namespace used which the proxies must have as a\nDBus path prefix. Will not change.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxies-onadded\">proxies.onadded</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies.addEventListener(\"added\", (event, proxy) =&gt; {\n    ...\n})</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when a proxy is added to the <code>proxies</code> object.\nThe proxy will already have loaded.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxies-onchanged\">proxies.onchanged</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies.addEventListener(\"changed\", (event, proxy) =&gt; {\n    ...\n})</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when one of the proxy in the <code>proxies</code> object\nchanges its properties.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-proxies-onremoved\">proxies.onremoved</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies.addEventListener(\"removed\", (event, proxy) =&gt; {\n    ...\n})</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when a proxy is removed to the <code>proxies</code> object.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-call\">client.call()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation = client.call(path, interface, method, args, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Make a DBus method call.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>path</code> is the DBus object path to make the call on, <code>interface</code>\nis the DBus interface for the method and <code>method</code> is the name of the\nmethod to call. The <code>args</code> is an array of arguments to pass to the\nmethod, each of which must be appropriate for the expected\n<a href=\"#cockpit-dbus\">DBus type</a> of that argument. The <code>args</code> may be\n<code>null</code> if no arguments are to be sent.</p>\n</div>\n<div class=\"paragraph\">\n<p>The returned value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the method returns, or fail if an\nerror occurs.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>options</code> is specified it should be a plain javascript object,\nwhich may contain the following properties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>flags</code></dt>\n<dd>\n<p>A string containing DBus message flags. The character <code>\"i\"</code>\nindicates to the dbus service that interactive authentication is\nallowed. If the entire <code>flags</code> field is missing, then <code>\"i\"</code> is set\nby default.</p>\n</dd>\n<dt class=\"hdlist1\"><code>type</code></dt>\n<dd>\n<p>A valid DBus type signature to use when calling the method. In the\nabsence of this, the DBus service will be introspected (and the result\ncached) to ask what the method type signature is.</p>\n</dd>\n<dt class=\"hdlist1\"><code>timeout</code></dt>\n<dd>\n<p>The timeout of the call in milliseconds. The call will fail with the\n<code>\"timeout\"</code> problem code. If \"timeout\" is not given, the call will\nnever time out.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-then\">invocation.then()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation.then((args, options) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the DBus method call\nfinishes successfully.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>args</code> argument is an array of return values from the DBus method.\nEach of them will be converted to an appropriate\n<a href=\"#cockpit-dbus\">javascript type</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> argument may contain additional information about the\nreply. If the <code>type</code> option was specified when performing the method\ncall, then the <code>options</code> in the reply here will also contain a\n<code>type</code> field containing the DBus type signature of the output. If the\n<code>flags</code> option was specified when performing the call then the\n<code>options</code> in the reply here will contain message flags. Possible out\nmessage flags are:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>&gt;</code></dt>\n<dd>\n<p>A big endian message.</p>\n</dd>\n<dt class=\"hdlist1\"><code>&lt;</code></dt>\n<dd>\n<p>A little endian message.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-catch\">invocation.catch()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation.catch(exception =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the DBus method call\nfails.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>exception</code> object passed to the handler can have the following\nproperties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>problem</code></dt>\n<dd>\n<p>A <a href=\"#cockpit-problems\">problem code</a> string when a problem occurred\nstarting or communicating with the DBus service. This is <code>null</code> in\nthe cases where an actual DBus error was occurred.</p>\n</dd>\n<dt class=\"hdlist1\"><code>name</code></dt>\n<dd>\n<p>The DBus error name. This will be <code>null</code> in cases where the failure\nwas not due to a DBus error.</p>\n</dd>\n<dt class=\"hdlist1\"><code>message</code></dt>\n<dd>\n<p>A DBus error message. This will be <code>null</code> in cases where the failure\nwas not due to a DBus error.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-subscribe\">client.subscribe()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>subscription = client.subscribe(match, (path, interface, signal, args) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Subscribe to signals. The <code>match</code> argument is a javascript plain\nobject which defines what signals to subscribe to. Each property in the\n<code>match</code> argument restricts signals subscribed to. If a property is not\npresent then it is treated as a wildcard, matching anything. If an empty\nobject is specified as <code>match</code> then all signals will be subscribed to.\nThe <code>match</code> argument may contain the following properties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>interface</code></dt>\n<dd>\n<p>A DBus interface to match.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path</code></dt>\n<dd>\n<p>A DBus object path to match. May not be used together with the\n<code>path_namespace</code> property. It should be a valid DBus object path,\nthat is, it should have no trailing slash.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path_namespace</code></dt>\n<dd>\n<p>A DBus object path prefix to match. Any paths in the hierarchy below\nthis top path will match. May not be used together with the <code>path</code>\nproperty.</p>\n</dd>\n<dt class=\"hdlist1\"><code>member</code></dt>\n<dd>\n<p>The DBus signal name to match.</p>\n</dd>\n<dt class=\"hdlist1\"><code>arg0</code></dt>\n<dd>\n<p>Matches the first argument of a DBus message, which must be a string.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The handler passed as the second argument will be invoked when the\nsignal is received. A <code>subscription</code> is returned which can be used to\nremove the subscription by calling its <code>subscription.remove()</code> method.</p>\n</div>\n<div class=\"paragraph\">\n<p>It is not a problem to subscribe to the same signals more than once,\nwith identical or slightly different <code>match</code> arguments.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-remove\">subscription.remove()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>subscription.remove()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Unsubscribe from the DBus signal subscription.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-watch\">client.watch()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch = client.watch(path)\nwatch = client.watch({ \"path_namespace\": path_namespace, \"interface\": interface })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Watch for property and interface changes on the given DBus object\n<code>path</code> DBus <code>path_namespace</code>. If <code>interface</code> is specified only\nproperties on that DBus interface will be watched.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-dbus-proxy\"><code>client.proxy()</code></a> and\n<a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a> functions and the\nobjects they return are high level wrappers around <code>client.watch()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The property and interface changes will be available in raw form on the\n<a href=\"#cockpit-dbus-onnotify\"><code>client.onnotify</code></a> event.</p>\n</div>\n<div class=\"paragraph\">\n<p>Property and interface changes that are caused by a method call or\nsignal will show up before that method call reply is received, or signal\nevent is triggered. It should be possible to rely on this guarantee,\nunless the DBus service in question behaves incorrectly. Internally\nthese watches work well with code that implements the\n<a href=\"https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager\">ObjectManager</a>\nportion of the DBus specification. If no ObjectManager implementation is\navailable, the watch falls back to using DBus\n<a href=\"https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-introspectable\">Introspection</a>\nalong with the usual\n<a href=\"https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties\">PropertiesChanged</a>\nsignal. If the DBus service implements none of these, or implements them\nin an inconsistent manner, then this function will provide inconsistent\nor unexpected results.</p>\n</div>\n<div class=\"paragraph\">\n<p>The parameter is either a DBus <code>path</code> or a plain javascript object\nwith zero or more of the following fields. If an empty javascript object\nis used as an argument, then all paths, interfaces and properties will\nbe watched.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>interface</code></dt>\n<dd>\n<p>Watch properties on this DBus interface.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path</code></dt>\n<dd>\n<p>Watch interfaces and properties at this DBus path. May not be used\ntogether with the <code>path_namespace</code> property.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path_namespace</code></dt>\n<dd>\n<p>Watch interfaces and properties under this DBus path. It should be a\nvalid DBus object path, that is, it should have no trailing slash. If\nan ObjectManager implementation is available at this interface, then\nit is used. May not be used together with the <code>path</code> property.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The returned value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the watch has populated its initial\nset of properties and interfaces, and these have been notified via\n<a href=\"#cockpit-dbus-onnotify\"><code>client.onnotify</code></a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>A watch can be removed by calling the\n<a href=\"#cockpit-dbus-watch-remove\"><code>watch.remove()</code></a> method on the\nreturned value. If identical watches are added more than once, then they\nmust also be removed the same number of times before the removal takes\neffect.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-watch-then\">watch.then()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch.then(() =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the watch has populated\nits initial properties and interfaces.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-watch-catch\">watch.catch()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch.catch(ex =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called if the watch fails to populate\nits initial properties and interfaces. Note that a watch will only fail\nif the DBus client closes or is somehow disconnected. It does not fail\nin the case of missing interfaces or properties.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-watch-remove\">watch.remove()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch.remove()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Remove the watch. This may not have any immediate effect if other\nwatches are in place. In particular, if identical watches are added more\nthan once, then they must also be removed the same number of times\nbefore the removal takes effect.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-onnotify\">client.onnotify</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.addEventListener(\"notify\", data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when <a href=\"#cockpit-dbus-watch\">watched</a> properties or\ninterfaces change.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-dbus-proxy\"><code>client.proxy()</code></a> and\n<a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a> functions and the\nobjects they return are high level wrappers around the <code>data</code> provided\nby this event.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> has the following form:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n    \"/path1\": {\n        \"org.Interface1\": {\n            \"Prop1\": \"value\",\n            \"Prop2\": 5\n        },\n        \"org.Interface2\": null\n    }\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Multiple paths may be present, each of which may have multiple\ninterfaces, each of which may have multiple properties. The first time a\ngiven path and interface is emitted from this signal, it will have all\nits properties and interfaces. Thereafter only changes are noted. If an\ninterface is set to <code>null</code>, then that interface has disappeared.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-notify\">client.notify()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.notify(data)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Emits a synthetic <a href=\"#cockpit-dbus-onnotify\"><code>notify</code></a> event. The\n<code>data</code> argument should follow the same layout as described for the\n<code>notify</code> event.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-onmeta\">client.onmeta</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.onmeta = (ev, data) =&gt; { ... }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the meta data about\n<a href=\"#cockpit-dbus-watch\">watched</a> interfaces is loaded.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-dbus-proxy\"><code>client.proxy()</code></a> and\n<a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a> functions and the\nobjects they return are high level wrappers around the <code>data</code> provided\nby this event.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> has the following form:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>  {\n      \"org.Interface\": {\n          \"methods\": {\n              \"Method1\": {\n                  \"in\": [ \"s\", \"v\" ],\n                  \"out\": [ \"i\" ]\n              },\n              \"Method2\": { }\n          },\n          \"signals\": {\n              \"Signal\": {\n                  \"in\": [ \"b\", \"s\" ]\n              }\n          },\n          \"properties\": {\n              \"Prop1\": {\n                  \"flags\": \"rw\",\n                  \"type\": \"s\"\n              },\n              \"Prop2\": {\n                  \"flags\": \"r\",\n                  \"type\": \"b\"\n              }\n          }\n      }\n  }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Multiple interfaces may be present, each of which may have methods and\nproperties. This is emitted before the first\n<a href=\"#cockpit-dbus-proxy\"><code>client.onnotify</code></a> event for the relevant\ninterface.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-dbus-variant\">cockpit.variant()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>variant = cockpit.variant(type, value)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>A DBus variant is represented as a plain javascript object with a\n<code>\"t\"</code> property represesting the full DBus type of the variant, and a\n<code>\"v\"</code> property containing the variant value.</p>\n</div>\n<div class=\"paragraph\">\n<p>This is a helper function for creating such a variant object.</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_cockpit_js_errors\">cockpit.js: Errors</h3>\n<div class=\"paragraph\">\n<p>cockpit.js: Errors</p>\n</div>\n<div class=\"paragraph\">\n<p>Problem codes and messages</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-problems\">Problem Codes</h4>\n<div class=\"paragraph\">\n<p>Cockpit represents problems with standardized problem string codes.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"access-denied\"</code></dt>\n<dd>\n<p>The user is not permitted to perform the action in question.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"authentication-failed\"</code></dt>\n<dd>\n<p>User authentication failed.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"internal-error\"</code></dt>\n<dd>\n<p>An unexpected internal error without further info. This should not\nhappen during the normal course of operations.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"no-cockpit\"</code></dt>\n<dd>\n<p>The system does not have a compatible version of Cockpit installed or\ninstalled properly.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"no-session\"</code></dt>\n<dd>\n<p>Cockpit is not logged in.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"not-found\"</code></dt>\n<dd>\n<p>Something specifically requested was not found, such as a file,\nexecutable etc.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"terminated\"</code></dt>\n<dd>\n<p>Something was terminated forcibly, such as a connection, process\nsession, etc.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"timeout\"</code></dt>\n<dd>\n<p>Something timed out.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"unknown-hostkey\"</code></dt>\n<dd>\n<p>The remote host had an unexpected or unknown key.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"no-forwarding\"</code></dt>\n<dd>\n<p>Could not forward authentication credentials to the remote host.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-messages\">cockpit.message()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>message = cockpit.message(problem)\nmessage = cockpit.message(exception)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Return a message for the <code>exception</code> or <code>problem</code> code passed as an\nargument. If the argument is an object with a <code>\"message\"</code> property, as\nis the case with most exceptions, that will be returned directly. If the\nargument is an object with a <code>\"problem\"</code> property, then it will be\nused as the problem code. An appropriate message will be returned for\nproblem codes.</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_cockpit_js_file_access\">cockpit.js: File Access</h3>\n<div class=\"paragraph\">\n<p>The <code>cockpit.file</code> API lets you read, write, and watch regular files\nin their entirety. It cannot efficiently do random access in a big file\nor read non-regular files such as <code>/dev/random</code>.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>file = cockpit.file(path,\n                    { syntax: syntax_object,\n                      binary: boolean,\n                      max_read_size: int,\n                      superuser: string,\n                    })\n\npromise = file.read()\npromise\n    .then((content, tag) =&gt; { ... })\n    .catch(error =&gt; { ... })\n\npromise = file.replace(content, [ expected_tag ])\npromise\n    .then(new_tag =&gt; { ... })\n    .catch(error =&gt; { ... })\n\npromise = file.modify(callback, [ initial_content, initial_tag ]\npromise\n    .then((new_content, new_tag) =&gt; { ... })\n    .catch(error =&gt; { ... })\n\nfile.watch((content, tag, [error]) =&gt; { }, [ { read: boolean } ])\n\nfile.close()</pre>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-file-simple\">Simple reading and writing</h4>\n<div class=\"paragraph\">\n<p>You can read a file with code like this:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.file(\"/path/to/file\").read()\n    .then((content, tag) =&gt; {\n        ...\n    })\n    .catch(error =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>It is recommended to use absolute paths. Relative paths are resolved\nagainst <code>/</code>. To work with the current user&#8217;s files\n<a href=\"#cockpit-user\">cockpit.user()</a> can be used to get the user&#8217;s home\ndirectory.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>read()</code> method returns a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>When successful, the promise will be resolved with the content of the\nfile. Unless you specify options to change this (see below), the file is\nassumed to be text in the UTF-8 encoding, and <code>content</code> will be a\nstring.</p>\n</div>\n<div class=\"paragraph\">\n<p>The tag that is passed to the <code>then()</code> callback is a short string that\nis associated with the file and changes whenever the content of the file\nchanges. It is meant to be used with <code>replace()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>It is not an error when the file does not exist. In this case, the\n<code>then()</code> callback will be called with a <code>null</code> value for <code>content</code>\nand <code>tag</code> is <code>\"-\"</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>superuser</code> option can be used the same way as described in the\n<a href=\"#cockpit-channels-channel\">cockpit.channel()</a> to provide a different\naccess level to the file.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can use the <code>max_read_size</code> option to limit the amount of data\nthat is read. If the file is larger than the given number of bytes, no\ndata is read and the channel is closed with problem code <code>too-large</code>.\nThe default limit is 16 MiB. The limit can be completely removed by\nsetting it to -1.</p>\n</div>\n<div class=\"paragraph\">\n<p>To write to a file, use code like this:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.file(\"/path/to/file\").replace(\"my new content\\n\")\n    .then(tag =&gt; {\n        ...\n    })\n    .catch(error =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <code>replace()</code> method returns a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>When the promise is resolved, the file has been atomically replaced (via\nthe <code>rename()</code> syscall) with the new content. As with <code>read()</code>, by\ndefault the new content is a string and will be written to the file as\nUTF-8. The returned tag corresponds to the new content of the file.</p>\n</div>\n<div class=\"paragraph\">\n<p>When the promise is rejected because of an error, the file or its meta\ndata has not been changed in any way.</p>\n</div>\n<div class=\"paragraph\">\n<p>As a special case, passing the value <code>null</code> to <code>replace()</code> will\nremove the file.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>replace()</code> method can also check for conflicting changes to a\nfile. You can pass a tag (as returned by <code>read()</code> or <code>replace()</code>) to\n<code>replace()</code>, and the file will only be replaced if it still has the\ngiven tag. If the tag of the file has changed, <code>replace()</code> will fail\nwith an error object that has <code>error.problem == \"change-conflict\"</code>.\nSee <code>modify()</code> below for a convenient way to achieve transactional\nupdates to a file.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-file-format\">File format</h4>\n<div class=\"paragraph\">\n<p>By default, a file is assumed to be text encoded in UTF-8, and the\n<code>read()</code> and <code>replace()</code> functions use strings to represent the\ncontent.</p>\n</div>\n<div class=\"paragraph\">\n<p>By specifying the <code>syntax.parser()</code> and <code>syntax.stringify()</code>\noptions, you can cause <code>read()</code> to parse the content before passing it\nback to you, and <code>replace()</code> to unparse it before writing.</p>\n</div>\n<div class=\"paragraph\">\n<p>The main idea is to be able to write <code>{ syntax: JSON }</code>, of course,\nbut you can easily pass in individual functions or make your own\nparser/unparser object:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.file(\"/path/to/file.json\", { syntax: JSON })\n\nvar syntax_object = {\n    parse:     my_parser,\n    stringify: my_unparser\n};\n\ncockpit.file(\"/path/to/file\", { syntax: syntax_object })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Any exceptions thrown by the <code>parse()</code> and <code>stringify()</code> functions\nare caught and reported as read or write errors.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>null</code> value that is used to represent the content of a\nnon-existing file (see \"Simple reading and writing\", above) is not\npassed through the <code>parse()</code> and <code>stringify()</code> functions.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-file-binary\">Binary files</h4>\n<div class=\"paragraph\">\n<p>By default the content of the file is assumed to be text encoded as\nUTF-8 and it can not contain zero bytes. The content is represented as a\nJavaScript string with <code>read()</code>, <code>replace()</code>, etc. By setting the\n<code>binary</code> option to true when creating the proxy, no assumptions are\nplaced on the content, and it is represented as a <code>Uint8Array</code> in\nJavaScript.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-file-atomic\">Atomic modifications</h4>\n<div class=\"paragraph\">\n<p>Use <code>modify()</code> to modify the content of the file safely. A call to\n<code>modify()</code> will read the content of the file, call <code>callback</code> on the\ncontent, and then replace the content of the file with the return value\nof the callback.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>modify()</code> method uses the <code>read()</code> and <code>replace()</code> methods\ninternally in the obvious way. Thus, the <code>syntax.parse()</code> and\n<code>syntax.stringify()</code> options work as expected, <code>null</code> represents a\nnon-existing file, and the watch callbacks are fired.</p>\n</div>\n<div class=\"paragraph\">\n<p>It will do this one or more times, until no other conflicting changes\nhave been made to the file between reading and replacing it.</p>\n</div>\n<div class=\"paragraph\">\n<p>The callback is called like this</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>new_content = callback (old_content)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The callback is allowed to mutate <code>old_content</code>, but note that this\nwill also mutate the objects that are passed to the watch callbacks.\nReturning <code>undefined</code> from the proxy is the same as returning\n<code>old_content</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>modify()</code> method returns a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The promise will be resolved with the new content and its tag, like so</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>function shout(old_content) {\n    return old_content.toUpperCase();\n}\n\ncockpit.file(\"/path/to/file\").modify(shout)\n    .then((content, tag) =&gt; {\n        ...\n    })\n    .catch(error =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If you have cached the last content and tag results of the <code>read()</code> or\n<code>modify()</code> method, or the last values passed to a watch callback, you\ncan pass them to <code>modify()</code> as the second and third argument. In this\ncase, <code>modify()</code> will skip the initial read and start with the given\nvalues.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-file-notify\">Change notifications</h4>\n<div class=\"paragraph\">\n<p>Calling <code>watch()</code> will start monitoring the file for external changes.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>handle = file.watch(callback);\n\nhandle_no_read = file.watch(callback, { read: false });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Whenever a change occurs, the <code>callback()</code> is called with the new\ncontent and tag of the file. This might happen because of external\nchanges, but also as part of calls to <code>read()</code>, <code>replace()</code>, and\n<code>modify()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>When a read error occurs, the <code>callback()</code> is called with an error as\na third argument. Write errors are not reported via the watch callback.</p>\n</div>\n<div class=\"paragraph\">\n<p>Calling <code>watch()</code> will also automatically call <code>read()</code> to get the\ninitial content of the file. Thus, you normally don&#8217;t need to call\n<code>read()</code> at all when using <code>watch()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>To disable the automatic reading, e.g. for large files or unreadable\nfile system objects, set the <code>read</code> option to <code>false</code>. The first\n<code>content</code> argument of the callback will then always be <code>null</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>To free the resources used for monitoring, call <code>handle.remove()</code>.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-file-path\">file.path</h4>\n<div class=\"paragraph\">\n<p>A string containing the path that was passed to the <code>cockpit.file()</code>\nmethod.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-file-close\">Closing</h4>\n<div class=\"paragraph\">\n<p>Call the <code>close()</code> method on a file proxy to cancel all ongoing\noperations, such as reading, writing, and monitoring. The proxy should\nnot be used after closing it.</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_cockpit_js_http_client\">cockpit.js: HTTP Client</h3>\n<div class=\"paragraph\">\n<p>Cockpit allows access to local HTTP and REST services via this API.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-http-constructor\">cockpit.http()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>http = cockpit.http(endpoint, [options])\nhttp = cockpit.http(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new HTTP client. The <code>endpoint</code> can be a file path starting\nwith <code>/</code> to connect to a unix socket, or it can be a port number to\nconnect to. The optional <code>options</code> argument is a javascript plain\nobject, and may include:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"address\"</code></dt>\n<dd>\n<p>Connect to an address other than localhost. Must be a valid host name\nor IP address. To use this option you also must provide a port number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"port\"</code></dt>\n<dd>\n<p>Port number to use with \"address\" option, when not given in\n<code>endpoint</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"tls\"</code></dt>\n<dd>\n<p>Object properties for an https connection. See\n<code>http-stream2 TLS options</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"headers\"</code></dt>\n<dd>\n<p>Additional HTTP headers to include with the HTTP request. This is a\nplain javascript object with each key as a header name, and each value\nas the header value.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to open this channel as root. If the currently\nlogged in user is not permitted to become root (eg: via <code>pkexec</code>)\nthen the <code>channel</code> will immediately be\n<a href=\"#cockpit-channels-close-ev\">closed</a> with a <code>\"access-denied\"</code>\nproblem code.\n+\nSet to <code>\"try\"</code> to try to make the request as root, but if that\nfails, fall back to perform an unprivileged request.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"tls\"</code></dt>\n<dd>\n<p>If set to a plain javascript object, then the connection will be an\nHTTPS connection and include TLS encryption. The fields of the <code>tls</code>\nobject declare various TLS configuration and data. All fields are\noptional:\n+</p>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><code>\"authority\"</code>: Certificate authority(s) to expect as signers of\nthe server&#8217;s TLS certificate, represented as a plain javascript\nobject. It should have either a <code>\"file\"</code> field containing a readable\nPEM file on the system containing authorities, or a <code>\"data\"</code> with\nPEM encoded certificate data.</p>\n</li>\n<li>\n<p><code>\"certificate\"</code>: A client certificate to use, represented as a\nplain javascript object. It should have either a <code>\"file\"</code> field\ncontaining a readable PEM file on the system to use as a certificate,\nor a <code>\"data\"</code> with PEM encoded certificate data.</p>\n</li>\n<li>\n<p><code>\"key\"</code>: A client key to use, represented as a plain javascript\nobject. It should have either a <code>\"file\"</code> field containing a readable\nPEM file on the system to use as a key, or a <code>\"data\"</code> with PEM\nencoded key data.</p>\n</li>\n<li>\n<p><code>\"validate\"</code>: A boolean that describes whether to validate the\nserver&#8217;s TLS certificate or not. By default local connections are not\nvalidated, and remote connections are validated.</p>\n</li>\n</ul>\n</div>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Here is a somewhat complex example of using most of the above\n<code>options</code> when when calling <code>cockpit.http()</code>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>http = cockpit.http({\n    \"address\": \"localhost\",\n    \"headers\": {\n        \"Authorization\": \"Basic dXNlcjpwYXNzd29yZA==\"\n    },\n    \"port\": 443,\n    \"tls\": {\n        \"validate\": true,\n        \"authority\": {\n            \"file\": \"/etc/pki/tls/certs/ca-bundle.crt\",\n        },\n        \"certificate\": {\n            \"data\": \"-----BEGIN CERTIFICATE-----\\nMIIDsDCCA...\"\n        },\n        \"key\": {\n            \"data\": \"-----BEGIN RSA PRIVATE KEY-----\\nMIIEogIBA...\"\n        }\n    }\n});</pre>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-http-get\">http.get()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request = http.get(path, [params, [headers]])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Perform an HTTP GET request for the given <code>path</code>. If the <code>params</code> is\nspecified it should be a plain javascript object, which will be turned\ninto a query string.</p>\n</div>\n<div class=\"paragraph\">\n<p>Optionally a plain javascript object containing headers can be included\nin the <code>headers</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>The return value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete if the request happens successfully, or fail if\nthere&#8217;s a problem.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-http-post\">http.post()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request = http.post(path, body, [headers])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Perform an HTTP POST request for the given <code>path</code>. The <code>body</code> can be\na string, or a javascript plain object, which will be encoded as JSON\ndata. If <code>body</code> is <code>undefined</code> or <code>null</code> then an empty HTTP body\nwill be sent.</p>\n</div>\n<div class=\"paragraph\">\n<p>Optionally a plain javascript object containing headers can be included\nin the <code>headers</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>The return value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete if the request happens successfully, or fail if\nthere&#8217;s a problem.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-http-request\">http.request()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request = http.request(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Perform an HTTP request. The <code>options</code> can contain the following:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"body\"</code></dt>\n<dd>\n<p>The HTTP request body. If you do not specify a body, then you must\ncall <a href=\"#cockpit-http-input\">request.input()</a> to complete the body\nand allow the request to start.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"headers\"</code></dt>\n<dd>\n<p>A javascript plain object containing HTTP headers.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"method\"</code></dt>\n<dd>\n<p>The HTTP method. Defaults to <code>\"GET\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"params\"</code></dt>\n<dd>\n<p>A javascript plain object containing query string parameters.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"path\"</code></dt>\n<dd>\n<p>The HTTP path. Defaults to <code>/</code>.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The return value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete if the request happens successfully, or fail if\nthere&#8217;s a problem.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-http-then\">request.then()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.then(data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the request finishes\nsuccessfully.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> argument contains the body result of the request. If it a\nstring, unless the process was opened in binary mode, in which case the\n<code>data</code> is an array of bytes. If a <code>request.stream()</code> handler is set\nup, then any standard output data consumed by the handler will not be\nincluded in the <code>data</code> argument.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-http-catch\">request.catch()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.catch((exception[, data]) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the request fails, or\nreturns an error code.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>exception</code> object passed to the handler can have the following\nfields:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>problem</code></dt>\n<dd>\n<p>A <a href=\"#cockpit-problems\">problem code</a> string when a problem occurred\nstarting or communicating with the server. This is <code>null</code> if the\nprocess exited or was terminated.</p>\n</dd>\n<dt class=\"hdlist1\"><code>status</code></dt>\n<dd>\n<p>The numeric status of the response. This is <code>null</code> if no response\nwas received.</p>\n</dd>\n<dt class=\"hdlist1\"><code>reason</code></dt>\n<dd>\n<p>A string reason returned in the response. This is <code>null</code> if no\nresponse was received.</p>\n</dd>\n<dt class=\"hdlist1\"><code>message</code></dt>\n<dd>\n<p>A string message returned in the response. This is <code>null</code> if no\nresponse was received.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>If the request returned a response body, it will be available in the\n<code>data</code> argument. Otherwise this argument will be <code>undefined</code>.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-http-response\">request.response()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.response((status, headers) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This sets up a handler to be called when the HTTP request gets the\ninitial response from the server. The <code>status</code> argument is the HTTP\nstatus integer, and the <code>headers</code> is a plain javascript object\ncontaining the headers of the response.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-http-stream\">request.stream()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.stream(data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This sets up a handler to be called when the request returns output\ndata. The handler will be called multiple times.</p>\n</div>\n<div class=\"paragraph\">\n<p>Only one handler may be registered at a time. Registering an additional\nhandler replaces the previous one. The handler receives either string\n<code>data</code> or an array of binary bytes as its argument. A stream handler\nmay return a number, which indicates the number of characters or bytes\nconsumed from <code>data</code>. Any data not consumed will be included again the\nnext time the handler is called.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>request.stream()</code> handler is set up, then the <code>request.then()</code>\nhandlers will only get any remaining data not consumed by the stream\nhandler.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-http-input\">request.input()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.input(data, [stream])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This method writes <code>data</code> to the HTTP request body. It is only valid\nif no <code>\"body\"</code> has been specified in\n<a href=\"#cockpit-http-request\">http.request()</a> options. If <code>stream</code> is\n<code>true</code> then this function can be called again to provide further data.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-http-close\">request.close()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cancel the request. If <code>problem</code> is specified it should be a standard\n<a href=\"#cockpit-problems\">problem code</a> string.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-http-close-all\">http.close()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>http.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cancel all outstanding requests with the given problem code. This is\nuseful when you know that the server is going down soon.</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_cockpit_js_localization\">cockpit.js: Localization</h3>\n<div class=\"paragraph\">\n<p>Cockpit provides a <a href=\"https://www.gnu.org/software/gettext/\"><code>gettext()</code></a>\nlike API for easy translation of strings.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-locale-language\">cockpit.language</h4>\n<div class=\"paragraph\">\n<p>The current locale language code. This is set based on the\n<a href=\"#cockpit-locale-locale\"><code>cockpit.locale()</code></a> data loaded.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-locale-locale\">cockpit.locale()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.locale(po)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Load locale information for a given <code>po</code> data. The data should be JSON\ndata in the <a href=\"https://www.npmjs.org/package/po2json\">po2json</a> format. The\ndata will be loaded globally. If <code>po</code> data has already been loaded,\nthen this will extend that loaded data with additional strings. Any\nidentical translations strings will be replaced with the new strings. A\n<code>null</code> argument clears all the locale information previously loaded.</p>\n</div>\n<div class=\"paragraph\">\n<p>Various methods such as\n<a href=\"#cockpit-locale-gettext\"><code>cockpit.gettext()</code></a> make use of the\nloaded data.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-locale-gettext\">cockpit.gettext()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>translated = cockpit.gettext([context], string)\nvar _ = cockpit.gettext\nvar C_ = cockpit.gettext\ntranslated = _(\"string\")\ntranslated = C_(\"context\", \"string\")</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Lookup <code>string</code> for translation in the loaded locale data. The\ntranslated string will be returned, or <code>string</code> will be returned if no\nsuch translated string is present. The <code>context</code> argument is an\noptional string used to qualify the string.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function can be assigned to a variable called <code>_</code> (underscore)\nwhich will make your code work with the typical <code>_(\"string\")</code> syntax.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-locale-noop\">cockpit.noop()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>var N_ = cockpit.noop\nvar NC_ = cockpit.noop</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>A noop function suitable for assigning to <code>N_</code> or <code>NC_</code> so that\ngettext scanners will be able to find translatable strings. More\nspecifically this function returns its last argument.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-locale-ngettext\">cockpit.ngettext()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>translated = cockpit.ngettext([context], string1, stringN, number)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Lookup a string appropriate for a pluralization form of the <code>number</code>.\nVarious languages have complex pluralization forms that go far between\nthe singular and plural forms speakers of English are familiar with. If\nno such translated string is found then either one of <code>string1</code> or\n<code>stringN</code> is returned according to simple pluralization rules.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>context</code> argument is an optional string used to qualify the\nstring.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-locale-translate\">cockpit.translate()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.translate()\ncockpit.translate(element, ...)\ncockpit.translate(selection)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The document will be scanned for <code>translate</code> tags and they will be\ntranslated according to the strings in loaded locale data. One or more\n<code>element</code> arguments may be specified. These are DOM elements for\nspecific parts of the document to be translated. If no <code>element</code> is\nspecified then the entire document is translated.</p>\n</div>\n<div class=\"paragraph\">\n<p>If an array or array-like object is passed as a <code>selection</code> then all\nDOM elements in the array will be treated as parts of the document to be\ntranslated.</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_cockpit_js_page_location_and_jumping\">cockpit.js: Page Location and Jumping</h3>\n<div class=\"paragraph\">\n<p>Page location and navigation between components</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-location-general\">Page location</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>location = cockpit.location\ncockpit.location = \"/path\"</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit components often have different views, without changing the HTML\nfile that is being viewed. These are known as pages.\n<code>cockpit.location</code> is an object that can be used to read the current\npage and to navigate to a different page location. It works by updating\n<code>window.location.hash</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>cockpit.location</code> looks like a HTTP path with a possible query\nstring:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>/path/sub/page?option=value,option2</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-location-path\"><code>location.path</code></a> and\n<a href=\"#cockpit-location-options\"><code>location.options</code></a> contain a parsed\nform of the location. While the location cannot be modified in place, a\nnew one can be created by assigning a string to <code>cockpit.location</code> or\nby calling the <a href=\"#cockpit-location-go\"><code>location.go()</code></a> function.</p>\n</div>\n<div class=\"paragraph\">\n<p><code>cockpit.location</code> is designed similarly to <code>window.location</code> in\nthat the location object is preplaced whenever the current page location\nchanges. To be aware of when the page location changes listen for the\n<a href=\"#cockpit-location-changed\"><code>cockpit.onlocationchanged</code></a> event.</p>\n</div>\n<div class=\"paragraph\">\n<p>Using the location object as a string will result in the\n<a href=\"#cockpit-location-href\"><code>location.href</code></a>.</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-location-href\">location.href</h5>\n<div class=\"paragraph\">\n<p>The string representation of this page location, including any options.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-location-path\">location.path</h5>\n<div class=\"paragraph\">\n<p>An array of path segments, parsed and decoded appropriately. An empty\narray denotes the root path.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-location-options\">location.options</h5>\n<div class=\"paragraph\">\n<p>A javascript object containing the various options present in the\nlocation.</p>\n</div>\n<div class=\"paragraph\">\n<p>If an option appears more than once, its value will be an array.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-location-go\">location.go()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>location.go(path, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Changes the current location to the given <code>path</code> and <code>options</code>. If\nthe <code>path</code> argument is a string, it will be parsed into a path. If it\nis a relative path, then the result will be relative to the current\n<code>location.path</code>. If the <code>path</code> argument is an array of path\nsegments, it will be treated as a full parsed absolute path.</p>\n</div>\n<div class=\"paragraph\">\n<p>Any options found in a <code>path</code> will be added to those in the optional\n<code>options</code> argument, and used in the result.</p>\n</div>\n<div class=\"paragraph\">\n<p>The location change will only take effect if the location has not\nchanged in the meantime. This can be to good effect by saving a\n<code>cockpit.location</code> object and doing a conditional navigation, by\ncalling the saved <code>location.go()</code> method later. This will only\nnavigate if the user or other code has not navigated in the meantime.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-location-replace\">location.replace()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>location.replace(path, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Similar to <a href=\"#cockpit-location-go\"><code>location.go()</code></a> except the\nlocation change will not result in a navigation change in the browser&#8217;s\nhistory.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-location-decode\">location.decode()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>path = location.decode(href, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Decode a cockpit href into its <code>path</code> array. If the <code>options</code>\nargument is specified, then it will be populated with options found in\nthe href.</p>\n</div>\n<div class=\"paragraph\">\n<p>If href is a relative path it will be resolved relative to\n<code>location.href</code>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-location-encode\">location.encode()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>href = location.encode(path, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Encode the given <code>path</code> and <code>options</code> into a cockpit href. The\n<code>path</code> argument may be an array of path segments, or a string path. If\na relative path is passed, it will be resolved relative to\n<code>location.href</code>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-location-changed\">cockpit.onlocationchanged</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.addEventListener(\"locationchanged\", function() { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event emitted when over the <code>cockpit.location</code> changes. Typically a\ncomponent reacts to this event by updating its interface to reflect the\nnew <a href=\"#cockpit-location-path\"><code>cockpit.location.path</code></a> and\n<a href=\"#cockpit-location-options\"><code>cockpit.location.options</code></a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This event is not triggered immediately during a <code>location.go()</code> or\nsimilar call. It will be triggered asynchronously at a later time.</p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-jump\">Jumping between components</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.jump(\"/system/log\")</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>In Cockpit in there multiple components shown. In order to tell Cockpit\nto jump to and show another component and a certain location within that\ncomponent, use the <code>cockpit.jump()</code> function. Stable component paths\nare documented. Don&#8217;t assume you can navigate into paths that are not\nstable API.</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-jump-jump\">cockpit.jump()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.jump(path, [ host ])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Ask Cockpit to jump to another component. The location of the current\ncomponent will not be affected. The <code>path</code> argument can be a string\npath, starting with <code>/</code> or an array containing the parts of a path\nthat will be joined to create a path. If <code>host</code> is not specified, then\nthe component on the same host as the caller will be displayed. If host\nis null, then the host portion of the path will be removed, displaying\nthe component on the host that cockpit is connected directly to.</p>\n</div>\n<div class=\"paragraph\">\n<p>If the calling component is not running within Cockpit, or the calling\ncomponent is not currently displayed, then the jump will not happen, and\nthis function has no effect.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-jump-hidden\">cockpit.hidden</h5>\n<div class=\"paragraph\">\n<p>A boolean property that indicates if the current component page is\nvisible or hidden. When the code or user jumps to another component, the\nprior one remains loaded and initialized but is hidden. Use this\nproperty together with the\n<a href=\"#cockpit-jump-visibilitychange\"><code>cockpit.onvisibilitychange</code></a>\nevent to decide whether or not to perform expensive tasks to update the\ninterface.</p>\n</div>\n<div class=\"paragraph\">\n<p>This property is analogous to the <code>document.hidden</code> page visibility\nAPI, but works with the document and frame implementation of Cockpit.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-jump-visibilitychange\">cockpit.onvisibilitychange</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.onvisibilitychange = function() { ... }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when the\n<a href=\"#cockpit-jump-hidden\"><code>cockpit.hidden</code></a> property changes. This\nevent is similar to the <code>document.onvisibilitychange</code> API, but works\nwith the document and frame implementation of Cockpit.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_cockpit_js_user_session\">cockpit.js: User Session</h3>\n<div class=\"paragraph\">\n<p>User information and login session state</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-logout\">cockpit.logout()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.logout([reload])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Logout of Cockpit. Unless <code>reload</code> is <code>false</code> this will also cause\nthe page to be reloaded, so that the user can see the logged out state.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-user\">cockpit.user()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>var promise = cockpit.user();\npromise.then(user =&gt; { ... });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This object contains information about the user that&#8217;s currently logged\ninto cockpit. The following fields are defined:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"id\"</code></dt>\n<dd>\n<p>This is unix user id.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"gid\"</code></dt>\n<dd>\n<p>This is unix user group id.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"name\"</code></dt>\n<dd>\n<p>This is the unix user name like <code>\"root\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"full_name\"</code></dt>\n<dd>\n<p>This is a readable name for the user.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"groups\"</code></dt>\n<dd>\n<p>This is an array of group names to which the user belongs. Since\nversion 318, the first item in this list is the primary group.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"home\"</code></dt>\n<dd>\n<p>This is user&#8217;s home directory.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"shell\"</code></dt>\n<dd>\n<p>This is unix user shell.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Returns a promise that completes once the user information is available.</p>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p><code>cockpit.user()</code> is soft-deprecated since Cockpit 336, if your page\ndoes not need to maintain compatibility with older Cockpit versions you\ncan use<a href=\"#cockpit-info\">cockpit.info</a> to obtain the user information.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-permission\">Permission lookup</h4>\n<div class=\"paragraph\">\n<p>Cockpit provides a mechanism for checking if the current user satisfies\na given criteria. This is meant for updating UI elements based on what\nactions the user can perform. It is <em>not an access control mechanism</em>.</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-permission-constructor\">cockpit.permission()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>permission = cockpit.permission([options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new permission object to check if the current user has a\nparticular permission specified by <code>options</code>:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>admin: true</code></dt>\n<dd>\n<p>True if the session has superuser privileges, i.e. can run channels as\nroot with <code>{ superuser: \"require\" }</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>group:</code> <em>name</em></dt>\n<dd>\n<p>True if the currently logged user is a member of group <em>name</em>.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The permission result is always true for the \"root\" user. When\n<code>options</code> is not given, check if the current user is root.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-permission-allowed\">permission.allowed</h5>\n<div class=\"paragraph\">\n<p>A boolean value which indicates if the permission is allowed or not.\nThis will be <code>null</code> if the permission is unknown, or there was an\nerror checking the permission or the permission data has not yet loaded.\nThis property will update asynchronously and if you wish to be notified\nof changes connect to the\n<a href=\"#cockpit-permission-changed\">permission.onchanged</a> event.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-permission-changed\">permission.onchanged</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>permission.addEventListener(\"changed\", function() { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is fired when the permission changes. In particular the\n<a href=\"#cockpit-permission-allowed\">permission.allowed</a> property.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-permission-close\">permission.close()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>permission.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Closes the permission object and tears down any registered callbacks and\ndbus subscriptions.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_cockpit_js_manifests\">cockpit.js: Manifests</h3>\n<div class=\"sect3\">\n<h4 id=\"cockpit-manifest-loading\">Loading Manifests</h4>\n<div class=\"paragraph\">\n<p>For a convenient access to all page manifests, include\n<code>&lt;script src=\"../manifests.js\"&gt;&lt;/script&gt;</code> into your page to register\nthe manifests at the <code>cockpit.manifests</code> global variable.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can also load <code>../manifests.json</code> directly in your page, with\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch\"><code>fetch()</code></a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_cockpit_js_metrics\">cockpit.js: Metrics</h3>\n<div class=\"paragraph\">\n<p>Metrics about the system can be retrieved from several sources using\n<a href=\"#cockpit-metrics\"><code>cockpit.metrics()</code></a> metrics channels. The\nmetrics are made available as series data, and can be used with the\n<a href=\"#cockpit-series\"><code>cockpit.series()</code></a> and\n<a href=\"#cockpit-grid\"><code>cockpit.grid()</code></a> facilities.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-metrics-function\">cockpit.metrics()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics = cockpit.metrics(interval, options, cache)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Opens a new metrics channel. The data retrieved will be available in the\n<a href=\"#cockpit-metrics-series\"><code>metrics.series</code></a> series sink, and can be\nused together with <a href=\"#cockpit-grid\"><code>cockpit.grid()</code></a> objects.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>interval</code> is in milliseconds, and is the granularity of the\nseries data retrieved. Any grids consuming the data must have the same\ninterval.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>cache</code> argument is a cache identifier. If specified, then this\nmetrics channel will share data with other metrics channels of the same\nidentifier. Make sure to use a globally unique string.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> argument is either a javascript plain object, or an\narray of those. Each object can have the following fields.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"metrics\"</code></dt>\n<dd>\n<p>An array of full metric descriptions, as javascript objects. The\nspecifics of these, and how to determine which ones to use, can\nunfortunately only be found in the low-level protocol documentation.\nThis option is required.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"source\"</code></dt>\n<dd>\n<p>The source to use for real-time data. This is used by the <code>follow</code>\nmethod, see below. Set to <code>\"internal\"</code> to retrieve internal metrics\nread by the bridge. If set to <code>\"direct\"</code> or <code>\"pmcd\"</code> then data\nwill be retrieved from <a href=\"https://pcp.io\">PCP</a>if it is available. The\ndefault is <code>\"internal\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"archive_source\"</code></dt>\n<dd>\n<p>The source to use for retrieving historical data. This is used by the\n<code>fetch</code> method, see below. Set to <code>\"pcp-archive\"</code> to retrieve data\nfrom PCP archives. The default is not to try to retrieve historical\ndata.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>When the <code>options</code> argument is an array of javascript objects, then\nthe metrics channel tries to use them in order until one succeeds. This\nway, you can prefer PCP as the source but fall back to internal metrics\nwhen PCP is not available, for example. The channel gives no indication\nwhich of the options has been used, and <code>fetch</code> and <code>follow</code> might\nuse different entries from the list.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-metrics-fetch\">metrics.fetch()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.fetch(beg, end)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Retrieve archived metrics data between <code>beg</code> and <code>end</code>. The\narguments can either be numbers, in which case they are interval based\noffsets, or they can be javascript Date objects.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-metrics-follow\">metrics.follow()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.follow()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Start retrieving live metrics data as it become available.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-metrics-close\">metrics.close()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Stop the retrieval of metrics and release resources.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-metrics-series\">metrics.series</h4>\n<div class=\"paragraph\">\n<p>The series sink where data retrieved data will be processed.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-metrics-meta\">metrics.meta</h4>\n<div class=\"paragraph\">\n<p>The metrics meta data last received.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-metrics-onchanged\">metrics.onchanged</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.onchanged = function() { }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when one of the properties on this metrics object\nchanges.</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_cockpit_js_series_data\">cockpit.js: Series Data</h3>\n<div class=\"paragraph\">\n<p>Series data consists of values along a continuous (usually time) axis.\nWe can place these in grids which expose a distinct subset of these\nvalues. These are the underlying mechanism for displaying metrics data\nin graphs.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-grid\">cockpit.grid()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid = cockpit.grid(interval, [beg, end])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Creates a grid object to contain series data.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>interval</code> is the granularity of the grid. Usually this is a\nnumber of milliseconds, when used with time series data. The <code>beg</code> and\n<code>end</code> are the bounds of the grid. If omitted they will be set to zero\nfor an initially empty grid.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>beg</code> and/or <code>end</code> are negative (including negative zero) then\nthey are interpreted in number of intervals relative to the current\ntime. Thus cockpit.grid(1000, -300, -0) will create a grid for the most\nrecent 5 minutes.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-grid-add\">grid.add()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>row = grid.add(series, path)\nrow = grid.add(callback, [early])\nrow = grid.add()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Adds a row to the grid. The returned <code>row</code> is a Javascript array that\nwill contain series data. The arguments control how the row is populated\nfrom the series data. The <code>row</code> is a sparse array. Its <code>row.length</code>\nwill not match the expected size of the grid, unless and until the row\nhas been completely filled in. The first index of the <code>row</code> will\ncontain the data from the series data at the\n<a href=\"#cockpit-grid-beg\"><code>grid.beg</code></a> offset.</p>\n</div>\n<div class=\"paragraph\">\n<p>When no arguments are passed, an empty row is added, and it is not\npopulated with data.</p>\n</div>\n<div class=\"paragraph\">\n<p>When called with a <code>series</code> and <code>path</code> argument then the row will be\npopulated directly with series data. The <code>series</code> can either be a\n<a href=\"#cockpit-series\">series object</a> or an object that has an\n<code>obj.series</code> property. The <a href=\"#cockpit-series-interval\">series\ninterval</a> must match the interval of this grid. If <code>path</code> is missing\nor empty, then the series data is placed into the row directly.\nOtherwise <code>path</code> indicates which part of the series data to place in\nthe row. When <code>path</code> is an array, it is used as a set of property\nnames or array indexes to follow into nested series data. When <code>path</code>\nis a dotted string, it is split and used the same way to locate the\ncorrect value in nested series data. The exact format of the series data\ndepends on its producer, and relevant paths will be documented there.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>callback</code> function is specified, then it will be invoked to\nprovide series data for the row. The function is invoked as\n<code>callback(row, index, count)</code>, where the <code>row</code> is the row to fill\nin, the <code>index</code> is the index to start filling in and <code>count</code> is the\nnumber of items to fill in. The <code>this</code> variable will be set to the\ngrid while invoking the <code>callback</code>. The callback is called after other\ndata rows for a given series have been filled in. Callbacks are called\nin the order added, unless the <code>early</code> argument is set to <code>true</code>, in\nwhich case the callback is called earlier than callbacks without the\n<code>early</code> argument set.</p>\n</div>\n<div class=\"paragraph\">\n<p>To remove the row use the <a href=\"#cockpit-grid-remove\"><code>grid.remove()</code>\nmethod.</a></p>\n</div>\n<div class=\"paragraph\">\n<p>The row will start being populated with data when the <code>series</code>\nproduces data. To make this happen right away, use the\n<a href=\"#cockpit-grid-sync\"><code>grid.sync()</code></a> method.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-grid-remove\">grid.remove()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.remove(row)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Remove a previously added <code>row</code> from the grid. The row will no longer\nbe updated with series data.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-grid-sync\">grid.sync()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.sync()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Load or reload data from the series into the rows. This does not clear\nthe rows before populating them. Some data may be populated immediately,\nothers may have to wait until data can be loaded. Internally this\nfunction calls <a href=\"#cockpit-series-load\"><code>series.load()</code></a> for each\nseries.</p>\n</div>\n<div class=\"paragraph\">\n<p>All rows with callbacks will be invoked to regenerate all the data. The\n<a href=\"#cockpit-grid-onnotify\"><code>grid.onnotify</code></a> event will be triggered.\nIt is not necessary to call this function after a call of the\n<a href=\"#cockpit-grid-move\"><code>grid.move()</code></a> method.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-grid-move\">grid.move()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.move(beg[, end])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Move the grid to new <code>beg</code> and <code>end</code> range. Data will be discarded\nfrom the rows and <a href=\"#cockpit-grid-sync\"><code>grid.sync()</code></a> will be\ncalled to load or reload series data for the new range of offsets.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>end</code> is not specified it will be set to <code>beg</code>. If <code>beg</code> and/or\n<code>end</code> are negative (including negative zero) then they will be set to\nthe number of intervals prior to the current time taken as an interval.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>beg</code> and/or <code>end</code> are negative (including negative zero) then\nthey are interpreted in number of intervals relative to the current\ntime. Thus cockpit.grid(1000, -300, -0) will create a grid for the most\nrecent 5 minutes.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-grid-walk\">grid.walk()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.walk()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Move the grid forward every\n<a href=\"#cockpit-grid-interval\"><code>grid.interval</code></a> milliseconds. To stop\nmoving forward, call <a href=\"#cockpit-grid-move\"><code>grid.move()</code></a>.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-grid-notify\">grid.notify()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.notify(index, count)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This function is called to have rows with callbacks recalculate their\ndata. It is not normally necessary to call this function, as it will be\ninvoked automatically when new series data is available or has been\nloaded. This function triggers the\n<a href=\"#cockpit-grid-onnotify\"><code>grid.onnotify</code></a> event.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-grid-onnotify\">grid.onnotify</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.addEventListener(\"notify\", function(index, count) { ... });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event that is triggered when some part of the series data in grid\nchanges. The <code>index</code> is the row index where things changed, and the\n<code>count</code> is the length of the data that changed.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-grid-close\">grid.close()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the grid, and stop updating the rows.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-grid-interval\">grid.interval</h4>\n<div class=\"paragraph\">\n<p>The granularity of the grid. For time series data this is an interval in\nmilliseconds. In order to use a given <a href=\"#cockpit-grid\">grid</a> and\n<a href=\"#cockpit-series\">series</a> together, their interval properties must\nmatch.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-grid-beg\">grid.beg</h4>\n<div class=\"paragraph\">\n<p>The beginning offset of the series data in the grid. Do not set this\nproperty directly. Use the <a href=\"#cockpit-grid-move\">grid.move()</a> method\ninstead.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-grid-end\">grid.end</h4>\n<div class=\"paragraph\">\n<p>The ending offset of the series data in the grid. Do not set this\nproperty directly. Use the <a href=\"#cockpit-grid-move\">grid.move()</a> method\ninstead.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-series\">cockpit.series()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>series = cockpit.series(interval, [cache, fetch])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new sink of series data. This is usually done by producers of\nseries data, and it is rare to invoke this function directly.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>interval</code> is the granularity of the series data. For time series\ndata this is an interval in milliseconds. If a <code>cache</code> string is\nspecified, series data will be cached across frames for series with the\nsame <code>cache</code> cache identifier to load and/or reload.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>fetch</code> callback is specified, then it will be invoked when grids\nrequest certain ranges of data. The <code>fetch</code> callback is invoked with\n<code>function fetch(beg, end) { ... }</code> range offsets. The\n<a href=\"#cockpit-series-input\">series.input()</a> should be called with data\nretrieved, either immediately or at a later time. The callback may be\ncalled multiple times for the same ranges of data. It is up to the\ncallback to determine when or whether it should retrieve the data more\nthan once.</p>\n</div>\n<div class=\"paragraph\">\n<p>A producer of series data, usually calls this function and creates\nitself a <code>obj.series</code> property containing this series object.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-series-input\">series.input()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>series.input(beg, items[, mapping])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Send series data into the series sink. Any grids that have added rows\nbased on this series, will have data filled in. The <code>beg</code> is the\nbeginning offset of <code>items</code>. The <code>items</code> are an array one or more\nseries data items.</p>\n</div>\n<div class=\"paragraph\">\n<p>Producers may wish to provide additional properties that can be used in\nlookup paths that rows can pull from. This is done in the <code>mapping</code>\nargument. If specified it is a tree of objects. Each sub object should\nhave a property with the name <code>\"\"</code> empty string, which will be used as\nthe property name or index in place of the one used in the lookup path.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-series-load\">series.load()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>series.load(beg, end)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Load data from the series into any grids that have rows based on this\nseries data. Any cached data will be filled in immediately. Any data not\ncached, will be requested from the producer, if possible, and may arrive\nat a later time.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>beg</code> and <code>end</code> denote the range of data to load.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-series-interval\">series.interval</h4>\n<div class=\"paragraph\">\n<p>The granularity of the series. For time series data this is an interval\nin milliseconds. In order to use a given <a href=\"#cockpit-grid\">grid</a> and\n<a href=\"#cockpit-series\">series</a> together, their interval properties must\nmatch.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-series-limit\">series.limit</h4>\n<div class=\"paragraph\">\n<p>The maximum number of items to cache for loading and/or reloading. You\ncan change this value to a different number. Having a number close to\nzero will break certain usage of grids, such as\n<a href=\"#cockpit-grid-walk\"><code>grid.walk()</code></a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_cockpit_js_spawning_processes\">cockpit.js: Spawning Processes</h3>\n<div class=\"paragraph\">\n<p>This is the API for spawning a process and receiving its output, as well\nas exit codes.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-spawn-spawn\">cockpit.spawn()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process = cockpit.spawn(args, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Spawns a process on the system.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>args</code> should be an array starting with the executable and\ncontaining all the arguments to pass on the command line. If <code>args</code> is\na string then it is interpreted as an executable name. The optional\n<code>options</code> argument is a javascript plain object and can contain any of\nthe following fields:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"binary\"</code></dt>\n<dd>\n<p>If set to <code>true</code> then handle the input and output of the process as\narrays of binary bytes.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"directory\"</code></dt>\n<dd>\n<p>The directory to spawn the process in.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"err\"</code></dt>\n<dd>\n<p>Controls where the standard error is sent. By default it is logged to\nthe journal. If set to <code>\"out\"</code> it is included in with the output\ndata. If set to <code>\"ignore\"</code> then the error output is discarded. If\nset to <code>\"message\"</code>, then it will be returned as the error message.\nWhen the <code>\"pty\"</code> field is set, this field has no effect.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"environ\"</code></dt>\n<dd>\n<p>An optional array that contains strings to be used as additional\nenvironment variables for the new process. These are <code>\"NAME=VALUE\"</code>\nstrings.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"pty\"</code></dt>\n<dd>\n<p>Launch the process in its own PTY terminal, and send/receive terminal\ninput and output.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"batch\"</code></dt>\n<dd>\n<p>Batch data coming from the process in blocks of at least this size.\nThis is not a guarantee. After a short timeout the data will be sent\neven if the data doesn&#8217;t match the batch size. Defaults to zero.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"latency\"</code></dt>\n<dd>\n<p>The timeout for flushing any cached data in milliseconds.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to spawn the process as root instead of the\nlogged in user. If the currently logged in user is not permitted to\nbecome root (eg: via <code>pkexec</code>) then the <code>client</code> will immediately\nbe <a href=\"#cockpit-dbus-onclose\">closed</a> with a <code>\"access-denied\"</code>\nproblem code.\n+\nSet to <code>\"try\"</code> to try to run the process as root, but if that fails,\nfall back to an unprivileged process.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The spawned process is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">promise</a>\nthat will complete if the process exits successfully, or fail if there&#8217;s\na problem. Some additional methods besides the standard promise methods\nare documented below.</p>\n</div>\n<div class=\"paragraph\">\n<p>The standard output of the process is made available via the spawned\nprocess object. Any non-UTF8 output from the process will be coerced\ninto textual form. It is highly recommended that only textual output be\nproduced by the command. The standard error is logged to the journal.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-spawn-script\">cockpit.script()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process = cockpit.script(script, [args], [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Run a shell script on the system.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function <a href=\"#cockpit-spawn-spawn\">spawns</a> a Bourne shell script\nprocess. The full text of the <code>/bin/sh</code> shell script should be passed\nin as the first argument. The <code>args</code> can be an array of arguments, not\nincluding the executable, which are passed to the script as <code>$1</code>,\n<code>$2</code> and so on. Shebang options are not used or respected.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> is an optional javascript plain object and can include\nany of the fields listed for the\n<a href=\"#cockpit-spawn-spawn\"><code>cockpit.spawn()</code></a> function.</p>\n</div>\n<div class=\"paragraph\">\n<p>The spawned process is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">promise</a>\nthat will complete if the script exits successfully, or fail if there&#8217;s\na problem. Some additional methods besides the standard promise methods\nare documented below.</p>\n</div>\n<div class=\"paragraph\">\n<p>The standard output of the process is made available via the spawned\nprocess object. Any non-UTF8 output from the process will be coerced\ninto textual form. It is highly recommended that only textual output be\nproduced by the command. The standard error is logged to the journal by\ndefault.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-spawn-then\">process.then()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.then((data[, message]) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">promise</a>\nmethod. It sets up a handler to be called when the process finishes\nsuccessfully.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> argument contains the standard output of the process. If it\na string, unless the process was opened in binary mode, in which case\nthe <code>data</code> is an array of bytes. If a <code>process.stream()</code> handler is\nset up, then any standard output data consumed by the handler will not\nbe included in the <code>data</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>If the process was spawned with the <code>\"err\"</code> option set to\n<code>\"message\"</code> then the second argument will contain the standard error\noutput of the process.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-spawn-catch\">process.catch()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.catch((exception[, data]) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the process fails,\nterminates or exits.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>exception</code> object passed to the handler can have the following\nfields:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>message</code></dt>\n<dd>\n<p>A message describing the exception. If the process was spawned with\nthe <code>\"err\"</code> option set to <code>\"message\"</code> then the second argument\nwill contain the standard error output of the process.</p>\n</dd>\n<dt class=\"hdlist1\"><code>problem</code></dt>\n<dd>\n<p>A <a href=\"#cockpit-problems\">problem code</a> string when a problem occurred\nstarting or communicating with the process. This is <code>null</code> if the\nprocess exited or was terminated.</p>\n</dd>\n<dt class=\"hdlist1\"><code>exit_status</code></dt>\n<dd>\n<p>The numeric exit status of the process. This is <code>null</code> if the\nprocess did not exit.</p>\n</dd>\n<dt class=\"hdlist1\"><code>exit_signal</code></dt>\n<dd>\n<p>A string representing a unix signal that caused the process to\nterminate. This is <code>null</code> if the process did not terminate because\nof a signal.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>If the process actually ran and produced output before failing, it will\nbe available in the <code>data</code> argument. Otherwise this argument will be\n<code>undefined</code>.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-spawn-stream\">process.stream()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.stream(data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This sets up a handler to be called when the process has standard\noutput. The handler will be called multiple times. The handler will be\ncalled regardless of whether the process ends up exiting successfully or\nnot.</p>\n</div>\n<div class=\"paragraph\">\n<p>Only one handler may be registered at a time. Registering an additional\nhandler replaces the previous one. The handler receives either string\n<code>data</code> or an array of binary bytes as its argument. A stream handler\nmay return a number, which indicates the number of characters or bytes\nconsumed from <code>data</code>. Any data not consumed will be included again the\nnext time the handler is called.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>process.stream()</code> handler is set up, then the <code>process.then()</code>\nhandlers will only get any remaining data not consumed by the stream\nhandler.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-spawn-input\">process.input()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.input(data, [stream])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This method writes <code>data</code> to the standard input of the process. If\n<code>data</code> is <code>null</code> or <code>undefined</code> it is not sent. The <code>data</code>\nshould be a string or an array of bytes if the process was opened in\nbinary mode.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>stream</code> is set to <code>true</code> then this function may be called again\nwith further input. Otherwise the standard input of the process is\nclosed.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-spawn-close\">process.close()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the process by closing its standard input and output. If\n<code>problem</code> is specified it should be a standard\n<a href=\"#cockpit-problems\">problem code</a> string. In this case the process\nwill be terminated with a signal.</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_cockpit_js_utilities\">cockpit.js: Utilities</h3>\n<div class=\"paragraph\">\n<p>Various utility functions</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-format\">cockpit.format()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format(template, args)\nstring = cockpit.format(template, [arg, ...])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Format a string interpolating <code>args</code> into <code>template</code> using shell\nlike syntax. The <code>args</code> may be either an array or javascript object.\nThe <code>template</code> can contain fields that look like <code>$name</code> or\n<code>${name}</code> or <code>$0</code>. Numeric fields are used with array <code>args</code> and\nstart at zero.</p>\n</div>\n<div class=\"paragraph\">\n<p>In the second form, multiple <code>arg</code> arguments may be passed directly,\nand interpolated as as numeric fields in the <code>template</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>All falsy arguments except the numbers <code>0</code> and `0.0`are replaced by\nan empty string.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-format-number\">cockpit.format_number()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_number(number, [precision])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Formats <code>number</code> into a displayable <code>string</code>. If the number is not\nan integer, it is rounded to the given number of decimal places,\ndefaulting to 3. If the number is near zero, but not quite zero it is\nrounded to the smallest non-zero value of the given precision; i.e.\n±0.001 for default precision 3.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>number</code> is <code>null</code> or <code>undefined</code> an empty string will be\nreturned.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-format-bytes\">cockpit.format_bytes()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_bytes(number, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Formats <code>number</code> into a displayable <code>string</code> with a suffix, such as\n<em>kB</em> or <em>MB</em>.</p>\n</div>\n<div class=\"paragraph\">\n<p>By default, SI units are used. IEC units (1024-based) can be requested\nby including <code>base2: true</code> in <code>options</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>By default, non-integer numbers will be formatted with 3 digits of\nprecision. This can be changed with <code>options.precision</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>number</code> is <code>null</code> or <code>undefined</code> an empty string will be\nreturned.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-format-bytes-per-sec\">cockpit.format_bytes_per_sec()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_bytes_per_sec(number, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Format <code>number</code> of bytes into a displayable speed <code>string</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is mostly equivalent to <code>cockpit.format_bytes()</code> but the\nreturned value contains a unit like <em>kB/s</em> or <em>MB/s</em>.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-format-bits-per-sec\">cockpit.format_bits_per_sec()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_bits_per_sec(number, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Format <code>number</code> of bits into a displayable speed <code>string</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is mostly equivalent to <code>cockpit.format_bytes()</code> but the\nreturned value contains a unit like <em>kbps</em> or <em>Mbps</em>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function does not support IEC units. <code>base2</code> may not be passed as\npart of <code>options</code>.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-init\">cockpit.init()</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>await cockpit.init();\n\ncockpit.init().then(() =&gt; { ... });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Requests initialization of the Cockpit client library. This will ensure\nthat the transport is connected and we are ready to create channels. It\nalso populates the <code>cockpit.info</code> field.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function returns a promise. Initialization isn&#8217;t complete until the\npromise has resolved. You can either <code>await</code> it or call <code>.then()</code> on\nit.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-info\">cockpit.info</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.info.channels[payload]\n\ncockpit.info.os_release[field]\n\ncockpit.info.user\n\ncockpit.info.ws.version</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This object contains information about Cockpit itself. It is only\navailable after cockpit.init() has been called and awaited.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>channels</code></dt>\n<dd>\n<p>This is a mapping of channel payload types (keys, strings) supported\nby the bridge to capabilities advertised by those channels (values,\nlists of strings). Channels are listed even if they don&#8217;t advertise\nany capabilities, making this useful as a way to determine which\nchannel types are supported by the bridge.</p>\n</dd>\n<dt class=\"hdlist1\"><code>os_release</code></dt>\n<dd>\n<p>This is the data from the <code>/etc/os-release</code> or\n<code>/usr/lib/os-release</code> on the system that the bridge is running on.\nIt is a mapping from the key names to their values. See the\n<a href=\"https://www.freedesktop.org/software/systemd/man/latest/os-release.html\">os-release\nSpecification</a> for information about the available keys.</p>\n</dd>\n<dt class=\"hdlist1\"><code>user</code></dt>\n<dd>\n<p>Contains information about the user we&#8217;re logged in as.</p>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>uid</code></dt>\n<dd>\n<p>This is unix user id as an integer.</p>\n</dd>\n<dt class=\"hdlist1\"><code>gid</code></dt>\n<dd>\n<p>This is unix user group id as an integer.</p>\n</dd>\n<dt class=\"hdlist1\"><code>name</code></dt>\n<dd>\n<p>This is the unix user name like <code>\"root\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>fullname</code></dt>\n<dd>\n<p>This is a readable name for the user, from the GECOS field.</p>\n</dd>\n<dt class=\"hdlist1\"><code>group</code></dt>\n<dd>\n<p>This is the primary group name of the user.</p>\n</dd>\n<dt class=\"hdlist1\"><code>groups</code></dt>\n<dd>\n<p>This is an array of group names to which the user belongs. The first\nitem in this list is the primary group.</p>\n</dd>\n<dt class=\"hdlist1\"><code>home</code></dt>\n<dd>\n<p>This is user&#8217;s home directory.</p>\n</dd>\n<dt class=\"hdlist1\"><code>shell</code></dt>\n<dd>\n<p>This is unix user shell.</p>\n</dd>\n</dl>\n</div>\n</dd>\n<dt class=\"hdlist1\"><code>ws</code></dt>\n<dd>\n<p>Contains information about the webserver Cockpit is being served with.</p>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>version</code></dt>\n<dd>\n<p>The version of the webserver.</p>\n</dd>\n</dl>\n</div>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"cockpit-event-target\">cockpit.event_target</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.event_target(object, [handlers])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Adds an\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/EventTarget\">EventTarget</a>\nimplementation to the <code>object</code>. Optionally store the handlers in\n<code>handlers</code> if its specified.</p>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_api_shell\">API: shell</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>This package contains the shell that loads other components.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_index_html\">index.html</h3>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;iframe src=\"http://127.0.0.1:9090/cockpit+app/@localhost/shell/index.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a Cockpit component that provides an interface to configure a\nsingle machine. It loads other components on demand to make that happen.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Component URL</dt>\n<dd>\n<p><code>/cockpit+app/@localhost/shell/index.html</code></p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_api_system\">API: system</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>This package contains general components for basic control of a system.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_logs_html\">logs.html</h3>\n<div class=\"paragraph\">\n<p>System log component</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"api-logs-html-description\">Description</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;iframe src=\"http://127.0.0.1:9090/cockpit+app/@localhost/system/logs.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a Cockpit component that brings up system log viewer, with\nfiltering capabilities. On systemd based systems this displays the\nentries from journal.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Component URL</dt>\n<dd>\n<p><code>/cockpit+app/@localhost/system/logs.html</code></p>\n</dd>\n<dt class=\"hdlist1\">Filter by priority</dt>\n<dd>\n<p><code>#?prio=notice</code><br>\n<br>\nFilters the log to show entries below the specific priority,\ninclusive. These\n<a href=\"https://en.wikipedia.org/wiki/Syslog#Severity_levels\">priorities are\nsyslog level keywords</a>. Specifying <code>*</code> as a priority will show all\navailable entries. The default priority is <code>err</code>.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by service</dt>\n<dd>\n<p><code>#?service=sshd.service</code><br>\n<br>\nFilters the log to show entries related to the specific service. The\nformat of the service is specific to the logging implementation. For\njournald these are systemd service unit names.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by tag</dt>\n<dd>\n<p><code>#?tag=kernel</code><br>\n<br>\nFilters the log to show entries related to the specific syslog\nidentifier.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by message</dt>\n<dd>\n<p><code>#?grep=</code><br>\n<br>\nFilters the log to show entries where the <code>MESSAGE=</code> field matches\nthe specified regular expression. PERL-compatible regular expressions\nare used. If the pattern is all lowercase, matching is case\ninsensitive. Otherwise, matching is case sensitive.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by any field</dt>\n<dd>\n<p><code>#?FIELD=VALUE</code><br>\n<br>\nA field is referring to the components of a structured journal entry.\nThe match must be exact. Value can be comma separated list in which\ncase they are automatically matched as alternatives.</p>\n</dd>\n<dt class=\"hdlist1\">Start at point</dt>\n<dd>\n<p><code>#?start=boot</code><br>\n<br>\nFilters the log to show entries after the specific point in time.\nValid values are <code>boot</code> (since last boot), <code>last-24h</code> (last 24\nhours), <code>last-week</code> (last seven days) and <code>previous-boot</code>\n(previous boot).</p>\n</dd>\n<dt class=\"hdlist1\">Follow the journal</dt>\n<dd>\n<p><code>#?follow=true</code><br>\n<br>\nKeep listening on new entries. Valid values are <code>true</code> (follow) and\n<code>false</code> (do not follow).</p>\n</dd>\n<dt class=\"hdlist1\">Show log entry</dt>\n<dd>\n<p><code>#/6e272d82993c4e0d...</code><br>\n<br>\nTo show a specific log entry, put the log entry cursor in a path after\nthe hash above. Note that cursors are logging system specific, and\njournal cursors are subject to change.</p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_terminal_html\">terminal.html</h3>\n<div class=\"paragraph\">\n<p>Server terminal component</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"api-terminal-html-description\">Description</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;iframe src=\"http://127.0.0.1:9090/cockpit+app/@localhost/system/terminal.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a Cockpit component that brings up a web-based terminal for the\nlogged in user.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Component URL</dt>\n<dd>\n<p><code>/cockpit+app/@localhost/system/terminal.html</code></p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/embedding.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Embedding and Integrating Cockpit</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"embedding\" class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>Embedding and Integrating Cockpit</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#embedding-full\">Embedding the Cockpit Interface</a></li>\n<li><a href=\"#embedding-components\">Integrating Cockpit Components into Web Applications</a></li>\n<li><a href=\"#embedding-deep\">Deep Integration</a></li>\n<li><a href=\"#embedding-cors\">Pinging Cockpit</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit can be embedded in other web applications either as a whole or\nspecific Cockpit components can be integrated. Due to frame security\npolicy restrictions, this only works if Cockpit and the web application\nhave the <em>same origin</em>; this is commonly achieved by running both from a\ncommon reverse proxy.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"embedding-full\">Embedding the Cockpit Interface</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit can be embedded into a larger web page as a frame. To embed the\nentire Cockpit Window use the URI: <code>https://server.example.com:9090/</code></p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-html\" data-lang=\"html\">&lt;html&gt;\n  &lt;head&gt;\n    &lt;title&gt;Embedded Cockpit&lt;/title&gt;\n  &lt;/head&gt;\n  &lt;body&gt;\n    This is Cockpit.\n    &lt;br/&gt;\n    &lt;iframe width=\"800px\" height=\"600px\"\n            src=\"https://server.example.com:9090/\"/&gt;\n  &lt;/body&gt;\n&lt;/html&gt;</code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"embedding-components\">Integrating Cockpit Components into Web Applications</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Instead of embedding the entirety of Cockpit, you can integrate specific\ncomponents. Only those components explicitly documented as API should be\nintegrated. Other components can and will change regularly.</p>\n</div>\n<div class=\"paragraph\">\n<p>The component will load from the server in question and a WebSocket\nconnection will be established with the server to relay the component&#8217;s\nmessage stream.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit components are HTML files contained in <a href=\"#packages\">packages</a>.\nThese can be placed in an iframe or web browser window. Each documented\nand stable component has a well-known URL and these are documented in\nthe <a href=\"#development\">API reference</a>. Each component URL begins with the\nstring <code>/cockpit/@localhost/</code> followed a package name, and then the\ncomponent itself.</p>\n</div>\n<div class=\"paragraph\">\n<p>For example the <a href=\"#api-terminal-html\">terminal.html</a> in the\n<a href=\"#api-system\">system</a> package, has this URL:\n<code>/cockpit/@localhost/system/terminal.html</code></p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-html\" data-lang=\"html\">&lt;html&gt;\n  &lt;head&gt;\n    &lt;title&gt;Embedded Terminal&lt;/title&gt;\n  &lt;/head&gt;\n  &lt;body&gt;\n    This is a terminal.\n    &lt;br/&gt;\n    &lt;iframe width=\"800px\" height=\"600px\"\n      src=\"https://server.example.com:9090/cockpit/@localhost/system/terminal.html\"/&gt;\n  &lt;/body&gt;\n&lt;/html&gt;</code></pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"embedding-deep\">Deep Integration</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Most often <a href=\"#embedding-components\">simple integration</a> will be used\nto bring Cockpit components into web applications. However it is also\npossible to do deep integration for embedders who wish to perform\nnon-standard authentication with the server, and relay the component&#8217;s\nmessage stream to the server themselves.</p>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>Deep integration capability is in heavy flux and is not yet documented.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"embedding-cors\">Pinging Cockpit</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>When embedding Cockpit or integrating Cockpit components, it may be\nnecessary to check whether Cockpit is available on a server before\nproceeding.</p>\n</div>\n<div class=\"paragraph\">\n<p>To do this perform a <code>/ping</code> request to Cockpit. This is a simple HTTP\nGET request. It returns the following:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>GET: https://server.example.com:9090/ping\n200 OK: { \"service\": \"cockpit\" }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <code>/ping</code> request allows\n<a href=\"https://en.wikipedia.org/wiki/Cross-origin_resource_sharing\">Cross Origin\nResource Sharing</a> headers and as such can be performed from Javascript\ncode with any origin. The request can also be made via plain HTTP\nwithout SSL. It is by design that no further information is present in\nthe response.</p>\n</div>\n<div class=\"paragraph\">\n<p>A complete example of using <code>/ping</code> is available in the Cockpit\nsources in the <code>/examples/ping-server/</code> directory.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/feature-firewall.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Firewall</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"feature-firewall\" class=\"article\">\n<div id=\"header\">\n<h1>Firewall</h1>\n</div>\n<div id=\"content\">\n<div class=\"paragraph\">\n<p>Cockpit uses <a href=\"https://www.firewalld.org\">firewalld</a> to interact with the\nsystem&#8217;s firewall. No firewall configuration UI will be shown if\nfirewalld is not installed.</p>\n</div>\n<div class=\"paragraph\">\n<p>Firewalld controls access to its APIs via PolicyKit. The user logged\ninto Cockpit needs to have the appropriate permissions to view or modify\nthe settings.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit can currently only show, add, and remove predefined firewalld\nservices in the default zone.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use\n<a href=\"https://www.firewalld.org/documentation/man-pages/firewall-cmd.html\">firewall-cmd</a>.\nFor example, to get the same list of allowed services that Cockpit\ndisplays:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo firewall-cmd --list-services\ndhcpv6-client samba-client mdns ssh cockpit</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>To enable an additional service, use:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ firewall-cmd --add-service pop3\nsuccess</pre>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/feature-journal.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Journal</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"feature-journal\" class=\"article\">\n<div id=\"header\">\n<h1>Journal</h1>\n</div>\n<div id=\"content\">\n<div class=\"paragraph\">\n<p>The systemd journal provides Cockpit with indexed log data. This log\ndata is found on the Journal page, as well as in various other places\nwhen configuring services, storage, networking etc.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit accesses Journal data via the\n<a href=\"https://www.freedesktop.org/software/systemd/man/journalctl.html\"><code>journalctl</code></a>\ncommand. Similar tasks can be performed at the command line:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo journalctl -f -u docker\n...</pre>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/feature-machines.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Multiple Machines</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"feature-machines\" class=\"article\">\n<div id=\"header\">\n<h1>Multiple Machines</h1>\n</div>\n<div id=\"content\">\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>This feature is deprecated as of Cockpit 322.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit can connect to multiple machines from a single Cockpit session.\nThese are listed in the host switcher.</p>\n</div>\n<div class=\"paragraph\">\n<p>These additional machines are accessed via SSH from the machine that the\nfirst machine connected to, and are <a href=\"#authentication\">authenticated</a>\nwith the logged in user&#8217;s password and/or SSH keys.</p>\n</div>\n<div class=\"paragraph\">\n<p>SSH host keys are stored in <code>/etc/ssh/ssh_known_hosts</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The machine data is stored in <code>/etc/cockpit/machines.d/*.json</code>, or\nbelow <code>$XDG_CONFIG_DIRS</code> if set (see\n<a href=\"./cockpit.conf.5.html\">cockpit.conf</a>). Settings in lexicographically\nlater files amend or override settings in earlier ones. Cockpit itself\nwrites into <code>99-webui.json</code>; packages or admins who want to\npre-configure machines should ship files like <code>05-mymachine.json</code> so\nthat changes from the web interface override the pre-configured files.</p>\n</div>\n<div class=\"paragraph\">\n<p>Each JSON file contains an object that maps machine IDs to objects that\ndefine the properties of that machine. The ID can be a human readable\nname or an IP address or any other unique value, and is shown in the web\ninterface until connecting to it the first time, at which point the web\ninterface will show the machine&#8217;s host name.</p>\n</div>\n<div class=\"paragraph\">\n<p>The following properties are recognized:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"address\"</code></dt>\n<dd>\n<p><em>(string, mandatory)</em> IP address or DNS name of the machine</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"visible\"</code></dt>\n<dd>\n<p><em>(boolean, optional)</em> If <code>true</code>, the machine will be displayed and\navailable for managing with Cockpit. If <code>false</code> (the default), it\nwill not be displayed, but still taken into account for type-ahead\nsearch when adding new machines in the web interface.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"user\"</code></dt>\n<dd>\n<p><em>(string, optional)</em> User name on the remote machine. When not given,\nCockpit will default to the user name that was being used to log into\nCockpit itself.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"port\"</code></dt>\n<dd>\n<p><em>(integer, optional)</em> ssh port of the remote machine. When not given,\nthe default port 22 is used.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"color\"</code></dt>\n<dd>\n<p><em>(string, optional)</em> Color to assign to the machine label in the web\ninterface. This can be either given as\n<code>rgb(r_value, g_value, b_value)</code> with each value being an integer\nbetween 0 and 255, or as a color name like <code>yellow</code>. When not given,\nCockpit will assign an unused color automatically.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Example:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n    \"web server\": {\n        \"address\": \"192.168.2.4\",\n        \"visible\": true,\n        \"color\": \"rgb(100, 200, 0)\",\n        \"user\": \"admin\"\n    },\n    \"192.168.2.1\": {\n        \"address\": \"192.168.2.1\",\n        \"port\": 2222,\n        \"visible\": true,\n        \"color\": \"green\"\n    }\n}</pre>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/feature-networkmanager.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>NetworkManager</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"feature-networkmanager\" class=\"article\">\n<div id=\"header\">\n<h1>NetworkManager</h1>\n</div>\n<div id=\"content\">\n<div class=\"paragraph\">\n<p>If available on the system, Cockpit uses\n<a href=\"https://wiki.gnome.org/Projects/NetworkManager\">NetworkManager</a> and the\nDBus APIs it provides to interact with the system&#8217;s network\nconfiguration.</p>\n</div>\n<div class=\"paragraph\">\n<p>For non root users, NetworkManager controls access to its APIs via\n<a href=\"#privileges\">Policy Kit</a> and a user logged into Cockpit will have\nthe same permissions as they do from the command line.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use the\n<a href=\"https://fedoraproject.org/wiki/Networking/CLI\">nmcli</a> command:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ nmcli general status\nSTATE      CONNECTIVITY  WIFI-HW  WIFI     WWAN-HW  WWAN\nconnected  full          enabled  enabled  enabled  enabled</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Devices marked as \"not managed\" with the <code>NM_CONTROLLED=no</code> setting\nwill not be displayed in the interface.</p>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/feature-packagekit.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Package Updates</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"feature-packagekit\" class=\"article\">\n<div id=\"header\">\n<h1>Package Updates</h1>\n</div>\n<div id=\"content\">\n<div class=\"paragraph\">\n<p>Cockpit uses the\n<a href=\"https://www.freedesktop.org/software/PackageKit/gtk-doc/api-reference.html\">PackageKit</a>\nD-Bus API to get information about available package updates and to\napply them, in an Operating System independent manner.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use the\n<a href=\"https://www.freedesktop.org/software/PackageKit/pk-using.html\">pkcon</a>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ pkcon refresh\n\n$ pkcon get-updates\nAvailable  sudo-1.8.20p2-1.fc26.x86_64 (updates-testing)\n    Allows restricted root access for specified users\nAvailable  vim-filesystem-2:8.0.617-1.fc26.x86_64 (updates-testing)\n    VIM filesystem layout\nAvailable  vim-minimal-2:8.0.617-1.fc26.x86_64 (updates-testing)\n    A minimal version of the VIM editor\n\n$ pkcon get-update-detail sudo\nDetails about the update:6.x86_64 [fedora]\n Package: sudo-1.8.20p2-1.fc26.x86_64\n Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1452941\n Update text: - update to 1.8.20p2\n    - added sudo package to dnf/yum protected packages\n\n$ pkcon update\nThe following packages have to be updated:\n sudo-1.8.20p2-1.fc26.x86_64    Allows restricted root access for specified users\n vim-filesystem-2:8.0.617-1.fc26.x86_64 VIM filesystem layout\n vim-minimal-2:8.0.617-1.fc26.x86_64    A minimal version of the VIM editor\nProceed with changes? [N/y] y\n[...]</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Of course you can also use your Operating System specific commands for\nthat, such as <code>dnf updateinfo info</code> on Fedora or <code>sudo apt upgrade</code>\non Debian.</p>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/feature-pcp.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>PCP Metrics</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"feature-pcp\" class=\"article\">\n<div id=\"header\">\n<h1>PCP Metrics</h1>\n</div>\n<div id=\"content\">\n<div class=\"paragraph\">\n<p>If available, Cockpit uses the <a href=\"https://pcp.io/\">Performance Co-Pilot</a>\nframework to gather metrics data about the system. This data is used to\ndisplay the history graphs on the \"Metrics and history\" page. Cockpit\ncan use the PCP logging feature to display archived data about the\nsystem from a different point in time. If PCP is not available, then\nCockpit gathers the metrics data itself, but archival features are not\navailable.</p>\n</div>\n<div class=\"paragraph\">\n<p>Whether or not metrics are archived depends on whether the\n<a href=\"https://linux.die.net/man/1/pmlogger\"><code>pmlogger.service</code></a> systemd unit\nis running or not. The \"Enable PCP metrics collector\" button on the\nMetrics page will enable and start this service.</p>\n</div>\n<div class=\"paragraph\">\n<p>To see similar metrics data from the command line, you can use tools\nlike <a href=\"https://linux.die.net/man/1/pmstat\"><code>pmstat</code></a> or\n<a href=\"https://linux.die.net/man/1/pminfo\"><code>pminfo</code></a>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ pmstat\n@ Sat Sep 26 15:30:10 2015\n loadavg                      memory      swap        io    system         cpu\n   1 min   swpd   free   buff  cache   pi   po   bi   bo   in   cs  us  sy  id\n    4.19      0 20710m 605148  6450m    0    0    0 2548 5688  14K  19   3  76\n...</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>These metrics can also be exposed to other machines on a TCP port with\n<a href=\"https://linux.die.net/man/1/pmproxy\">pmproxy</a> and\n<a href=\"https://redis.io/\">Redis</a> or <a href=\"https://valkey.io/\">Valkey</a>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>systemctl enable --now redis pmproxy\n# if you use firewalld, open port 44322:\nfirewall-cmd --permanent --add-service pmproxy\nfirewall-cmd --reload</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This allows you to gather and visualize PCP metrics from multiple\nmachines with <a href=\"https://grafana.com/\">Grafana</a> and the\n<a href=\"https://grafana-pcp.readthedocs.io\">PCP Grafana plugin</a>.</p>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/feature-realmd.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>realmd</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"feature-realmd\" class=\"article\">\n<div id=\"header\">\n<h1>realmd</h1>\n</div>\n<div id=\"content\">\n<div class=\"paragraph\">\n<p>If available on the system, Cockpit uses\n<a href=\"https://www.freedesktop.org/software/realmd/\">realmd</a> and the DBus APIs\nit provides to configure the system&#8217;s Active Directory or IPA domain\nmembership.</p>\n</div>\n<div class=\"paragraph\">\n<p>Not all systems can join all kinds of domains. This depends on the\navailability of the necessary client software.</p>\n</div>\n<div class=\"paragraph\">\n<p>For non root users, realmd controls access to its APIs via\n<a href=\"#privileges\">Policy Kit</a> and a user logged into Cockpit will have\nthe same permissions as they do from the command line.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use the\n<a href=\"https://www.freedesktop.org/software/realmd/docs/realm.html\">realm</a>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ realm join example.com\nPassword for Administrator:</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><a href=\"http://www.freedesktop.org/software/realmd/\">realmd</a> sets up\ndomain-qualified user names by default, i. e. login user names look like\n&#8220;user@example.com&#8221;. For using unqualified names (just &#8220;user&#8221;),\nset the <code>fully-qualified-names</code> option in\n<a href=\"https://www.freedesktop.org/software/realmd/docs/realmd-conf.html\">/etc/realmd.conf</a>\nbefore joining a domain.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit requests an SSL certificate from the IPA server for\n<code>cockpit-ws</code> with the\n<a href=\"https://www.freeipa.org/page/Certmonger\">ipa-getcert</a> command.</p>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/feature-selinux.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>SELinux Policy</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"feature-selinux\" class=\"article\">\n<div id=\"header\">\n<h1>SELinux Policy</h1>\n</div>\n<div id=\"content\">\n<div class=\"paragraph\">\n<p>If present on the system Cockpit can set the SELinux mode to enforcing\nor permissive. It can also use <code>setroubleshootd</code> to show audit issues\nand apply suggested fixes.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line use the <code>setenforce</code>\nand <code>sealert</code> tools.</p>\n</div>\n<div class=\"paragraph\">\n<p>To clear out all the information that <code>setroubleshootd</code> tracks, you\ncan use a commands like:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo killall setroubleshootd\n$ sudo rm -rf /var/lib/setroubleshoot/*</pre>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/feature-sosreport.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>SOS Report</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"feature-sosreport\" class=\"article\">\n<div id=\"header\">\n<h1>SOS Report</h1>\n</div>\n<div id=\"content\">\n<div class=\"paragraph\">\n<p>If present on the system Cockpit can use <code>sosreport</code> to collect system\nconfiguration and diagnostic information.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use the <code>sosreport</code>\ncommand.</p>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/feature-storaged.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>storaged</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"feature-storaged\" class=\"article\">\n<div id=\"header\">\n<h1>storaged</h1>\n</div>\n<div id=\"content\">\n<div class=\"paragraph\">\n<p>If available on the system, Cockpit uses\n<a href=\"https://github.com/storaged-project/storaged/\"><code>storaged</code></a> to configure\nand monitor storage, disks, mounts etc. on the system. This\nfunctionality is present in the Cockpit <em>storaged</em> package.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>storaged</code> project is originally based on a project called\n<a href=\"https://www.freedesktop.org/wiki/Software/udisks/\"><code>udisks</code></a> and added\nsupport for many more features such as\n<a href=\"https://en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)\">LVM</a>,\n<a href=\"https://en.wikipedia.org/wiki/ISCSI\">iSCSI</a>,\n<a href=\"https://en.wikipedia.org/wiki/Linux_DM_Multipath\">Multipath</a>, and\n<a href=\"https://btrfs.wiki.kernel.org/index.php/Main_Page\">BTRFS</a>. The same tools\nand backwards compatible API are available between <code>storaged</code> and\n<code>udisks</code> the projects. Cockpit can use <code>udisks</code> but disables many of\nit&#8217;s storage related features, including updating <code>/etc/fstab</code> and\n<code>/etc/crypttab</code> for stability reasons.</p>\n</div>\n<div class=\"paragraph\">\n<p>For non root users, storaged controls access to its APIs via\n<a href=\"#privileges\">Policy Kit</a> and a user logged into Cockpit will have\nthe same permissions as they do from the command line.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use the <code>storagedctl</code>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ udisksctl dump\n...</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>To perform LVM tasks, you may use the various LVM commands, such as\n<code>vgcreate</code>, <code>lvresize</code> and so on. Cockpit will detect such changes\nmade at the command line.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit recognizes devices with multiple paths and can start the\n<code>multipathd</code> service in case it is not running. On the command line,\nyou can control multipath features with the <code>mpathconf</code>,\n<code>multipathd</code>, and <code>multipath</code> commands.</p>\n</div>\n<div class=\"paragraph\">\n<p>To manage iSCSI initiators from the command line, you can use\n<code>iscsiadm</code> and related tools.</p>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/feature-systemd.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>systemd</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"feature-systemd\" class=\"article\">\n<div id=\"header\">\n<h1>systemd</h1>\n</div>\n<div id=\"content\">\n<div class=\"paragraph\">\n<p>Cockpit uses <a href=\"https://www.freedesktop.org/wiki/Software/systemd/\">systemd</a>\nand the DBus APIs it provides to configure and monitor core aspects of\nthe system. Use of alternate system APIs are not currently implemented.</p>\n</div>\n<div class=\"paragraph\">\n<p>For non root users, systemd controls access to its APIs via\n<a href=\"#privileges\">Policy Kit</a> and a user logged into Cockpit will have\nthe same permissions as they do from the command line.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit retrieves information about the host and changes the hostname\nvia the <code>hostnamed</code> daemon. To perform similar tasks from the command\nline use the\n<a href=\"https://www.freedesktop.org/software/systemd/man/hostnamectl.html\"><code>hostnamectl</code></a>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ hostnamectl\n   Static hostname: pink.example.com\n   Pretty hostname: Pink\n         Icon name: computer-desktop\n           Chassis: desktop\n        Machine ID: ef00b79be229463cbb844c3e715de96c\n           Boot ID: 934983d64d34465cb5a8383b5a89ad8c\n  Operating System: Fedora 22 (Twenty Two)\n       CPE OS Name: cpe:/o:fedoraproject:fedora:22\n            Kernel: Linux 4.0.4-301.fc22.x86_64\n      Architecture: x86-64</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit configures the system time and time zone via the <code>timedated</code>\ndaemon. To perform similar tasks from the command line use the\n<a href=\"https://www.freedesktop.org/software/systemd/man/timedatectl.html\"><code>timedatectl</code></a>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ timedatectl list-timezones\nAfrica/Abidjan\nAfrica/Accra\nAfrica/Addis_Ababa\nAfrica/Algiers\n...</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit can manage the list of NTP servers used by <code>systemd-timesyncd</code>\nby putting its own file into <code>/etc/systemd/timesyncd.conf.d/</code>. Note\nthat <code>systemd-timesyncd</code> is not always enabled, depending on the\nconfiguration of the machine. In that case, Cockpit disabled the UI for\nmanaging the list of NTP servers. In some cases use of <code>ntpd</code> can\ncause the <code>timedated</code> daemon to behave inconsistently with regards to\ntime synchronization.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit reboots or powers down the machine by using the\n<a href=\"https://www.freedesktop.org/software/systemd/man/shutdown.html\"><code>shutdown</code></a>\ncommand. To perform similar tasks from the command line, run it\ndirectly:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo shutdown +15\nShutdown scheduled for Sa 2015-09-26 15:49:40 CEST, use 'shutdown -c' to cancel.</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit manages system services and sockets via systemd. To perform\nsimilar tasks from the command line use the\n<a href=\"https://www.freedesktop.org/software/systemd/man/systemctl.html\"><code>systemctl</code></a>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ systemctl status cockpit\n● cockpit.service - Cockpit Web Service\n   Loaded: loaded (/usr/lib/systemd/system/cockpit.service; static; vendor preset: disabled)\n  Drop-In: /etc/systemd/system/cockpit.service.d\n           └─debug.conf\n   Active: active (running) since Sa 2015-09-26 13:28:02 CEST; 2h 7min ago\n     Docs: man:cockpit-ws(8)\n Main PID: 6957 (cockpit-ws)\n   Memory: 1.8M\n   CGroup: /system.slice/cockpit.service\n           ├─ 6957 /usr/libexec/cockpit-ws\n           └─29598 /usr/bin/ssh-agent</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>In order to customize who can perform various actions in system,\n<a href=\"#privileges-polkit\">create polkit rules</a> with the following actions\nand details:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>org.freedesktop.systemd1.manage-units</code></dt>\n<dd>\n<p>Permission to manage system services or other units. Details\navailable: <code>unit</code>, <code>verb</code></p>\n</dd>\n<dt class=\"hdlist1\"><code>org.freedesktop.systemd1.manage-unit-files</code></dt>\n<dd>\n<p>Permission to manage system services or other unit files.</p>\n</dd>\n<dt class=\"hdlist1\"><code>org.freedesktop.systemd1.reload-daemon</code></dt>\n<dd>\n<p>Permission to reload the systemd state.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>For example, placing the following polkit rule to\n<code>/etc/polkit-1/rules.d/10-http.rule</code> allows all users in the\n<code>operators</code> group start, stop, and restart the Apache HTTP service:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>polkit.addRule(function(action, subject) {\n    if (action.id == \"org.freedesktop.systemd1.manage-units\") {\n        if (subject.isInGroup(\"operators\") &amp;&amp; action.lookup(\"unit\") == \"httpd.service\") {\n            var verb = action.lookup(\"verb\");\n            if (verb == \"start\" || verb == \"stop\" || verb == \"restart\") {\n                return polkit.Result.YES;\n            }\n        }\n    }\n});</pre>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/feature-terminal.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Terminal</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"feature-terminal\" class=\"article\">\n<div id=\"header\">\n<h1>Terminal</h1>\n</div>\n<div id=\"content\">\n<div class=\"paragraph\">\n<p>Cockpit provides a standard shell in a terminal. This shell and the\nprocesses running in it have the <a href=\"#privileges\">same privileges</a> as if\nthe user had logged in via SSH.</p>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/feature-tuned.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Tuned Profiles</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"feature-tuned\" class=\"article\">\n<div id=\"header\">\n<h1>Tuned Profiles</h1>\n</div>\n<div id=\"content\">\n<div class=\"paragraph\">\n<p>If present on the system Cockpit can use Tuned and the DBUS API it\nprovides to set system performance profiles. To perform similar tasks\nfrom the command line, use the <code>tuned-adm</code> command.</p>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/feature-users.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>User Tools</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"feature-users\" class=\"article\">\n<div id=\"header\">\n<h1>User Tools</h1>\n</div>\n<div id=\"content\">\n<div class=\"paragraph\">\n<p>Cockpit uses the usual tools to create and modify local user accounts.\nExamples are <code>useradd</code>, <code>usermod</code> and <code>passwd</code>. These same tools\nare available for use on the command line.</p>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/features.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Feature Internals</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"features\" class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>Feature Internals</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#feature-systemd\">systemd</a></li>\n<li><a href=\"#feature-journal\">Journal</a></li>\n<li><a href=\"#feature-networkmanager\">NetworkManager</a></li>\n<li><a href=\"#feature-firewall\">Firewall</a></li>\n<li><a href=\"#feature-storaged\">storaged</a></li>\n<li><a href=\"#feature-users\">User Tools</a></li>\n<li><a href=\"#feature-realmd\">realmd</a></li>\n<li><a href=\"#feature-terminal\">Terminal</a></li>\n<li><a href=\"#feature-pcp\">PCP Metrics</a></li>\n<li><a href=\"#feature-machines\">Multiple Machines</a></li>\n<li><a href=\"#feature-selinux\">SELinux Policy</a></li>\n<li><a href=\"#feature-tuned\">Tuned Profiles</a></li>\n<li><a href=\"#feature-sosreport\">SOS Report</a></li>\n<li><a href=\"#feature-packagekit\">Package Updates</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"feature-systemd\">systemd</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit uses <a href=\"https://www.freedesktop.org/wiki/Software/systemd/\">systemd</a>\nand the DBus APIs it provides to configure and monitor core aspects of\nthe system. Use of alternate system APIs are not currently implemented.</p>\n</div>\n<div class=\"paragraph\">\n<p>For non root users, systemd controls access to its APIs via\n<a href=\"#privileges\">Policy Kit</a> and a user logged into Cockpit will have\nthe same permissions as they do from the command line.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit retrieves information about the host and changes the hostname\nvia the <code>hostnamed</code> daemon. To perform similar tasks from the command\nline use the\n<a href=\"https://www.freedesktop.org/software/systemd/man/hostnamectl.html\"><code>hostnamectl</code></a>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ hostnamectl\n   Static hostname: pink.example.com\n   Pretty hostname: Pink\n         Icon name: computer-desktop\n           Chassis: desktop\n        Machine ID: ef00b79be229463cbb844c3e715de96c\n           Boot ID: 934983d64d34465cb5a8383b5a89ad8c\n  Operating System: Fedora 22 (Twenty Two)\n       CPE OS Name: cpe:/o:fedoraproject:fedora:22\n            Kernel: Linux 4.0.4-301.fc22.x86_64\n      Architecture: x86-64</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit configures the system time and time zone via the <code>timedated</code>\ndaemon. To perform similar tasks from the command line use the\n<a href=\"https://www.freedesktop.org/software/systemd/man/timedatectl.html\"><code>timedatectl</code></a>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ timedatectl list-timezones\nAfrica/Abidjan\nAfrica/Accra\nAfrica/Addis_Ababa\nAfrica/Algiers\n...</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit can manage the list of NTP servers used by <code>systemd-timesyncd</code>\nby putting its own file into <code>/etc/systemd/timesyncd.conf.d/</code>. Note\nthat <code>systemd-timesyncd</code> is not always enabled, depending on the\nconfiguration of the machine. In that case, Cockpit disabled the UI for\nmanaging the list of NTP servers. In some cases use of <code>ntpd</code> can\ncause the <code>timedated</code> daemon to behave inconsistently with regards to\ntime synchronization.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit reboots or powers down the machine by using the\n<a href=\"https://www.freedesktop.org/software/systemd/man/shutdown.html\"><code>shutdown</code></a>\ncommand. To perform similar tasks from the command line, run it\ndirectly:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo shutdown +15\nShutdown scheduled for Sa 2015-09-26 15:49:40 CEST, use 'shutdown -c' to cancel.</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit manages system services and sockets via systemd. To perform\nsimilar tasks from the command line use the\n<a href=\"https://www.freedesktop.org/software/systemd/man/systemctl.html\"><code>systemctl</code></a>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ systemctl status cockpit\n● cockpit.service - Cockpit Web Service\n   Loaded: loaded (/usr/lib/systemd/system/cockpit.service; static; vendor preset: disabled)\n  Drop-In: /etc/systemd/system/cockpit.service.d\n           └─debug.conf\n   Active: active (running) since Sa 2015-09-26 13:28:02 CEST; 2h 7min ago\n     Docs: man:cockpit-ws(8)\n Main PID: 6957 (cockpit-ws)\n   Memory: 1.8M\n   CGroup: /system.slice/cockpit.service\n           ├─ 6957 /usr/libexec/cockpit-ws\n           └─29598 /usr/bin/ssh-agent</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>In order to customize who can perform various actions in system,\n<a href=\"#privileges-polkit\">create polkit rules</a> with the following actions\nand details:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>org.freedesktop.systemd1.manage-units</code></dt>\n<dd>\n<p>Permission to manage system services or other units. Details\navailable: <code>unit</code>, <code>verb</code></p>\n</dd>\n<dt class=\"hdlist1\"><code>org.freedesktop.systemd1.manage-unit-files</code></dt>\n<dd>\n<p>Permission to manage system services or other unit files.</p>\n</dd>\n<dt class=\"hdlist1\"><code>org.freedesktop.systemd1.reload-daemon</code></dt>\n<dd>\n<p>Permission to reload the systemd state.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>For example, placing the following polkit rule to\n<code>/etc/polkit-1/rules.d/10-http.rule</code> allows all users in the\n<code>operators</code> group start, stop, and restart the Apache HTTP service:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>polkit.addRule(function(action, subject) {\n    if (action.id == \"org.freedesktop.systemd1.manage-units\") {\n        if (subject.isInGroup(\"operators\") &amp;&amp; action.lookup(\"unit\") == \"httpd.service\") {\n            var verb = action.lookup(\"verb\");\n            if (verb == \"start\" || verb == \"stop\" || verb == \"restart\") {\n                return polkit.Result.YES;\n            }\n        }\n    }\n});</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"feature-journal\">Journal</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The systemd journal provides Cockpit with indexed log data. This log\ndata is found on the Journal page, as well as in various other places\nwhen configuring services, storage, networking etc.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit accesses Journal data via the\n<a href=\"https://www.freedesktop.org/software/systemd/man/journalctl.html\"><code>journalctl</code></a>\ncommand. Similar tasks can be performed at the command line:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo journalctl -f -u docker\n...</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"feature-networkmanager\">NetworkManager</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>If available on the system, Cockpit uses\n<a href=\"https://wiki.gnome.org/Projects/NetworkManager\">NetworkManager</a> and the\nDBus APIs it provides to interact with the system&#8217;s network\nconfiguration.</p>\n</div>\n<div class=\"paragraph\">\n<p>For non root users, NetworkManager controls access to its APIs via\n<a href=\"#privileges\">Policy Kit</a> and a user logged into Cockpit will have\nthe same permissions as they do from the command line.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use the\n<a href=\"https://fedoraproject.org/wiki/Networking/CLI\">nmcli</a> command:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ nmcli general status\nSTATE      CONNECTIVITY  WIFI-HW  WIFI     WWAN-HW  WWAN\nconnected  full          enabled  enabled  enabled  enabled</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Devices marked as \"not managed\" with the <code>NM_CONTROLLED=no</code> setting\nwill not be displayed in the interface.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"feature-firewall\">Firewall</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit uses <a href=\"https://www.firewalld.org\">firewalld</a> to interact with the\nsystem&#8217;s firewall. No firewall configuration UI will be shown if\nfirewalld is not installed.</p>\n</div>\n<div class=\"paragraph\">\n<p>Firewalld controls access to its APIs via PolicyKit. The user logged\ninto Cockpit needs to have the appropriate permissions to view or modify\nthe settings.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit can currently only show, add, and remove predefined firewalld\nservices in the default zone.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use\n<a href=\"https://www.firewalld.org/documentation/man-pages/firewall-cmd.html\">firewall-cmd</a>.\nFor example, to get the same list of allowed services that Cockpit\ndisplays:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo firewall-cmd --list-services\ndhcpv6-client samba-client mdns ssh cockpit</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>To enable an additional service, use:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ firewall-cmd --add-service pop3\nsuccess</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"feature-storaged\">storaged</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>If available on the system, Cockpit uses\n<a href=\"https://github.com/storaged-project/storaged/\"><code>storaged</code></a> to configure\nand monitor storage, disks, mounts etc. on the system. This\nfunctionality is present in the Cockpit <em>storaged</em> package.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>storaged</code> project is originally based on a project called\n<a href=\"https://www.freedesktop.org/wiki/Software/udisks/\"><code>udisks</code></a> and added\nsupport for many more features such as\n<a href=\"https://en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)\">LVM</a>,\n<a href=\"https://en.wikipedia.org/wiki/ISCSI\">iSCSI</a>,\n<a href=\"https://en.wikipedia.org/wiki/Linux_DM_Multipath\">Multipath</a>, and\n<a href=\"https://btrfs.wiki.kernel.org/index.php/Main_Page\">BTRFS</a>. The same tools\nand backwards compatible API are available between <code>storaged</code> and\n<code>udisks</code> the projects. Cockpit can use <code>udisks</code> but disables many of\nit&#8217;s storage related features, including updating <code>/etc/fstab</code> and\n<code>/etc/crypttab</code> for stability reasons.</p>\n</div>\n<div class=\"paragraph\">\n<p>For non root users, storaged controls access to its APIs via\n<a href=\"#privileges\">Policy Kit</a> and a user logged into Cockpit will have\nthe same permissions as they do from the command line.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use the <code>storagedctl</code>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ udisksctl dump\n...</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>To perform LVM tasks, you may use the various LVM commands, such as\n<code>vgcreate</code>, <code>lvresize</code> and so on. Cockpit will detect such changes\nmade at the command line.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit recognizes devices with multiple paths and can start the\n<code>multipathd</code> service in case it is not running. On the command line,\nyou can control multipath features with the <code>mpathconf</code>,\n<code>multipathd</code>, and <code>multipath</code> commands.</p>\n</div>\n<div class=\"paragraph\">\n<p>To manage iSCSI initiators from the command line, you can use\n<code>iscsiadm</code> and related tools.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"feature-users\">User Tools</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit uses the usual tools to create and modify local user accounts.\nExamples are <code>useradd</code>, <code>usermod</code> and <code>passwd</code>. These same tools\nare available for use on the command line.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"feature-realmd\">realmd</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>If available on the system, Cockpit uses\n<a href=\"https://www.freedesktop.org/software/realmd/\">realmd</a> and the DBus APIs\nit provides to configure the system&#8217;s Active Directory or IPA domain\nmembership.</p>\n</div>\n<div class=\"paragraph\">\n<p>Not all systems can join all kinds of domains. This depends on the\navailability of the necessary client software.</p>\n</div>\n<div class=\"paragraph\">\n<p>For non root users, realmd controls access to its APIs via\n<a href=\"#privileges\">Policy Kit</a> and a user logged into Cockpit will have\nthe same permissions as they do from the command line.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use the\n<a href=\"https://www.freedesktop.org/software/realmd/docs/realm.html\">realm</a>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ realm join example.com\nPassword for Administrator:</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><a href=\"http://www.freedesktop.org/software/realmd/\">realmd</a> sets up\ndomain-qualified user names by default, i. e. login user names look like\n&#8220;user@example.com&#8221;. For using unqualified names (just &#8220;user&#8221;),\nset the <code>fully-qualified-names</code> option in\n<a href=\"https://www.freedesktop.org/software/realmd/docs/realmd-conf.html\">/etc/realmd.conf</a>\nbefore joining a domain.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit requests an SSL certificate from the IPA server for\n<code>cockpit-ws</code> with the\n<a href=\"https://www.freeipa.org/page/Certmonger\">ipa-getcert</a> command.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"feature-terminal\">Terminal</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit provides a standard shell in a terminal. This shell and the\nprocesses running in it have the <a href=\"#privileges\">same privileges</a> as if\nthe user had logged in via SSH.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"feature-pcp\">PCP Metrics</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>If available, Cockpit uses the <a href=\"https://pcp.io/\">Performance Co-Pilot</a>\nframework to gather metrics data about the system. This data is used to\ndisplay the history graphs on the \"Metrics and history\" page. Cockpit\ncan use the PCP logging feature to display archived data about the\nsystem from a different point in time. If PCP is not available, then\nCockpit gathers the metrics data itself, but archival features are not\navailable.</p>\n</div>\n<div class=\"paragraph\">\n<p>Whether or not metrics are archived depends on whether the\n<a href=\"https://linux.die.net/man/1/pmlogger\"><code>pmlogger.service</code></a> systemd unit\nis running or not. The \"Enable PCP metrics collector\" button on the\nMetrics page will enable and start this service.</p>\n</div>\n<div class=\"paragraph\">\n<p>To see similar metrics data from the command line, you can use tools\nlike <a href=\"https://linux.die.net/man/1/pmstat\"><code>pmstat</code></a> or\n<a href=\"https://linux.die.net/man/1/pminfo\"><code>pminfo</code></a>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ pmstat\n@ Sat Sep 26 15:30:10 2015\n loadavg                      memory      swap        io    system         cpu\n   1 min   swpd   free   buff  cache   pi   po   bi   bo   in   cs  us  sy  id\n    4.19      0 20710m 605148  6450m    0    0    0 2548 5688  14K  19   3  76\n...</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>These metrics can also be exposed to other machines on a TCP port with\n<a href=\"https://linux.die.net/man/1/pmproxy\">pmproxy</a> and\n<a href=\"https://redis.io/\">Redis</a> or <a href=\"https://valkey.io/\">Valkey</a>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>systemctl enable --now redis pmproxy\n# if you use firewalld, open port 44322:\nfirewall-cmd --permanent --add-service pmproxy\nfirewall-cmd --reload</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This allows you to gather and visualize PCP metrics from multiple\nmachines with <a href=\"https://grafana.com/\">Grafana</a> and the\n<a href=\"https://grafana-pcp.readthedocs.io\">PCP Grafana plugin</a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"feature-machines\">Multiple Machines</h2>\n<div class=\"sectionbody\">\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>This feature is deprecated as of Cockpit 322.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit can connect to multiple machines from a single Cockpit session.\nThese are listed in the host switcher.</p>\n</div>\n<div class=\"paragraph\">\n<p>These additional machines are accessed via SSH from the machine that the\nfirst machine connected to, and are <a href=\"#authentication\">authenticated</a>\nwith the logged in user&#8217;s password and/or SSH keys.</p>\n</div>\n<div class=\"paragraph\">\n<p>SSH host keys are stored in <code>/etc/ssh/ssh_known_hosts</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The machine data is stored in <code>/etc/cockpit/machines.d/*.json</code>, or\nbelow <code>$XDG_CONFIG_DIRS</code> if set (see\n<a href=\"./cockpit.conf.5.html\">cockpit.conf</a>). Settings in lexicographically\nlater files amend or override settings in earlier ones. Cockpit itself\nwrites into <code>99-webui.json</code>; packages or admins who want to\npre-configure machines should ship files like <code>05-mymachine.json</code> so\nthat changes from the web interface override the pre-configured files.</p>\n</div>\n<div class=\"paragraph\">\n<p>Each JSON file contains an object that maps machine IDs to objects that\ndefine the properties of that machine. The ID can be a human readable\nname or an IP address or any other unique value, and is shown in the web\ninterface until connecting to it the first time, at which point the web\ninterface will show the machine&#8217;s host name.</p>\n</div>\n<div class=\"paragraph\">\n<p>The following properties are recognized:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"address\"</code></dt>\n<dd>\n<p><em>(string, mandatory)</em> IP address or DNS name of the machine</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"visible\"</code></dt>\n<dd>\n<p><em>(boolean, optional)</em> If <code>true</code>, the machine will be displayed and\navailable for managing with Cockpit. If <code>false</code> (the default), it\nwill not be displayed, but still taken into account for type-ahead\nsearch when adding new machines in the web interface.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"user\"</code></dt>\n<dd>\n<p><em>(string, optional)</em> User name on the remote machine. When not given,\nCockpit will default to the user name that was being used to log into\nCockpit itself.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"port\"</code></dt>\n<dd>\n<p><em>(integer, optional)</em> ssh port of the remote machine. When not given,\nthe default port 22 is used.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"color\"</code></dt>\n<dd>\n<p><em>(string, optional)</em> Color to assign to the machine label in the web\ninterface. This can be either given as\n<code>rgb(r_value, g_value, b_value)</code> with each value being an integer\nbetween 0 and 255, or as a color name like <code>yellow</code>. When not given,\nCockpit will assign an unused color automatically.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Example:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n    \"web server\": {\n        \"address\": \"192.168.2.4\",\n        \"visible\": true,\n        \"color\": \"rgb(100, 200, 0)\",\n        \"user\": \"admin\"\n    },\n    \"192.168.2.1\": {\n        \"address\": \"192.168.2.1\",\n        \"port\": 2222,\n        \"visible\": true,\n        \"color\": \"green\"\n    }\n}</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"feature-selinux\">SELinux Policy</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>If present on the system Cockpit can set the SELinux mode to enforcing\nor permissive. It can also use <code>setroubleshootd</code> to show audit issues\nand apply suggested fixes.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line use the <code>setenforce</code>\nand <code>sealert</code> tools.</p>\n</div>\n<div class=\"paragraph\">\n<p>To clear out all the information that <code>setroubleshootd</code> tracks, you\ncan use a commands like:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo killall setroubleshootd\n$ sudo rm -rf /var/lib/setroubleshoot/*</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"feature-tuned\">Tuned Profiles</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>If present on the system Cockpit can use Tuned and the DBUS API it\nprovides to set system performance profiles. To perform similar tasks\nfrom the command line, use the <code>tuned-adm</code> command.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"feature-sosreport\">SOS Report</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>If present on the system Cockpit can use <code>sosreport</code> to collect system\nconfiguration and diagnostic information.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use the <code>sosreport</code>\ncommand.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"feature-packagekit\">Package Updates</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit uses the\n<a href=\"https://www.freedesktop.org/software/PackageKit/gtk-doc/api-reference.html\">PackageKit</a>\nD-Bus API to get information about available package updates and to\napply them, in an Operating System independent manner.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use the\n<a href=\"https://www.freedesktop.org/software/PackageKit/pk-using.html\">pkcon</a>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ pkcon refresh\n\n$ pkcon get-updates\nAvailable  sudo-1.8.20p2-1.fc26.x86_64 (updates-testing)\n    Allows restricted root access for specified users\nAvailable  vim-filesystem-2:8.0.617-1.fc26.x86_64 (updates-testing)\n    VIM filesystem layout\nAvailable  vim-minimal-2:8.0.617-1.fc26.x86_64 (updates-testing)\n    A minimal version of the VIM editor\n\n$ pkcon get-update-detail sudo\nDetails about the update:6.x86_64 [fedora]\n Package: sudo-1.8.20p2-1.fc26.x86_64\n Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1452941\n Update text: - update to 1.8.20p2\n    - added sudo package to dnf/yum protected packages\n\n$ pkcon update\nThe following packages have to be updated:\n sudo-1.8.20p2-1.fc26.x86_64    Allows restricted root access for specified users\n vim-filesystem-2:8.0.617-1.fc26.x86_64 VIM filesystem layout\n vim-minimal-2:8.0.617-1.fc26.x86_64    A minimal version of the VIM editor\nProceed with changes? [N/y] y\n[...]</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Of course you can also use your Operating System specific commands for\nthat, such as <code>dnf updateinfo info</code> on Fedora or <code>sudo apt upgrade</code>\non Debian.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/https.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>SSL/TLS Usage</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"https\" class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>SSL/TLS Usage</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#https-required\">HTTPS Requirement</a></li>\n<li><a href=\"#https-certificates\">Certificates</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit usually requires that web browsers communicate with it using\nHTTPS, for security reasons.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"https-required\">HTTPS Requirement</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit listens for both HTTP and HTTPS connections on the same port, by\ndefault 9090. If an HTTP connection is made, Cockpit will redirect that\nconnection to HTTPS. There are some exceptions:</p>\n</div>\n<div class=\"ulist\">\n<ul>\n<li>\n<p>If an HTTP connection comes from <code>localhost</code> (<code>127.0.0.1</code> or\n<code>::1</code>, then Cockpit will allow communication without redirecting to\nHTTPS.</p>\n</li>\n<li>\n<p>Certain URLs, like <code>/ping</code> are not required to use HTTPS.</p>\n</li>\n</ul>\n</div>\n<div class=\"paragraph\">\n<p>This behavior can be overridden by setting the <code>AllowUnencrypted</code>\noption in <code>cockpit.conf</code>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"https-certificates\">Certificates</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit will load a certificate from the <code>/etc/cockpit/ws-certs.d</code>,\ndirectory, or below <code>$XDG_CONFIG_DIRS</code> if set (see\n<a href=\"./cockpit.conf.5.html\">cockpit.conf</a>). It will use the last file\nwith a <code>.cert</code> or <code>.crt</code> extension in alphabetical order. The file\nshould contain one or more OpenSSL style <code>BEGIN CERTIFICATE</code> blocks\nfor the server certificate and the intermediate certificate authorities.</p>\n</div>\n<div class=\"paragraph\">\n<p>The private key must be contained in a separate file with the same name\nas the certificate, but with a <code>.key</code> suffix instead. The key must not\nbe encrypted.</p>\n</div>\n<div class=\"paragraph\">\n<p>If no certificate is found, a self-signed certificate is created and\nstored in the <code>0-self-signed.cert</code> file. On some platforms, Cockpit\nwill also generate a ca.crt in that directory, which may be safely\nimported into client browsers.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit will read the files as root, so they can have tight permissions.</p>\n</div>\n<div class=\"paragraph\">\n<p>To check which certificate <code>cockpit-ws</code> will use run the following\ncommand.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo /usr/libexec/cockpit-certificate-ensure --check</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Or, on Debian-based systems:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo /usr/lib/cockpit/cockpit-certificate-ensure --check</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If using <code>certmonger</code> to manage certificates, following command can be\nused to automatically prepare a certificate/key file pair:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>getcert request -f /etc/cockpit/ws-certs.d/50-certmonger.cert \\\n                -k /etc/cockpit/ws-certs.d/50-certmonger.key \\\n                -D myhostname.example.com \\\n                [--ca=...]</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This will not work on Red Hat Enterprise Linux 8 by default. Adjust the\nSELinux type of the certificate directory to <code>cert_t</code> to allow\ncertmonger to write its certificates there:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>semanage fcontext -a -t cert_t '/etc/cockpit/ws-certs\\.d(/.*)?'\nrestorecon -v /etc/cockpit/ws-certs.d</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/index.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Cockpit documentation</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>Cockpit documentation</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#guide\">Deployment Guide</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#cockpit-manual\">Manual pages</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#_cockpit1\">cockpit(1)</a></li>\n<li><a href=\"#_cockpit_conf5\">cockpit.conf(5)</a></li>\n<li><a href=\"#_cockpit_ws8\">cockpit-ws(8)</a></li>\n<li><a href=\"#_cockpit_tls8\">cockpit-tls(8)</a></li>\n<li><a href=\"#_cockpit_desktop1\">cockpit-desktop(1)</a></li>\n<li><a href=\"#_cockpit_bridge1\">cockpit-bridge(1)</a></li>\n<li><a href=\"#_pam_ssh_add8\">pam_ssh_add(8)</a></li>\n</ul>\n</li>\n<li><a href=\"#https\">SSL/TLS Usage</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#https-required\">HTTPS Requirement</a></li>\n<li><a href=\"#https-certificates\">Certificates</a></li>\n</ul>\n</li>\n<li><a href=\"#listen\">TCP Port and Address</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#listen-systemd\">Cockpit systemd Socket</a></li>\n<li><a href=\"#listen-selinux\">SELinux Port</a></li>\n<li><a href=\"#listen-firewalld\">Firewalld Port</a></li>\n</ul>\n</li>\n<li><a href=\"#startup\">Start up</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#startup-shutdown\">Process exit</a></li>\n<li><a href=\"#startup-boot\">Boot start up</a></li>\n</ul>\n</li>\n<li><a href=\"#multi-host\">Managing multiple hosts at the same time</a></li>\n<li><a href=\"#authentication\">Cockpit Authentication</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#initial-auth\">Directly logging into the primary server</a></li>\n<li><a href=\"#direct-secondary-auth\">Directly logging into a secondary server without a primary session</a></li>\n<li><a href=\"#secondary-auth\">Logging into a secondary server from the primary session</a></li>\n</ul>\n</li>\n<li><a href=\"#sso\">Single Sign On</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#sso-server\">Server Requirements</a></li>\n<li><a href=\"#sso-client\">Client Requirements</a></li>\n</ul>\n</li>\n<li><a href=\"#cert-authentication\">Certificate/smart card authentication</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#certauth-server-cert-generation\">User certificate generation</a></li>\n<li><a href=\"#certauth-server-ipa\">Certificate mapping with FreeIPA</a></li>\n<li><a href=\"#certauth-server-ms-ad\">Certificate mapping with Microsoft Active Directory</a></li>\n<li><a href=\"#certauth-server-samba-ad\">Certificate mapping with Samba Active Directory</a></li>\n<li><a href=\"#certauth-server-cockpitconf\">Cockpit web server configuration</a></li>\n<li><a href=\"#certauth-server-resourcelimits\">Cockpit web server resource limits</a></li>\n<li><a href=\"#certauth-forwarding\">Authentication to other services like sudo and ssh</a></li>\n</ul>\n</li>\n<li><a href=\"#privileges\">Privileges and Permissions</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#privileges-polkit\">Customizing Polkit Privileges</a></li>\n</ul>\n</li>\n</ul>\n</li>\n<li><a href=\"#features\">Feature Internals</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#feature-systemd\">systemd</a></li>\n<li><a href=\"#feature-journal\">Journal</a></li>\n<li><a href=\"#feature-networkmanager\">NetworkManager</a></li>\n<li><a href=\"#feature-firewall\">Firewall</a></li>\n<li><a href=\"#feature-storaged\">storaged</a></li>\n<li><a href=\"#feature-users\">User Tools</a></li>\n<li><a href=\"#feature-realmd\">realmd</a></li>\n<li><a href=\"#feature-terminal\">Terminal</a></li>\n<li><a href=\"#feature-pcp\">PCP Metrics</a></li>\n<li><a href=\"#feature-machines\">Multiple Machines</a></li>\n<li><a href=\"#feature-selinux\">SELinux Policy</a></li>\n<li><a href=\"#feature-tuned\">Tuned Profiles</a></li>\n<li><a href=\"#feature-sosreport\">SOS Report</a></li>\n<li><a href=\"#feature-packagekit\">Package Updates</a></li>\n</ul>\n</li>\n<li><a href=\"#development\">Developer Guide</a>\n<ul class=\"sectlevel2\">\n<li><a href=\"#embedding\">Embedding and Integrating Cockpit</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#embedding-full\">Embedding the Cockpit Interface</a></li>\n<li><a href=\"#embedding-components\">Integrating Cockpit Components into Web Applications</a></li>\n<li><a href=\"#embedding-deep\">Deep Integration</a></li>\n<li><a href=\"#embedding-cors\">Pinging Cockpit</a></li>\n</ul>\n</li>\n<li><a href=\"#packages\">Cockpit Packages</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#package-layout\">Layout of Package Files</a></li>\n<li><a href=\"#_package_manifest\">Package Manifest</a></li>\n<li><a href=\"#package-manifest-override\">Manifest overrides</a></li>\n<li><a href=\"#package-links\">Package Links and Paths</a></li>\n<li><a href=\"#package-minified\">Content Negotiation</a></li>\n<li><a href=\"#package-api\">Using Cockpit API</a></li>\n<li><a href=\"#package-bridges\">Bridges for specific tasks</a></li>\n<li><a href=\"#package-replace\">Replacing an existing package</a></li>\n</ul>\n</li>\n<li><a href=\"#urls\">Cockpit URLs</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#urls-components\">Component URLs</a></li>\n<li><a href=\"#urls-visible\">Visible URLs</a></li>\n</ul>\n</li>\n<li><a href=\"#_api_base1\">API: base1</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#_cockpit_js\">cockpit.js</a></li>\n<li><a href=\"#_cockpit_js_object_caching\">cockpit.js: Object Caching</a></li>\n<li><a href=\"#_cockpit_js_raw_channels\">cockpit.js: Raw Channels</a></li>\n<li><a href=\"#_cockpit_js_dbus_client\">cockpit.js: DBus Client</a></li>\n<li><a href=\"#_cockpit_js_errors\">cockpit.js: Errors</a></li>\n<li><a href=\"#_cockpit_js_file_access\">cockpit.js: File Access</a></li>\n<li><a href=\"#_cockpit_js_http_client\">cockpit.js: HTTP Client</a></li>\n<li><a href=\"#_cockpit_js_localization\">cockpit.js: Localization</a></li>\n<li><a href=\"#_cockpit_js_page_location_and_jumping\">cockpit.js: Page Location and Jumping</a></li>\n<li><a href=\"#_cockpit_js_user_session\">cockpit.js: User Session</a></li>\n<li><a href=\"#_cockpit_js_manifests\">cockpit.js: Manifests</a></li>\n<li><a href=\"#_cockpit_js_metrics\">cockpit.js: Metrics</a></li>\n<li><a href=\"#_cockpit_js_series_data\">cockpit.js: Series Data</a></li>\n<li><a href=\"#_cockpit_js_spawning_processes\">cockpit.js: Spawning Processes</a></li>\n<li><a href=\"#_cockpit_js_utilities\">cockpit.js: Utilities</a></li>\n</ul>\n</li>\n<li><a href=\"#_api_shell\">API: shell</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#_index_html\">index.html</a></li>\n</ul>\n</li>\n<li><a href=\"#_api_system\">API: system</a>\n<ul class=\"sectlevel3\">\n<li><a href=\"#_logs_html\">logs.html</a></li>\n<li><a href=\"#_terminal_html\">terminal.html</a></li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"guide\">Deployment Guide</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Documentation for Cockpit 362.</p>\n</div>\n<div class=\"paragraph\">\n<p>Latest version <a href=\"https://cockpit-project.org/guide/latest\">available here</a>.</p>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cockpit-manual\">Manual pages</h3>\n<div class=\"sect3\">\n<h4 id=\"_cockpit1\">cockpit(1)</h4>\n<div class=\"sect4\">\n<h5 id=\"_name\">Name</h5>\n<div class=\"paragraph\">\n<p>cockpit - Cockpit</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_description\">Description</h5>\n<div class=\"paragraph\">\n<p>Cockpit is a web accessible interactive admin interface for Linux\nmachines. Cockpit can usually be accessed on port <code>9090</code> of the\nmachine it&#8217;s installed on. Cockpit starts on demand. Use your system\ncredentials to log in.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_components\">Components</h5>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-ws</strong> web service listens on port <code>9090</code> and is started\non demand by <strong>systemd</strong>. The Cockpit web service authenticates the\nuser, loads Cockpit into the browser, and starts <strong>cockpit-bridge</strong> in a\nLinux user session.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-bridge</strong> provides Cockpit in the web browser with access\nto the system APIs. It does this over its standard in and standard out.\nThe bridge is started like a shell once per Linux user session.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_bugs\">Bugs</h5>\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_author\">Author</h5>\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_see_also\">See also</h5>\n<div class=\"paragraph\">\n<p><strong>cockpit-tls(8)</strong> , <strong>cockpit.bridge(1)</strong> , <strong>systemd(1)</strong>, <strong><a href=\"https://cockpit-project.org/guide/latest\">Cockpit guide</a></strong></p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_conf5\">cockpit.conf(5)</h4>\n<div class=\"sect4\">\n<h5 id=\"_name_2\">Name</h5>\n<div class=\"paragraph\">\n<p>cockpit.conf - Cockpit configuration file</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_description_2\">Description</h5>\n<div class=\"paragraph\">\n<p>Cockpit can be configured via /etc/cockpit/cockpit.conf. If\n<strong>$XDG_CONFIG_DIRS</strong> is set, then the first path containing a\n<strong>../cockpit/cockpit.conf</strong> is used instead. Other configuration files\nand directories are searched for in the same way.</p>\n</div>\n<div class=\"paragraph\">\n<p>This file is not required and may need to be created manually. The file\nhas a INI file syntax and thus contains key / value pairs, grouped into\ntopical groups. See the examples below for details.</p>\n</div>\n<div class=\"paragraph\">\n<p>Note: The port that cockpit listens on cannot be changed in this file.\nTo change the port change the systemd <strong>cockpit.socket</strong> file.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_webservice\">WebService</h5>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>Origins</strong></dt>\n<dd>\n<p>By default cockpit will not accept crossdomain websocket connections.\nUse this setting to allow access from alternate domains. Origins\nshould include scheme, host and port, if necessary. Wildcards and glob\nexpressions are permitted. IPv6 addresses must have their brackets escaped\nwith backslashes (e.g. <code>\\[::1\\]</code>) as they are matched using <code>fnmatch()</code>.\n<br></p>\n</dd>\n</dl>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-ini\" data-lang=\"ini\">[WebService]\nOrigins = https://somedomain1.com https://somedomain2.com:9090 https://*.somedomain3.com https://\\[::1\\]:9090</code></pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>ProtocolHeader</strong></dt>\n<dd>\n<p>Configure cockpit to look at the contents of this header to determine\nif a connection is using tls. This should only be used when cockpit is\nbehind a reverse proxy, and care should be taken to make sure that\nincoming requests cannot set this header.\n<br></p>\n</dd>\n</dl>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-ini\" data-lang=\"ini\">[WebService]\nProtocolHeader = X-Forwarded-Proto</code></pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>ForwardedForHeader</strong></dt>\n<dd>\n<p>Configure cockpit to look at the contents of this header to determine\nthe real origin of a connection. This should only be used when cockpit\nis behind a reverse proxy, and care should be taken to make sure that\nincoming requests cannot set this header.\n<br></p>\n</dd>\n</dl>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-ini\" data-lang=\"ini\">[WebService]\nForwardedForHeader = X-Forwarded-For</code></pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>LoginTitle</strong></dt>\n<dd>\n<p>Set the browser title for the login screen.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>LoginTo</strong></dt>\n<dd>\n<p>When set to <code>true</code> the <em>Connect to</em> option on the login screen is\nvisible and allows logging into another server. When set to <code>false</code>,\ndirect remote logins are disallowed. If this option is not specified\nthen it will be automatically detected based on whether the\n<strong>cockpit-bridge</strong> package is installed and the <strong>ssh</strong> program is\navailable.<br>\n<br>\nIf cockpit-ws is exposed to the public internet, and also has access\nto a private internal network, it is recommended to explicitly set\n<strong>LoginTo=false</strong>. This prevents unauthenticated remote attackers from\nscanning the internal network for existing machines and open ports.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>RequireHost</strong></dt>\n<dd>\n<p>When set to <code>true</code> cockpit will require users to use the <em>Connect\nto</em> option to specify the host to log into.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>AllowMultiHost</strong></dt>\n<dd>\n<p>When set to <code>true</code>, cockpit will allow users to connect to multiple\nhosts in one session. The default is OS specific.<br>\n<br>\nWhen connecting to multiple servers, JavaScript runs without\nisolation. All systems will be vulnerable to potential attacks from\nother connected hosts. Enable this option <em>only</em> when all hosts are\ntrusted.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>MaxStartups</strong></dt>\n<dd>\n<p>Same as the <strong>sshd</strong> configuration option by the same name. Specifies\nthe maximum number of concurrent login attempts allowed. Additional\nconnections will be dropped until authentication succeeds or the\nconnections are closed. Defaults to 10.<br>\n<br>\nAlternatively, random early drop can be enabled by specifying the\nthree colon separated values <strong>start:rate:full</strong> (e.g. \"10:30:60\").\nCockpit will start refusing authentication attempts with a probability\nof <strong>rate/100</strong> (30%) if there are currently <strong>start</strong> (10)\nunauthenticated connections. The probability increases linearly and\nall connection attempts are refused if the number of unauthenticated\nconnections reaches <strong>full</strong> (60).</p>\n</dd>\n<dt class=\"hdlist1\"><strong>AllowUnencrypted</strong></dt>\n<dd>\n<p>If true, cockpit will accept unencrypted HTTP connections. Otherwise,\nit redirects all HTTP connections to HTTPS. Exceptions are connections\nfrom localhost and for certain URLs (like <strong>/ping</strong>). Defaults to\nfalse.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>UrlRoot</strong></dt>\n<dd>\n<p>The root URL where you will be serving cockpit. When provided cockpit\nwill expect all requests to be prefixed with the given url. This is\nmostly useful when you are using cockpit behind a reverse proxy, such\nas nginx. <code>/cockpit/</code> and <code>/cockpit+</code> are reserved and should not\nbe used. For example <code>/cockpit-new/</code> is ok. <code>/cockpit/</code> and\n<code>/cockpit+new/</code> are not.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>ClientCertAuthentication</strong></dt>\n<dd>\n<p>If true, enable TLS client certificates for authenticating users.\nCommonly these are provided by a smart card, but it&#8217;s equally possible\nto import certificates directly into the web browser. Please see the\n<a href=\"https://cockpit-project.org/guide/latest/cert-authentication.html\">Certificate/smart\ncard authentication</a> section in the Cockpit guide for details.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>Shell</strong></dt>\n<dd>\n<p>The relative URL to top level component to display in Cockpit once\nlogged in. Defaults to <code>/shell/index.html</code></p>\n</dd>\n<dt class=\"hdlist1\"><strong>CustomLoginPage</strong></dt>\n<dd>\n<p>Load the login page from an alternative directory. The directory must\ncontain a <code>login.html</code> and optionally a <code>po.js</code> file for translations.\nWhen not set, the hardcoded <code>$prefix/share/cockpit/static</code> directory is used.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_log\">Log</h5>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>Fatal</strong></dt>\n<dd>\n<p>The kind of log messages in the bridge to treat as fatal. Separate\nmultiple values with spaces. Relevant values are: <strong>criticals</strong> and\n<strong>warnings</strong>.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_oauth\">OAuth</h5>\n<div class=\"paragraph\">\n<p>Cockpit can be configured to support the\n<a href=\"https://tools.ietf.org/html/rfc6749#section-4.2\">implicit grant</a> OAuth\nauthorization flow. When successful the resulting oauth token will be\npassed to cockpit-ws using the <strong>Bearer</strong> auth-scheme. For a login to be\nsuccessful, cockpit will also need a to be configured to verify and\nallow <strong>Bearer</strong> tokens.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>URL</strong></dt>\n<dd>\n<p>This is the url that cockpit will redirect the users browser to when\nit needs to obtain an oauth token. Cockpit will add a redirect_uri\nparameter to the url with the location of where the oauth provider\nshould redirect to once a token has been obtained.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>ErrorParam</strong></dt>\n<dd>\n<p>When a oauth provider redirects a user back to cockpit, look for this\nparameter in the querystring or fragment portion of the url to find a\nerror message. When not provided it will default to\n<strong>error_description</strong></p>\n</dd>\n<dt class=\"hdlist1\"><strong>TokenParam</strong></dt>\n<dd>\n<p>When a oauth provider redirects a user back to cockpit, look for this\nparameter in the querystring or fragment portion of the url to find\nthe access token. When not provided it will default to\n<strong>access_token</strong></p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_session\">Session</h5>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>Banner</strong></dt>\n<dd>\n<p>The contents of the specified file (commonly <strong>/etc/issue</strong>) are shown\non the login page. By default, no banner is displayed.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>IdleTimeout</strong></dt>\n<dd>\n<p>Time in minutes after which session expires and user is logged out if\nno user action has been performed in the given time. This idle timeout\nonly applies to interactive password logins. With non-interactive\nauthentication methods like Kerberos, OAuth, or certificate login, the\nbrowser cannot forget credentials, and thus automatic logouts are not\nuseful for protecting credentials of forgotten sessions. Set to <strong>0</strong>\nto disable session timeout.\n<br></p>\n</dd>\n</dl>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-ini\" data-lang=\"ini\">[Session]\nIdleTimeout=15</code></pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"></dt>\n<dd>\n<p>When not specified, there is no idle timeout by default.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>WarnBeforeConnecting</strong></dt>\n<dd>\n<p>Whether to warn before connecting to remote hosts from the Shell.\nDefaults to true.\n<br></p>\n</dd>\n</dl>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-ini\" data-lang=\"ini\">[Session]\nWarnBeforeConnecting=false</code></pre>\n</div>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_bugs_2\">Bugs</h5>\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_author_2\">Author</h5>\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_see_also_2\">See also</h5>\n<div class=\"paragraph\">\n<p><strong>cockpit-ws(8)</strong>, <strong>cockpit-tls(8)</strong></p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_ws8\">cockpit-ws(8)</h4>\n<div class=\"sect4\">\n<h5 id=\"_name_3\">Name</h5>\n<div class=\"paragraph\">\n<p>cockpit-ws - Cockpit web service</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_synopsis\">Synopsis</h5>\n<div class=\"paragraph\">\n<p><strong>cockpit-ws</strong> [<strong>--help</strong>] [<strong>--port</strong> <em>PORT</em>] [<strong>--address</strong> <em>ADDRESS</em>] [<strong>--no-tls</strong>]\n\t\t\t [<strong>--for-tls-proxy</strong>] [<strong>--local-ssh</strong>] [<strong>--local-session</strong> <em>BRIDGE</em>]</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_description_3\">Description</h5>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-ws</strong> program is the web service component used for\ncommunication between the browser application and various configuration\ntools and services like <strong>cockpit-bridge(1)</strong>.</p>\n</div>\n<div class=\"paragraph\">\n<p>Users or administrators should never need to start this program as it\nautomatically started by <strong>systemd(1)</strong> on bootup, through\n<strong>cockpit-tls(8)</strong>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_transport_security\">Transport security</h5>\n<div class=\"paragraph\">\n<p><strong>cockpit-ws</strong> is normally run behind the <strong>cockpit-tls</strong> TLS\nterminating proxy, and only deals with unencrypted HTTP by itself. But\nfor backwards compatibility it can also handle TLS connections by itself\nwhen being run directly. For details how to configure certificates,\nplease refer to the <strong>cockpit-tls(8)</strong> documentation.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_timeout\">Timeout</h5>\n<div class=\"paragraph\">\n<p>When started via <strong>systemd(1)</strong> then <strong>cockpit-ws</strong> will exit after 90\nseconds if nobody logs in, or after the last user is disconnected.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_options\">Options</h5>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>--help</strong></dt>\n<dd>\n<p>Show help options.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--port</strong> <em>PORT</em></dt>\n<dd>\n<p>Serve HTTP requests <em>PORT</em> instead of port <strong>9090</strong>. Usually Cockpit is\nstarted on demand by <strong>systemd</strong> socket activation, and this option\nhas no effect. Update the <strong>ListenStream</strong> directive\n<strong>cockpit.socket</strong> file in the usual <strong>systemd</strong> manner.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--address</strong> <em>ADDRESS</em></dt>\n<dd>\n<p>Bind to address <em>ADDRESS</em> instead of binding to all available\naddresses. Usually Cockpit is started on demand by <strong>systemd</strong> socket\nactivation, and this option has no effect. In that case, update the\n<strong>ListenStream</strong> directive in the <strong>cockpit.socket</strong> file in the usual\n<strong>systemd</strong> manner.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--no-tls</strong></dt>\n<dd>\n<p>Disable http to https redirection.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--for-tls-proxy</strong></dt>\n<dd>\n<p>Tell <strong>cockpit-ws</strong> that it is running behind a local reverse proxy\nthat does the TLS termination. Then Cockpit puts https:// URLs into\nthe default <strong>Content-Security-Policy</strong>, and accepts only https://\norigins, instead of http: ones by default. However, if <strong>Origins</strong> is\nset in the <strong>cockpit.conf(5)</strong> configuration file, it will override\nthis default.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--local-ssh</strong></dt>\n<dd>\n<p>Normally <strong>cockpit-ws</strong> uses <strong>cockpit-session</strong> and PAM to\nauthenticate the user and start a user session. With this option\nenabled, it will instead authenticate via SSH at <strong>127.0.0.1</strong> port\n<strong>22</strong>.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--local-session</strong> <em>BRIDGE</em></dt>\n<dd>\n<p>Skip all authentication and <strong>cockpit-session</strong>, and launch the\n<strong>cockpit-bridge</strong> specified in <em>BRIDGE</em> in the local session. If the\n<em>BRIDGE</em> is specified as <code>-</code> then expect an already running bridge\nthat is connected to stdin and stdout of this <strong>cockpit-ws</strong> process.\nThis allows the web server to run as any unprivileged user in an\nalready running session.<br>\n<br>\nThis mode implies <strong>--no-tls</strong>, thus you need to use http:// URLs with\nthis.</p>\n</dd>\n</dl>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>With <strong>--local-session</strong> <em>BRIDGE</em>, you <em>have to isolate the opened TCP port</em> somehow\n(for example in a network namespace), otherwise all other users (or\neven remote machines if the port is not just listening on localhost)\ncan access the session!</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_environment\">Environment</h5>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-ws</strong> process will use the <strong>XDG_CONFIG_DIRS</strong> environment\nvariable from the\n<a href=\"https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html\">XDG\nbasedir spec</a> to find its <strong>cockpit.conf(5)</strong> configuration file.</p>\n</div>\n<div class=\"paragraph\">\n<p>In addition the <strong>XDG_DATA_DIRS</strong> environment variable from the\n<a href=\"https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html\">XDG\nbasedir spec</a> can be used to override the location to serve static files\nfrom. These are the files that are served to a non-logged in user.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_bugs_3\">Bugs</h5>\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_author_3\">Author</h5>\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_see_also_3\">See also</h5>\n<div class=\"paragraph\">\n<p><strong>cockpit-tls(8)</strong> , <strong>cockpit.conf(5)</strong> , <strong>systemd(1)</strong></p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_tls8\">cockpit-tls(8)</h4>\n<div class=\"sect4\">\n<h5 id=\"_name_4\">Name</h5>\n<div class=\"paragraph\">\n<p>cockpit-tls - TLS proxy for Cockpit web service</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_synopsis_2\">Synopsis</h5>\n<div class=\"paragraph\">\n<p><strong>cockpit-tls</strong> [<strong>--help</strong>] [<strong>--port</strong> <em>PORT</em>] [<strong>--no-tls</strong>] [<strong>--idle-timeout</strong> <em>SECONDS</em>]</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_description_4\">Description</h5>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-tls</strong> program is a TLS terminating HTTP proxy for\n<strong>cockpit-ws(8)</strong>. It manages a set of isolated cockpit-ws instances,\none per TLS client certificate, plus one for TLS without a client\ncertificate, and one for unencrypted HTTP. With that, one session cannot\ntamper with another one through possible security vulnerability\nexploits.</p>\n</div>\n<div class=\"paragraph\">\n<p>Users or administrators should never need to start this program as it\nautomatically started by <strong>systemd(1)</strong> via socket activation.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_transport_security_2\">Transport security</h5>\n<div class=\"paragraph\">\n<p>To specify the TLS certificate the web service should use, simply drop a\nfile with the extension <strong>.cert</strong> in the <strong>/etc/cockpit/ws-certs.d</strong>\ndirectory, or below <strong>$XDG_CONFIG_DIRS</strong> if set (see\n<a href=\"./cockpit.conf.5.html\">cockpit.conf</a>). If there are multiple files\nin this directory, then the highest priority one is chosen after\nsorting.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <strong>.cert</strong> file should contain at least two OpenSSL style PEM blocks.\nFirst one or more <code>BEGIN CERTIFICATE</code> blocks for the server\ncertificate and intermediate certificate authorities and a second one\ncontaining a <code>BEGIN PRIVATE KEY</code> or similar. The key must not be\nencrypted.</p>\n</div>\n<div class=\"paragraph\">\n<p>If there is no TLS certificate, a self-signed certificate is\nautomatically generated using <strong>sscg</strong> (if available) or <strong>openssl</strong> and\nstored in the <strong>0-self-signed.cert</strong> file.</p>\n</div>\n<div class=\"paragraph\">\n<p>When enrolling into a FreeIPA domain, an SSL certificate is requested\nfrom the IPA server and stored in <strong>10-ipa.cert</strong>.</p>\n</div>\n<div class=\"paragraph\">\n<p>To check which certificate <strong>cockpit-ws</strong> will use, run the following\ncommand.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo /usr/libexec/cockpit-certificate-ensure --check</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Or, on Debian-based systems:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo /usr/lib/cockpit/cockpit-certificate-ensure --check</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If using <strong>certmonger</strong> to manage certificates, following command can be\nused to generate a certificate/key pair:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>CERT_FILE=/etc/cockpit/ws-certs.d/50-certmonger.crt\nKEY_FILE=/etc/cockpit/ws-certs.d/50-certmonger.key\n\ngetcert request -f ${CERT_FILE} -k ${KEY_FILE} -D $(hostname --fqdn)</pre>\n</div>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_options_2\">Options</h5>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>--help</strong></dt>\n<dd>\n<p>Show help options.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--port</strong> <em>PORT</em></dt>\n<dd>\n<p>Serve HTTP requests on <em>PORT</em> instead of port 9090. Usually Cockpit is\nstarted on demand by <strong>systemd</strong> socket activation, and this option\nhas no effect. Update the <strong>ListenStream</strong> directive\n<strong>cockpit.socket</strong> file in the usual <strong>systemd</strong> manner.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--no-tls</strong></dt>\n<dd>\n<p>Don&#8217;t use TLS. Certificates will not be read, and https connections\ndenied. Then <strong>cockpit-tls</strong> will only manage a single cockpit-ws\ninstance, and thus not do anything different than running\n<strong>cockpit-ws --no-tls</strong> directly. Only use this for debugging or\ntesting.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--idle-timeout</strong> <em>SECONDS</em></dt>\n<dd>\n<p>If greater than 0, exit if no connections have happened for the given\nnumber of seconds, i. e. the server is idle. If not given, the default\nis 90.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_environment_2\">Environment</h5>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-tls</strong> program expects the <strong>RUNTIME_DIRECTORY</strong>\nenvironment variable to be set to an empty directory (preferably in\n<strong>/run/</strong>) that is only accessible by the system user under which it is\nrunning. This contains the Unix sockets for communicating with the\n<strong>cockpit-ws</strong> instances, and in the future, state information about\nclient certificates. This variable is normally set by the\n<strong>cockpit.service</strong> systemd unit.</p>\n</div>\n<div class=\"paragraph\">\n<p>In addition, <strong>cockpit-tls</strong> will use the <strong>XDG_CONFIG_DIRS</strong>\nenvironment variable from the\n<a href=\"https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html\">XDG\nbasedir spec</a> to find its certificates and the <strong>cockpit.conf(5)</strong>\nconfiguration file.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_bugs_4\">Bugs</h5>\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_author_4\">Author</h5>\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_see_also_4\">See also</h5>\n<div class=\"paragraph\">\n<p><strong>cockpit-ws(8)</strong> , <strong>cockpit.conf(5)</strong> , <strong>systemd(1)</strong></p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_desktop1\">cockpit-desktop(1)</h4>\n<div class=\"sect4\">\n<h5 id=\"_name_5\">Name</h5>\n<div class=\"paragraph\">\n<p>cockpit-desktop - Cockpit Desktop integration</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_synopsis_3\">Synopsis</h5>\n<div class=\"paragraph\">\n<p><strong>cockpit-desktop</strong> <em>URLPATH</em> [<em>SSH_HOST</em>]</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_description_5\">Description</h5>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-desktop</strong> program provides secure access to Cockpit pages\nin an already running desktop session. It starts a web server\n(<strong>cockpit-ws</strong>) and a web browser in an isolated network namespace, and\na <strong>cockpit-bridge(8)</strong> in the running user session.</p>\n</div>\n<div class=\"paragraph\">\n<p>This avoids having to log into Cockpit, and having to enable\n<strong>cockpit.socket</strong> system-wide. The network isolation ensures that no\nother user, and not even other processes in the user&#8217;s session, can\naccess this local web server.</p>\n</div>\n<div class=\"paragraph\">\n<p><strong>URLPATH</strong> is the Cockpit page to open, i. e. the path component of\nCockpit URLs. It is highly recommended to only open a\n<a href=\"https://cockpit-project.org/guide/latest/embedding.html\">particular page frame</a>, not the entire Cockpit navigation and menu. For example, the\npath <code>/cockpit/@localhost/storage/index.html</code> will open the Storage\npage. It is also possible to give abbreviated forms of urls, such as\n&#8220;/storage&#8221; or &#8220;/network/firewall&#8221;.</p>\n</div>\n<div class=\"paragraph\">\n<p><em>SSH_HOST</em> is an optional SSH remote host specification (<em>hostname</em>\nor <em>username@hostname</em>). If given, <strong>cockpit-bridge</strong> will be started\non the remote host through <strong>ssh(1)</strong> instead, i. e. the Cockpit web\nbrowser will show that remote host. Note that this is more of an\nexperimental/demo feature.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_environment_3\">Environment</h5>\n<div class=\"paragraph\">\n<p>The <strong>BROWSER</strong> environment variable specifies the browser command (and\npossibly options) that will be used to open the requested Cockpit page.\nIf not set, <strong>cockpit-desktop</strong> attempts to use an internal minimalistic\nWebKit browser, and failing that, will attempt to detect some reasonable\nalternatives.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_bugs_5\">Bugs</h5>\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_author_5\">Author</h5>\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_see_also_5\">See also</h5>\n<div class=\"paragraph\">\n<p><strong>cockpit-ws(8)</strong>, <strong>cockpit-bridge(1)</strong></p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_bridge1\">cockpit-bridge(1)</h4>\n<div class=\"sect4\">\n<h5 id=\"_name_6\">Name</h5>\n<div class=\"paragraph\">\n<p>cockpit-bridge - Cockpit Host Bridge</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_synopsis_4\">Synopsis</h5>\n<div class=\"paragraph\">\n<p><strong>cockpit-bridge</strong> [<strong>--help</strong>] [<strong>--packages</strong>]</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_description_6\">Description</h5>\n<div class=\"paragraph\">\n<p>The <strong>cockpit-bridge</strong> program is used by Cockpit to relay messages and\ncommands from the Web front end to the server. Among other things it\nrelays DBus, and spawns processes on behalf of the Web user interface.</p>\n</div>\n<div class=\"paragraph\">\n<p>This program is not routinely run by users or administrators. It is in\nthe <strong>$PATH</strong> so that Cockpit can find it when connecting between hosts.\nHowever there are some diagnostics available when running from the\ncommand line.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_options_3\">Options</h5>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>--help</strong></dt>\n<dd>\n<p>Show help options.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--interact</strong>=<em>boundary</em></dt>\n<dd>\n<p>Interact with the raw cockpit1 protocol. Useful for debugging and\ntesting. Specify a <em>boundary</em> which should be on an empty line\nbetween messages.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--packages</strong></dt>\n<dd>\n<p>List all available Cockpit packages and exit. Note this includes\npackages available to the user running this command.</p>\n</dd>\n<dt class=\"hdlist1\"><strong>--version</strong></dt>\n<dd>\n<p>Show Cockpit version information.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_bugs_6\">Bugs</h5>\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_author_6\">Author</h5>\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_see_also_6\">See also</h5>\n<div class=\"paragraph\">\n<p><strong>cockpit-ws(8)</strong></p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_pam_ssh_add8\">pam_ssh_add(8)</h4>\n<div class=\"sect4\">\n<h5 id=\"_name_7\">Name</h5>\n<div class=\"paragraph\">\n<p>pam_ssh_add - PAM module to auto load ssh keys into an agent</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_description_7\">Description</h5>\n<div class=\"paragraph\">\n<p><strong>pam_ssh_add</strong> provides authentication and session modules that allow users\nto start their session with a running ssh-agent with as many ssh keys\nloaded as possible.</p>\n</div>\n<div class=\"paragraph\">\n<p>If used, the authentication module simply stores the authentication\ntoken for later use by the session module. Because this module performs\nno actual authentication it returns PAM_CRED_INSUFFICIENT on success and\nshould always be accompanied by an actual authentication module in your\npam configuration.</p>\n</div>\n<div class=\"paragraph\">\n<p>By default the session module will start a new ssh-agent and run\nssh-add, loading any keys that exist in the default path for the newly\nlogged in user. If any keys prompt for a password, and a authentication\ntoken was successfully stored, that token will be provided as the\npassword.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_options_4\">Options</h5>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>debug</strong></dt>\n<dd>\n<p>This option will turn on debug logging to syslog.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_examples\">Examples</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>        auth     required  pam_unix.so\n        auth     optional  pam_ssh_add.so\n        session  optional  pam_ssh_add.so</pre>\n</div>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_bugs_7\">Bugs</h5>\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_author_7\">Author</h5>\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"https\">SSL/TLS Usage</h3>\n<div class=\"paragraph\">\n<p>Cockpit usually requires that web browsers communicate with it using\nHTTPS, for security reasons.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"https-required\">HTTPS Requirement</h4>\n<div class=\"paragraph\">\n<p>Cockpit listens for both HTTP and HTTPS connections on the same port, by\ndefault 9090. If an HTTP connection is made, Cockpit will redirect that\nconnection to HTTPS. There are some exceptions:</p>\n</div>\n<div class=\"ulist\">\n<ul>\n<li>\n<p>If an HTTP connection comes from <code>localhost</code> (<code>127.0.0.1</code> or\n<code>::1</code>, then Cockpit will allow communication without redirecting to\nHTTPS.</p>\n</li>\n<li>\n<p>Certain URLs, like <code>/ping</code> are not required to use HTTPS.</p>\n</li>\n</ul>\n</div>\n<div class=\"paragraph\">\n<p>This behavior can be overridden by setting the <code>AllowUnencrypted</code>\noption in <code>cockpit.conf</code>.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"https-certificates\">Certificates</h4>\n<div class=\"paragraph\">\n<p>Cockpit will load a certificate from the <code>/etc/cockpit/ws-certs.d</code>,\ndirectory, or below <code>$XDG_CONFIG_DIRS</code> if set (see\n<a href=\"./cockpit.conf.5.html\">cockpit.conf</a>). It will use the last file\nwith a <code>.cert</code> or <code>.crt</code> extension in alphabetical order. The file\nshould contain one or more OpenSSL style <code>BEGIN CERTIFICATE</code> blocks\nfor the server certificate and the intermediate certificate authorities.</p>\n</div>\n<div class=\"paragraph\">\n<p>The private key must be contained in a separate file with the same name\nas the certificate, but with a <code>.key</code> suffix instead. The key must not\nbe encrypted.</p>\n</div>\n<div class=\"paragraph\">\n<p>If no certificate is found, a self-signed certificate is created and\nstored in the <code>0-self-signed.cert</code> file. On some platforms, Cockpit\nwill also generate a ca.crt in that directory, which may be safely\nimported into client browsers.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit will read the files as root, so they can have tight permissions.</p>\n</div>\n<div class=\"paragraph\">\n<p>To check which certificate <code>cockpit-ws</code> will use run the following\ncommand.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo /usr/libexec/cockpit-certificate-ensure --check</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Or, on Debian-based systems:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo /usr/lib/cockpit/cockpit-certificate-ensure --check</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If using <code>certmonger</code> to manage certificates, following command can be\nused to automatically prepare a certificate/key file pair:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>getcert request -f /etc/cockpit/ws-certs.d/50-certmonger.cert \\\n                -k /etc/cockpit/ws-certs.d/50-certmonger.key \\\n                -D myhostname.example.com \\\n                [--ca=...]</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This will not work on Red Hat Enterprise Linux 8 by default. Adjust the\nSELinux type of the certificate directory to <code>cert_t</code> to allow\ncertmonger to write its certificates there:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>semanage fcontext -a -t cert_t '/etc/cockpit/ws-certs\\.d(/.*)?'\nrestorecon -v /etc/cockpit/ws-certs.d</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"listen\">TCP Port and Address</h3>\n<div class=\"paragraph\">\n<p>Cockpit&#8217;s <code>cockpit-ws</code> component is configured by default to accept\nconnections on port <code>9090</code>. This is the port that is documented for a\n\"Web-based System Manager\" to listen on. It is also relatively\nmemorable.</p>\n</div>\n<div class=\"paragraph\">\n<p>However there are many reasons you may wish to change the default port.\nFor example other software may use port <code>9090</code> or you may wish to\nsetup Cockpit to listen on <code>443</code> instead. It is also possible to have\nCockpit only listen on one specific IP address.</p>\n</div>\n<div class=\"paragraph\">\n<p>Note that it is only required to have Cockpit listening on a TCP port on\nthe server that you access with your web browser. If you add multiple\nservers with host switcher, Cockpit will connect to those servers via\n<code>ssh</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The systems that Cockpit runs on are typically locked down with\nfirewalls, SELinux, so changing the default port is not as easy as\nediting a configuration file.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"listen-systemd\">Cockpit systemd Socket</h4>\n<div class=\"paragraph\">\n<p>On servers with\n<a href=\"https://www.freedesktop.org/wiki/Software/systemd/\"><code>systemd</code></a> Cockpit\nstarts on demand via socket activation. To change its port and/or\naddress you should place the following content in the\n<code>/etc/systemd/system/cockpit.socket.d/listen.conf</code> file. Create the\nfile and directories in that path which not already exist. The\n<code>ListenStream</code> option specifies the desired address and TCP port.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>[Socket]\nListenStream=\nListenStream=443</pre>\n</div>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>[Socket]\nListenStream=\nListenStream=7777\nListenStream=192.168.1.1:443\nFreeBind=yes</pre>\n</div>\n</div>\n<div class=\"admonitionblock note\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Note</div>\n</td>\n<td class=\"content\">\nThe first line with an empty value is intentional. <code>systemd</code>\nallows multiple <code>Listen</code> directives to be declared in a single socket\nunit; an empty value in a drop-in file resets the list and thus disables\nthe default port 9090 from the original unit.\n</td>\n</tr>\n</table>\n</div>\n<div class=\"paragraph\">\n<p>The <code>FreeBind</code> option is highly recommended when defining specific IP\naddresses. See the\n<a href=\"https://www.freedesktop.org/software/systemd/man/systemd.socket.html\"><code>systemd.socket</code>\nmanpage</a> for details.</p>\n</div>\n<div class=\"paragraph\">\n<p>In order for the changes to take effect, run the following commands:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo systemctl daemon-reload\n$ sudo systemctl restart cockpit.socket</pre>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"listen-selinux\">SELinux Port</h4>\n<div class=\"paragraph\">\n<p>If <a href=\"https://selinuxproject.org/page/Main_Page\">SELinux</a> is protecting your\nserver, then you will need to tell it to allow Cockpit to listen on the\nnew port. Run the following command to do so. The last argument\nspecifies the desired TCP port.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo semanage port -a -t websm_port_t -p tcp 9999</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If the port is already defined by some other part of the SELinux policy,\nthen you will need to use the <code>-m</code> argument to modify the definition.\nThat&#8217;s the case with the <code>443</code> SSL port, which is typically defined as\nan <code>http_port_t</code> port.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo semanage port -m -t websm_port_t -p tcp 443</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The changes should take effect immediately.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"listen-firewalld\">Firewalld Port</h4>\n<div class=\"paragraph\">\n<p>If <a href=\"https://fedoraproject.org/wiki/FirewallD\">Firewalld</a> is configured as\nyour firewall, then you will need to tell it to allow Cockpit to receive\nconnections on the new port. Run the following commands to do so. The\nlast options specify the desired TCP port.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo firewall-cmd [--zone=ZONE] --add-port=443/tcp\n$ sudo firewall-cmd --permanent [--zone=ZONE] --add-port=443/tcp</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"startup\">Start up</h3>\n<div class=\"paragraph\">\n<p>Cockpit&#8217;s <code>cockpit-ws</code> component is what the browser connects to and\nit typically starts on demand via\n<a href=\"https://www.freedesktop.org/wiki/Software/systemd/\"><code>systemd</code></a> socket\nactivation.</p>\n</div>\n<div class=\"paragraph\">\n<p>The actual <code>cockpit.service</code> and <code>cockpit-ws</code> process will start on\ndemand when a browser accesses the <code>cockpit.socket</code>,\n<a href=\"#listen\">usually on port 9090</a>. Once a user logs in then a\n<code>cockpit-bridge</code> process will be started in a Linux user login\nsession.</p>\n</div>\n<div class=\"paragraph\">\n<p>Only systems that you connect to with your browser need to have the\n<code>cockpit.socket</code> enabled. For systems that you add through host\nswitcher the bridge is started via SSH on demand.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"startup-shutdown\">Process exit</h4>\n<div class=\"paragraph\">\n<p>The <code>cockpit-bridge</code> process will exit when the user logs out. In\naddition, after 10 minutes of inactivity, the <code>cockpit-ws</code> process\nwill exit on its own. The browser will automatically disconnect if it\nfails to hear from the <code>cockpit-ws</code> process for 30 seconds.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"startup-boot\">Boot start up</h4>\n<div class=\"paragraph\">\n<p>To make Cockpit available by default after system boot the\n<code>cockpit.socket</code> needs to be enabled:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo systemctl enable cockpit.socket</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If you wish to not have Cockpit available by default via a browser, then\nthe <code>cockpit.socket</code> should be disabled:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo systemctl disable cockpit.socket</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"multi-host\">Managing multiple hosts at the same time</h3>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>This feature is deprecated as of Cockpit 322.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit allows you to access multiple hosts in a single session, by\nestablishing SSH connections to other hosts. This is quite similar to\nlogging into these other hosts using the <code>ssh</code> command on the command\nline, with one very important difference:</p>\n</div>\n<div class=\"paragraph\">\n<p>Code from the local host and all the remote hosts run at the same time,\nin the same browser context. They are not isolated from each other in\nthe browser. All code effectively has the same privileges as the primary\nsession on the local host.</p>\n</div>\n<div class=\"paragraph\">\n<p>Thus, <em>you should only only connect to remote hosts that you trust</em>. You\nmust be sure that none of the hosts that you connect to will cause\nCockpit to load malicious JavaScript code into your browser.</p>\n</div>\n<div class=\"paragraph\">\n<p>Therefore, Cockpit will warn you before connecting to more than one\nhost. It is also possible to disable multiple hosts entirely, and some\noperating systems do this already by default.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can prevent loading of JavaScript, HTML, etc from more than one host\nby adding this to <code>cockpit.conf</code>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>    [WebService]\n    AllowMultiHost=false</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>When you allow multiple hosts in a single Cockpit session by setting\n<code>AllowMultiHost</code> to true, then the user will be warned once per\nsession, before connecting to the second host. If that is still too\nmuch, you can switch the warning off completely by adding the following\nto <code>cockpit.conf</code>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>    [Session]\n    WarnBeforeConnecting=false</pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"authentication\">Cockpit Authentication</h3>\n<div class=\"paragraph\">\n<p>While cockpit allows you to monitor and administer several servers at\nthe same time, there is always a primary server your browser connects to\nthat runs the Cockpit web service (cockpit-ws) through which connections\nto additional servers are established. See\n<a href=\"https://raw.githubusercontent.com/cockpit-project/cockpit/main/doc/cockpit-transport.png\">this\ndiagram</a> for how it works.</p>\n</div>\n<div class=\"paragraph\">\n<p>Normally, a session is established on the primary server, and you use\nthe Shell UI of that session to connect to secondary servers.</p>\n</div>\n<div class=\"paragraph\">\n<p>However, it is also possible to instruct the <code>cockpit-ws</code> process on\nthe primary server to directly connect to a secondary server, without\nopening a session on the primary server at all. This is done on the main\nlogin page of Cockpit, by filling out the \"Connect to\" field.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"initial-auth\">Directly logging into the primary server</h4>\n<div class=\"paragraph\">\n<p>The most common way to use Cockpit is to just log directly into the\nserver that you want to access. This can be done if you have direct\nnetwork access to port 9090 on that server.</p>\n</div>\n<div class=\"paragraph\">\n<p>By default the cockpit web service is installed on the base system and\n<a href=\"#listen\">socket activated by systemd</a>. In this setup access is\ncontrolled by a cockpit specific pam stack, generally located at\n<code>/etc/pam.d/cockpit</code>. By default this is configured to allow you to\nlogin with the username and password of any local account on the system.\nYou can also setup a <a href=\"#sso\">Kerberos based SSO solution</a> or\n<a href=\"#cert-authentication\">certificate/smart card authentication</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can also\n<a href=\"https://github.com/cockpit-project/cockpit/blob/main/doc/authentication.md#actions\">disable\nauthentication schemes</a> to enforce authentication policies, or to\nsuppress undesired browser GSSAPI authentication dialogs.</p>\n</div>\n<div class=\"paragraph\">\n<p>The web server can also be run from the\n<a href=\"https://quay.io/cockpit/ws\">cockpit/ws</a> container. If you are\nrunning cockpit on a container host operating system like\n<a href=\"https://getfedora.org/coreos/\">Fedora CoreOS</a> this will be the only\nsupported mode. In this setup, cockpit establishes an SSH connection\nfrom the container to the underlying host, meaning that it is up to your\nSSH server to grant access. To login with a local account, <code>sshd</code> will\nneed to be configured to allow password based authentication.\nAlternatively you can setup a <a href=\"#sso\">Kerberos based SSO solution</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>Like <code>sshd</code>, cockpit can be configured to limit the number of\nconcurrent login attempts allowed. This is done by adding a\n<code>MaxStartups</code> option to the <code>WebService</code> section of your\n<code>cockpit.conf</code>. Additional connections will be dropped until\nauthentication succeeds or the connections are closed.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"direct-secondary-auth\">Directly logging into a secondary server without a primary session</h4>\n<div class=\"paragraph\">\n<p>It is also possible to log into a secondary server without opening a\nsession on the primary server. This is useful if you are not actually\ninterested in the primary server and would only use it because you do\nnot have direct network access to the secondary server.</p>\n</div>\n<div class=\"paragraph\">\n<p>In this case, <code>cockpit-ws</code> still runs on the primary server, but the\ncredentials from the login screen are directly used with SSH to log into\nthe secondary server given in the \"Connect To\" field of the login\nscreen.</p>\n</div>\n<div class=\"paragraph\">\n<p>Thus, the PAM configuration and accounts on the primary server don&#8217;t\nmatter at all. Often, the only purpose of the primary server is to sit\non the boundary of your network and forward connections to internal\nmachines.</p>\n</div>\n<div class=\"paragraph\">\n<p>In this case, the login page will prompt you to verify unknown SSH keys.\nAccepted keys will be remembered in the local storage of your browser.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"secondary-auth\">Logging into a secondary server from the primary session</h4>\n<div class=\"paragraph\">\n<p>Once you have a session on the primary server, it is possible connect to\nadditional servers by using the host switching UI of the Cockpit Shell.\nThis is useful if you have direct network access to the primary server,\nbut not to the secondary server.</p>\n</div>\n<div class=\"paragraph\">\n<p>On the command line, you would log into the primary server and then use\nSSH to log into the secondary one. Cockpit does just the same, and uses\nSSH to log into the secondary server. Instead of running a interactive\nshell there, however, it starts a <code>cockpit-bridge</code> process.</p>\n</div>\n<div class=\"paragraph\">\n<p><em>Warning:</em> Unlike with SSH on the command line though, this will also\nload and use the Cockpit pages (i.e. JavaScript) from the remote\nmachine, which means that the remote machine can execute arbitrary code\non your primary and all other connected secondary machines. Hence, only\nconnect to <em>machines which you trust</em>.</p>\n</div>\n<div class=\"paragraph\">\n<p>Due to this security risk, this host switcher functionality is disabled\nby default, except on long-term stable Linux distributions (Red Hat\nEnterprise Linux 9, Debian 12, and Ubuntu 22.04/24.04 LTS). If you are\ncomfortable with the security implications, you can enable it manually\nwith the <code>AllowMultiHost</code> option in <code>cockpit.conf</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>These servers will need to be running an SSH server and be configured to\nsupport one of the following authentication methods.</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_password\">Password</h5>\n<div class=\"paragraph\">\n<p>The target server will need to have password based authentication\nenabled in <code>sshd</code>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_kerberos\">Kerberos</h5>\n<div class=\"paragraph\">\n<p>The target server will need to be a member of the same domain as the\nprimary server and your domain must be whitelisted in your browser. See\nthe <a href=\"#sso\">SSO documentation</a> for how to set this up.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"_public_key\">Public key</h5>\n<div class=\"paragraph\">\n<p>When you successfully log into the primary server, a <code>ssh-agent</code> is\nstarted and keys are loaded into it by running <code>ssh-add</code> without any\narguments. Any passphrase prompt is answered with the password used to\nlog into the primary server.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit provides a user interface for loading other keys into the agent\nthat could not be automatically loaded.</p>\n</div>\n<div class=\"paragraph\">\n<p>The target server will need to have public key authentication enabled in\n<code>sshd</code>, and the public key you wish to use must be present in\n<code>~/.ssh/authorized_keys</code>. Cockpit has a user interface for creating\nSSH keys and for authorizing them.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"host-keys\">SSH host keys</h5>\n<div class=\"paragraph\">\n<p>Cockpit will prompt the user to verify unknown SSH host keys, and will\nwrite accepted host keys into <code>~/.ssh/known_hosts</code>.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"sso\">Single Sign On</h3>\n<div class=\"paragraph\">\n<p>Cockpit can use Kerberos for Single Sign On authentication, where users\nare automatically authenticated if they have a valid Kerberos ticket.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"sso-server\">Server Requirements</h4>\n<div class=\"paragraph\">\n<p>To authenticate users, the server that Cockpit is running on must be\njoined to a domain. This can usually be accomplished using the\n<a href=\"https://freedesktop.org/software/realmd/docs/realm.html\"><code>realm join example.com</code></a>\ncommand.</p>\n</div>\n<div class=\"paragraph\">\n<p>The domain must be resolvable by DNS. For instance, the SRV records of\nthe kerberos server should be resolvable:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ host -t SRV  _kerberos._udp.example.com\n_kerberos._udp.example.com has SRV record 0 100 88 dc.example.com</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The server running Cockpit should have a fully qualified name that ends\nwith the domain name.</p>\n</div>\n<div class=\"paragraph\">\n<p>There must be a valid Kerberos host key for the server in the\n<code>/etc/krb5.keytab</code> file. Alternatively, if you would like to use a\ndifferent keytab, you can do so by placing it in\n<code>/etc/cockpit/krb5.keytab</code>, or below <code>$XDG_CONFIG_DIRS</code> if set (see\n<a href=\"./cockpit.conf.5.html\">cockpit.conf</a>). It may be necessary to create\na kerberos service principal and update the keytab if it is not present.\nDepending on your domain type different service names are required:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Active Directory</dt>\n<dd>\n<p><code>HOST/server.example.com@EXAMPLE.COM</code></p>\n</dd>\n<dt class=\"hdlist1\">IPA and MIT</dt>\n<dd>\n<p><code>HTTP/server.example.com@EXAMPLE.COM</code></p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>When joining an IPA domain with Cockpit and the <code>ipa</code> command line\ntool is available, both the service principal name and a\n<code>/etc/cockpit/krb5.keytab</code> get created automatically, so that Kerberos\nbased single sign on into Cockpit works out of the box. If you want/need\nto do this by hand or in a script, first create or modify the <code>HTTP/</code>\nservice principal:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo ipa service-add --ok-as-delegate=true --ok-to-auth-as-delegate=true \\\n    HTTP/server.example.com@EXAMPLE.COM\n# or, if it already exists, just enable delegation:\n$ sudo ipa service-mod --ok-as-delegate=true --ok-to-auth-as-delegate=true \\\n    HTTP/server.example.com@EXAMPLE.COM</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Then generate a key for that principal:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo ipa-getkeytab -p HTTP/server.example.com@EXAMPLE.COM -k /etc/cockpit/krb5.keytab</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The following command can be used to list the\n<code>/etc/cockpit/krb5.keytab</code>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo klist -k /etc/cockpit/krb5.keytab</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Lastly accounts from the domain must be resolvable to unix accounts on\nthe server running Cockpit. For example:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ getent passwd user@example.com\nuser@example.com:*:381001109:381000513:User Name:/home/user:/bin/sh</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If you wish to delegate your kerberos credentials to Cockpit, and allow\nCockpit to then connect to other machines using those credentials, you\nshould enable delegation for the hosts running Cockpit, and in some\ncases the <code>HTTP</code> service as well. When joining an IPA domain, this is\nenabled by default.</p>\n</div>\n<div class=\"paragraph\">\n<p>Domain admins (usually the <code>admins@example.com</code> group) should normally\nalso be able to administer any joined machine. Enable sudo access for\nthat group with the following command on the IPA server, for version\n4.7.1 and later:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>ipa-advise enable-admins-sudo | sh -ex</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>On earlier FreeIPA versions, run these commands instead, as a domain\nadmin on any joined machine:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>ipa sudorule-add --hostcat=all --cmdcat=all All\nipa sudorule-add-user --groups=admins All</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Note that this does not change security properties; domain admins can\ngive this privilege to themselves, so it is safe to enable by default.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"sso-client\">Client Requirements</h4>\n<div class=\"paragraph\">\n<p>The client side, where your web browser is running, should have a valid\nkerberos ticket in the current user session. A command like this will\nget one:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ kinit user@EXAMPLE.COM\nPassword for user@EXAMPLE.COM:</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>In addition your browser must be usually be configured to allow kerberos\nauthentication for the domain.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Mozilla Firefox</dt>\n<dd>\n<p>Go to <code>about:config</code> and set the\n<code>network.negotiate-auth.trusted-uris</code> setting to your domain name\npreceded by a dot, ie: <code>.example.com</code></p>\n</dd>\n<dt class=\"hdlist1\">Google Chrome</dt>\n<dd>\n<p>On Linux: create the file\n<code>/etc/opt/chrome/policies/managed/example-com.json</code> with the\ncontents:</p>\n</dd>\n<dt class=\"hdlist1\"></dt>\n</dl>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"AuthServerWhitelist\": \"*example.com\"\n}</pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"></dt>\n<dd>\n<p>and restart the browser. On other platforms, exit your browser\ncompletely, and start it with a command line like this:\n<code>google-chrome --auth-server-whitelist=*example.com</code></p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Use a fully qualified server name (with the domain name at the end) to\naccess Cockpit in your web browser.</p>\n</div>\n<div class=\"paragraph\">\n<p>If you wish to connect from one server to another in Cockpit using\nkerberos SSO, then you have to explicitly enable all sorts of things.\nFor starters, make sure that delegated credentials are allowed by your\ndomain (see above). Next when requesting your kerberos ticket make sure\nthat forwardable tickets are requested:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ kinit -f user@EXAMPLE.COM\nPassword for user@EXAMPLE.COM:</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Make sure that the forwardable flag <code>F</code> is present in your ticket:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ klist -f\nTicket cache: KEYRING:persistent:1000:1000\nDefault principal: user@EXAMPLE.COM\n\nValid starting       Expires              Service principal\n18.03.2017 05:39:23  19.03.2017 05:39:20  krbtgt/EXAMPLE.COM@EXAMPLE.COM\n    Flags: FIA</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Lastly configure your browser to allow delegated, forwardable kerberos\ncredentials to be sent to Cockpit:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Mozilla Firefox</dt>\n<dd>\n<p>Go to <code>about:config</code> and set the\n<code>network.negotiate-auth.delegation-uris</code> setting to your domain name\npreceded by a dot, ie: <code>.example.com</code></p>\n</dd>\n<dt class=\"hdlist1\">Google Chrome</dt>\n<dd>\n<p>On Linux: create the file\n<code>/etc/opt/chrome/policies/managed/example-com.json</code> with the\ncontents:</p>\n</dd>\n<dt class=\"hdlist1\"></dt>\n</dl>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"AuthServerWhitelist\": \"*example.com\",\n  \"AuthNegotiateDelegateWhitelist\": \"*example.com\"\n}</pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"></dt>\n<dd>\n<p>and restart the browser. On other platforms, exit your browser\ncompletely, and start it with a command line like this:\n<code>google-chrome --auth-server-whitelist=*example.com --auth-negotiate-delegate-whitelist=*example.com</code></p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"cert-authentication\">Certificate/smart card authentication</h3>\n<div class=\"paragraph\">\n<p>Cockpit can use TLS client certificates for authenticating users.\nCommonly these are provided by a smart card, but it&#8217;s equally possible\nto import certificates directly into the web browser.</p>\n</div>\n<div class=\"paragraph\">\n<p>This requires the host to be in an Identity Management domain like\n<a href=\"https://www.freeipa.org\">FreeIPA</a> or\n<a href=\"https://en.wikipedia.org/wiki/Active_Directory\">Active Directory</a>, which\ncan associate certificates to users.</p>\n</div>\n<div class=\"paragraph\">\n<p>To authenticate users from a Identity Management domain, the server that\nCockpit is running on must be joined to that domain. See the\n<a href=\"#sso-server\">SSO server requirements</a> for details.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"certauth-server-cert-generation\">User certificate generation</h4>\n<div class=\"paragraph\">\n<p>Generating the certificates for users is usually done with a certificate\nmanagement system like <a href=\"https://pagure.io/certmonger\">certmonger</a> or\n<a href=\"https://www.freeipa.org/page/PKI\">FreeIPA</a>, which are not documented\nhere. This command generates a simple key and certificate request for\nthe \"alice\" user:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>openssl req -new -newkey rsa:2048 -days 365 \\\n    -keyout alice.key -out alice.csr -subj \"/CN=alice\"</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Now get this certificate request signed by the Certificate Authority of\nyour Identity Management domain, to get a PEM certificate. Browsers and\nsmart cart utilities accept PKCS#12 format for importing/transfer, so\nconvert the certificate/key pair; it will ask for and protect it with a\ntransfer password:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>openssl pkcs12 -export -in alice.pem -inkey alice.key -out alice.p12</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Don&#8217;t forget to clean up the key file when you do not need it any more:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>shred -u alice.key</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>You can now import <code>alice.p12</code> directly into your browser, with giving\nthe transfer password set above. Or\n<a href=\"https://linux.die.net/man/1/pkcs15-init\">put the certificate onto a smart\ncard</a>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>pkcs15-init --store-private-key alice.p12 --format pkcs12 --auth-id 01</pre>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"certauth-server-ipa\">Certificate mapping with FreeIPA</h4>\n<div class=\"paragraph\">\n<p>The recommended method to sign a user certificate request and associate\nit to a user is <code>ipa cert-request</code>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>ipa cert-request alice.csr --principal=alice --certificate-out=alice.pem</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Alternatively, if you are using a different CA, you can use\n<code>ipa user-add-cert</code> to associate the signed certificate to the user.\nThis expects PEM format, but without the <code>-----BEGIN</code>/<code>-----END</code>\nmarkers:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>ipa user-add-cert alice --certificate=\"$(grep -v ^---- alice.pem)\"</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>See the\n<a href=\"https://www.freeipa.org/page/V4/User_Certificates#Feature_Management\">FreeIPA\nUser Certificates documentation</a> for details.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"certauth-server-ms-ad\">Certificate mapping with Microsoft Active Directory</h4>\n<div class=\"paragraph\">\n<p>The domain user certificates get imported into the\n<code>userCertificate;binary</code> LDAP attribute. The following commands\nconvert the PEM certificate into binary DER form, create an\n<a href=\"https://ldap.com/ldif-the-ldap-data-interchange-format/\">LDIF</a> file and\napply it to the LDAP server running on the domain controller\n\"dc.example.com\":</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>openssl x509 -outform der -in alice.pem -out alice.der\n\ncat &lt;&lt;EOF &gt; alice.ldif\nversion: 1\ndn: cn=alice,ou=users,ou=YOUR_NETBIOS_NAME,dc=example,dc=com\nchangetype: modify\nadd: userCertificate;binary\nuserCertificate;binary:&lt; file://$(pwd)/alice.der\nEOF\n\nldapmodify -H ldap://dc.example.com -f alice.ldif</pre>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"certauth-server-samba-ad\">Certificate mapping with Samba Active Directory</h4>\n<div class=\"paragraph\">\n<p>At least some versions of <a href=\"https://www.samba.org/\">Samba</a> do not support\nthe <code>userCertificate;binary</code> LDAP attribute, so the import has to\nhappen in base64 PEM form into the textual <code>userCertificate</code> attribute\ninstead. Also, Samba uses a slightly different user hierarchy:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cat &lt;&lt;EOF &gt; alice.ldif\nversion: 1\ndn: cn=alice,cn=users,dc=example,dc=com\nchangetype: modify\nadd: userCertificate\nuserCertificate: $(grep -v ^---- alice.pem | tr -d '\\n')\nEOF\n\nldapmodify -H ldap://dc.example.com  -f alice.ldif</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>As <code>userCertificate</code> is a text instead of binary field, you need to\nset up a\n<a href=\"https://www.mankier.com/5/sssd.conf#Certificate_Mapping_Section\">certificate\nmapping rule</a> in <code>sssd.conf(5)</code> in a <code>[certmap/domain/rulename]</code>\nsection, for example:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>[certmap/example.com/adcerts]\n# we match full certificates, so it is not important to check anything here\nmatchrule = &lt;KU&gt;digitalSignature\nmaprule = LDAP:(userCertificate={cert!base64})</pre>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"certauth-server-cockpitconf\">Cockpit web server configuration</h4>\n<div class=\"paragraph\">\n<p>Set the trusted Certificate Authority of your user certificates in\n<code>sssd</code>, either by copying the CA PEM file to\n<code>/etc/sssd/pki/sssd_auth_ca_db.pem</code> or setting the\n<a href=\"https://www.mankier.com/5/sssd.conf#Services_Sections-PAM_configuration_options\"><code>pam_cert_db_path</code></a>\nconfiguration option to the path of the CA. If you use FreeIPA and its\nCA:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cp /etc/ipa/ca.crt /etc/sssd/pki/sssd_auth_ca_db.pem</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Certificate authentication needs to be enabled in\n<a href=\"./cockpit.conf.5.html\">cockpit.conf</a> explicitly:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>[WebService]\nClientCertAuthentication = yes</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>When enabling this mode,\n<a href=\"https://github.com/cockpit-project/cockpit/blob/main/doc/authentication.md\">other\nauthentication types</a> commonly get disabled, so that <em>only</em> client\ncertificate authentication will be accepted. By default, after a failed\ncertificate authentication attempt, Cockpit&#8217;s normal login page will\nappear and permit other login types such as <code>basic</code> (passwords) or\n<code>negotiate</code> (Kerberos). For example, password authentication gets\ndisabled with:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>[basic]\naction = none</pre>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"certauth-server-resourcelimits\">Cockpit web server resource limits</h4>\n<div class=\"paragraph\">\n<p>When using certificate authentication, all requests with a particular\ncertificate will be handled by a separate and isolated instance of the\n<a href=\"./cockpit-ws.8.html\">cockpit-ws</a> web server. This protects against\npossible vulnerabilities in the web server and prevents an attacker from\nimpersonating another user. However, this introduces a potential Denial\nof Service: Some remote attacker could create a large number of\ncertificates and send a large number of http requests to Cockpit with\nthese.</p>\n</div>\n<div class=\"paragraph\">\n<p>To mitigate that, all <code>cockpit-ws</code> instances run in a\n<code>system-cockpithttps.slice</code>\n<a href=\"https://www.freedesktop.org/software/systemd/man/systemd.slice.html\">systemd\nslice unit</a> which\n<a href=\"https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html\">limits\nthe collective resources</a> of these web server instances: by default,\nthis slice sets a limit of 200 threads (roughly 100 instances of\n<code>cockpit-ws</code>&#8201;&#8212;&#8201;in other words, a maximum of 100 parallel user\nsessions with different certificates) and a 75% (soft)/90% (hard) memory\nlimit.</p>\n</div>\n<div class=\"paragraph\">\n<p>You are welcome to adjust these limits to your need through a\n<a href=\"https://www.freedesktop.org/software/systemd/man/systemd.unit.html\">drop-in</a>.\nFor example:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre># systemctl edit system-cockpithttps.slice\n\n[Slice]\n# change existing value\nTasksMax=100\n# add new restriction\nCPUQuota=30%</pre>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"certauth-forwarding\">Authentication to other services like sudo and ssh</h4>\n<div class=\"paragraph\">\n<p>Once you logged into Cockpit with a certificate, you likely need to\nswitch to administrative mode (root privileges through sudo), or connect\nto remote machines through SSH. If your user account has a password,\nthat can be used for authenticating to sudo or ssh as usual.</p>\n</div>\n<div class=\"paragraph\">\n<p><em>Supported with FreeIPA only:</em> As an alternative to password\nauthentication, you can also declare the initial Cockpit certificate\nauthentication as trusted for authenticating to SSH, sudo, or other\nservices. For that purpose, Cockpit automatically creates an\n<a href=\"https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-sfu/bde93b0e-f3c9-4ddf-9f44-e1453be7af5a\">S4U2Proxy\nKerberos ticket</a> in the user session:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ klist\nTicket cache: FILE:/run/user/1894000001/cockpit-session-3692.ccache\nDefault principal: user@EXAMPLE.COM\n\nValid starting     Expires            Service principal\n07/30/21 09:19:06  07/31/21 09:19:06  HTTP/myhost.example.com@EXAMPLE.COM\n07/30/21 09:19:06  07/31/21 09:19:06  krbtgt/EXAMPLE.COM@EXAMPLE.COM\n    for client HTTP/myhost.example.com@EXAMPLE.COM</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>You can set up\n<a href=\"https://www.freeipa.org/page/V4/Service_Constraint_Delegation\">constrained\ndelegation rules</a> to enumerate which hosts (including its own) that\nticket is trusted to access. For example, if the cockpit session runs on\nhost <code>myhost.example.com</code> and should be trusted to access its own host\n(through sudo) and another host <code>remote.example.com</code> (through ssh),\ncreate a delegation like this:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre># a list of target machines which can be accessed by a particular rule\nipa servicedelegationtarget-add cockpit-target\nipa servicedelegationtarget-add-member cockpit-target \\\n  --principals=host/myhost.example.com@EXAMPLE.COM \\\n  --principals=host/remote.example.com@EXAMPLE.COM\n\n# allow cockpit sessions (HTTP/ principal) to access that host list\nipa servicedelegationrule-add cockpit-delegation\nipa servicedelegationrule-add-member cockpit-delegation \\\n  --principals=HTTP/myhost.example.com@EXAMPLE.COM\nipa servicedelegationrule-add-target cockpit-delegation \\\n  --servicedelegationtargets=cockpit-target</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>In addition, you need to enable GSS (Kerberos) authentication in the\ncorresponding services.</p>\n</div>\n<div class=\"ulist\">\n<ul>\n<li>\n<p>For SSH, enable <code>GSSAPIAuthentication yes</code> in\n<a href=\"https://linux.die.net/man/5/sshd_config\">/etc/ssh/sshd_config</a>.</p>\n</li>\n<li>\n<p>For sudo, enable <code>pam_sss_gss</code> as described in the\n<a href=\"https://www.mankier.com/8/pam_sss_gss\">manpage</a>: In\n<code>/etc/sssd/sssd.conf</code>: Add an entry for your domain:</p>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>[domain/example.com]\npam_gssapi_services = sudo, sudo-i</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>In <code>/etc/pam.d/sudo</code>, enable the module in the first line:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>auth sufficient pam_sss_gss.so</pre>\n</div>\n</div>\n</li>\n</ul>\n</div>\n<div class=\"paragraph\">\n<p><em>Caveat:</em> The delegated S4U ticket is not yet forwarded to remote SSH\nhosts when connecting to them from Cockpit, so authenticating to sudo on\nthe remote host with that ticket does not work. This will be provided in\na future version.</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"privileges\">Privileges and Permissions</h3>\n<div class=\"paragraph\">\n<p>When a user is logged into Cockpit, they are logged into a normal\nsession that has exactly the same privileges as if they logged in via\nSSH or on the console.</p>\n</div>\n<div class=\"paragraph\">\n<p>However, Cockpit will usually try to escalate the privileges of the user\nusing <a href=\"https://www.freedesktop.org/wiki/Software/polkit/\">Policy Kit</a> or\n<a href=\"https://www.sudo.ws/\">sudo</a>. If the user is able to escalate privileges\nfrom the command line by typing in their password again (or without\ntyping in any password), then Cockpit will be able to escalate the\nprivileges of the session to \"root\" immediately upon login.</p>\n</div>\n<div class=\"paragraph\">\n<p>The user can change the privileges of a session from within that\nsession, via the \"Administrative access\" indicator in the top bar. From\nthat indicator, the user can drop \"root\" privileges and regain them. On\nthe next login, Cockpit will give the session the same privileges.</p>\n</div>\n<div class=\"paragraph\">\n<p>Usually a user needs to be in the <code>wheel</code> Unix user group for the user\nto be able to escalate privileges in this way. However both Policy Kit\nand sudo may be configured to use other criteria.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"privileges-polkit\">Customizing Polkit Privileges</h4>\n<div class=\"paragraph\">\n<p>Services like\n<a href=\"https://www.freedesktop.org/wiki/Software/systemd/\">systemd</a> and\n<a href=\"https://wiki.gnome.org/Projects/NetworkManager\">NetworkManager</a> use\n<a href=\"https://www.freedesktop.org/wiki/Software/polkit/\">Polkit</a> to validate\nand escalate privileges. It is possible to customize these rules with\nfiles in <code>/etc/polkit-1/rules.d</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>Polkit rules files are\n<a href=\"https://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html\">javascript\nwith specific methods and objects</a>. For example, placing the following\npolkit rule to <code>/etc/polkit-1/rules.d/10-operators.rule</code> allows all\nusers in the <code>operators</code> group to start, stop, restart and otherwise\nmanage systemd services:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>polkit.addRule(function(action, subject) {\n    if (action.id == \"org.freedesktop.systemd1.manage-units\") {\n        if (subject.isInGroup(\"operators\")) {\n            return polkit.Result.YES;\n        }\n    }\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>In order to allow a certain group to perform any administrative action\nyou could add a rule like this:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>polkit.addAdminRule(function(action, subject) {\n    return [\"unix-group:operators\"];\n});</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"features\">Feature Internals</h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"feature-systemd\">systemd</h3>\n<div class=\"paragraph\">\n<p>Cockpit uses <a href=\"https://www.freedesktop.org/wiki/Software/systemd/\">systemd</a>\nand the DBus APIs it provides to configure and monitor core aspects of\nthe system. Use of alternate system APIs are not currently implemented.</p>\n</div>\n<div class=\"paragraph\">\n<p>For non root users, systemd controls access to its APIs via\n<a href=\"#privileges\">Policy Kit</a> and a user logged into Cockpit will have\nthe same permissions as they do from the command line.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit retrieves information about the host and changes the hostname\nvia the <code>hostnamed</code> daemon. To perform similar tasks from the command\nline use the\n<a href=\"https://www.freedesktop.org/software/systemd/man/hostnamectl.html\"><code>hostnamectl</code></a>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ hostnamectl\n   Static hostname: pink.example.com\n   Pretty hostname: Pink\n         Icon name: computer-desktop\n           Chassis: desktop\n        Machine ID: ef00b79be229463cbb844c3e715de96c\n           Boot ID: 934983d64d34465cb5a8383b5a89ad8c\n  Operating System: Fedora 22 (Twenty Two)\n       CPE OS Name: cpe:/o:fedoraproject:fedora:22\n            Kernel: Linux 4.0.4-301.fc22.x86_64\n      Architecture: x86-64</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit configures the system time and time zone via the <code>timedated</code>\ndaemon. To perform similar tasks from the command line use the\n<a href=\"https://www.freedesktop.org/software/systemd/man/timedatectl.html\"><code>timedatectl</code></a>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ timedatectl list-timezones\nAfrica/Abidjan\nAfrica/Accra\nAfrica/Addis_Ababa\nAfrica/Algiers\n...</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit can manage the list of NTP servers used by <code>systemd-timesyncd</code>\nby putting its own file into <code>/etc/systemd/timesyncd.conf.d/</code>. Note\nthat <code>systemd-timesyncd</code> is not always enabled, depending on the\nconfiguration of the machine. In that case, Cockpit disabled the UI for\nmanaging the list of NTP servers. In some cases use of <code>ntpd</code> can\ncause the <code>timedated</code> daemon to behave inconsistently with regards to\ntime synchronization.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit reboots or powers down the machine by using the\n<a href=\"https://www.freedesktop.org/software/systemd/man/shutdown.html\"><code>shutdown</code></a>\ncommand. To perform similar tasks from the command line, run it\ndirectly:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo shutdown +15\nShutdown scheduled for Sa 2015-09-26 15:49:40 CEST, use 'shutdown -c' to cancel.</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit manages system services and sockets via systemd. To perform\nsimilar tasks from the command line use the\n<a href=\"https://www.freedesktop.org/software/systemd/man/systemctl.html\"><code>systemctl</code></a>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ systemctl status cockpit\n● cockpit.service - Cockpit Web Service\n   Loaded: loaded (/usr/lib/systemd/system/cockpit.service; static; vendor preset: disabled)\n  Drop-In: /etc/systemd/system/cockpit.service.d\n           └─debug.conf\n   Active: active (running) since Sa 2015-09-26 13:28:02 CEST; 2h 7min ago\n     Docs: man:cockpit-ws(8)\n Main PID: 6957 (cockpit-ws)\n   Memory: 1.8M\n   CGroup: /system.slice/cockpit.service\n           ├─ 6957 /usr/libexec/cockpit-ws\n           └─29598 /usr/bin/ssh-agent</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>In order to customize who can perform various actions in system,\n<a href=\"#privileges-polkit\">create polkit rules</a> with the following actions\nand details:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>org.freedesktop.systemd1.manage-units</code></dt>\n<dd>\n<p>Permission to manage system services or other units. Details\navailable: <code>unit</code>, <code>verb</code></p>\n</dd>\n<dt class=\"hdlist1\"><code>org.freedesktop.systemd1.manage-unit-files</code></dt>\n<dd>\n<p>Permission to manage system services or other unit files.</p>\n</dd>\n<dt class=\"hdlist1\"><code>org.freedesktop.systemd1.reload-daemon</code></dt>\n<dd>\n<p>Permission to reload the systemd state.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>For example, placing the following polkit rule to\n<code>/etc/polkit-1/rules.d/10-http.rule</code> allows all users in the\n<code>operators</code> group start, stop, and restart the Apache HTTP service:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>polkit.addRule(function(action, subject) {\n    if (action.id == \"org.freedesktop.systemd1.manage-units\") {\n        if (subject.isInGroup(\"operators\") &amp;&amp; action.lookup(\"unit\") == \"httpd.service\") {\n            var verb = action.lookup(\"verb\");\n            if (verb == \"start\" || verb == \"stop\" || verb == \"restart\") {\n                return polkit.Result.YES;\n            }\n        }\n    }\n});</pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"feature-journal\">Journal</h3>\n<div class=\"paragraph\">\n<p>The systemd journal provides Cockpit with indexed log data. This log\ndata is found on the Journal page, as well as in various other places\nwhen configuring services, storage, networking etc.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit accesses Journal data via the\n<a href=\"https://www.freedesktop.org/software/systemd/man/journalctl.html\"><code>journalctl</code></a>\ncommand. Similar tasks can be performed at the command line:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo journalctl -f -u docker\n...</pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"feature-networkmanager\">NetworkManager</h3>\n<div class=\"paragraph\">\n<p>If available on the system, Cockpit uses\n<a href=\"https://wiki.gnome.org/Projects/NetworkManager\">NetworkManager</a> and the\nDBus APIs it provides to interact with the system&#8217;s network\nconfiguration.</p>\n</div>\n<div class=\"paragraph\">\n<p>For non root users, NetworkManager controls access to its APIs via\n<a href=\"#privileges\">Policy Kit</a> and a user logged into Cockpit will have\nthe same permissions as they do from the command line.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use the\n<a href=\"https://fedoraproject.org/wiki/Networking/CLI\">nmcli</a> command:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ nmcli general status\nSTATE      CONNECTIVITY  WIFI-HW  WIFI     WWAN-HW  WWAN\nconnected  full          enabled  enabled  enabled  enabled</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Devices marked as \"not managed\" with the <code>NM_CONTROLLED=no</code> setting\nwill not be displayed in the interface.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"feature-firewall\">Firewall</h3>\n<div class=\"paragraph\">\n<p>Cockpit uses <a href=\"https://www.firewalld.org\">firewalld</a> to interact with the\nsystem&#8217;s firewall. No firewall configuration UI will be shown if\nfirewalld is not installed.</p>\n</div>\n<div class=\"paragraph\">\n<p>Firewalld controls access to its APIs via PolicyKit. The user logged\ninto Cockpit needs to have the appropriate permissions to view or modify\nthe settings.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit can currently only show, add, and remove predefined firewalld\nservices in the default zone.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use\n<a href=\"https://www.firewalld.org/documentation/man-pages/firewall-cmd.html\">firewall-cmd</a>.\nFor example, to get the same list of allowed services that Cockpit\ndisplays:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo firewall-cmd --list-services\ndhcpv6-client samba-client mdns ssh cockpit</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>To enable an additional service, use:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ firewall-cmd --add-service pop3\nsuccess</pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"feature-storaged\">storaged</h3>\n<div class=\"paragraph\">\n<p>If available on the system, Cockpit uses\n<a href=\"https://github.com/storaged-project/storaged/\"><code>storaged</code></a> to configure\nand monitor storage, disks, mounts etc. on the system. This\nfunctionality is present in the Cockpit <em>storaged</em> package.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>storaged</code> project is originally based on a project called\n<a href=\"https://www.freedesktop.org/wiki/Software/udisks/\"><code>udisks</code></a> and added\nsupport for many more features such as\n<a href=\"https://en.wikipedia.org/wiki/Logical_Volume_Manager_(Linux)\">LVM</a>,\n<a href=\"https://en.wikipedia.org/wiki/ISCSI\">iSCSI</a>,\n<a href=\"https://en.wikipedia.org/wiki/Linux_DM_Multipath\">Multipath</a>, and\n<a href=\"https://btrfs.wiki.kernel.org/index.php/Main_Page\">BTRFS</a>. The same tools\nand backwards compatible API are available between <code>storaged</code> and\n<code>udisks</code> the projects. Cockpit can use <code>udisks</code> but disables many of\nit&#8217;s storage related features, including updating <code>/etc/fstab</code> and\n<code>/etc/crypttab</code> for stability reasons.</p>\n</div>\n<div class=\"paragraph\">\n<p>For non root users, storaged controls access to its APIs via\n<a href=\"#privileges\">Policy Kit</a> and a user logged into Cockpit will have\nthe same permissions as they do from the command line.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use the <code>storagedctl</code>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ udisksctl dump\n...</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>To perform LVM tasks, you may use the various LVM commands, such as\n<code>vgcreate</code>, <code>lvresize</code> and so on. Cockpit will detect such changes\nmade at the command line.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit recognizes devices with multiple paths and can start the\n<code>multipathd</code> service in case it is not running. On the command line,\nyou can control multipath features with the <code>mpathconf</code>,\n<code>multipathd</code>, and <code>multipath</code> commands.</p>\n</div>\n<div class=\"paragraph\">\n<p>To manage iSCSI initiators from the command line, you can use\n<code>iscsiadm</code> and related tools.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"feature-users\">User Tools</h3>\n<div class=\"paragraph\">\n<p>Cockpit uses the usual tools to create and modify local user accounts.\nExamples are <code>useradd</code>, <code>usermod</code> and <code>passwd</code>. These same tools\nare available for use on the command line.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"feature-realmd\">realmd</h3>\n<div class=\"paragraph\">\n<p>If available on the system, Cockpit uses\n<a href=\"https://www.freedesktop.org/software/realmd/\">realmd</a> and the DBus APIs\nit provides to configure the system&#8217;s Active Directory or IPA domain\nmembership.</p>\n</div>\n<div class=\"paragraph\">\n<p>Not all systems can join all kinds of domains. This depends on the\navailability of the necessary client software.</p>\n</div>\n<div class=\"paragraph\">\n<p>For non root users, realmd controls access to its APIs via\n<a href=\"#privileges\">Policy Kit</a> and a user logged into Cockpit will have\nthe same permissions as they do from the command line.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use the\n<a href=\"https://www.freedesktop.org/software/realmd/docs/realm.html\">realm</a>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ realm join example.com\nPassword for Administrator:</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p><a href=\"http://www.freedesktop.org/software/realmd/\">realmd</a> sets up\ndomain-qualified user names by default, i. e. login user names look like\n&#8220;user@example.com&#8221;. For using unqualified names (just &#8220;user&#8221;),\nset the <code>fully-qualified-names</code> option in\n<a href=\"https://www.freedesktop.org/software/realmd/docs/realmd-conf.html\">/etc/realmd.conf</a>\nbefore joining a domain.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit requests an SSL certificate from the IPA server for\n<code>cockpit-ws</code> with the\n<a href=\"https://www.freeipa.org/page/Certmonger\">ipa-getcert</a> command.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"feature-terminal\">Terminal</h3>\n<div class=\"paragraph\">\n<p>Cockpit provides a standard shell in a terminal. This shell and the\nprocesses running in it have the <a href=\"#privileges\">same privileges</a> as if\nthe user had logged in via SSH.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"feature-pcp\">PCP Metrics</h3>\n<div class=\"paragraph\">\n<p>If available, Cockpit uses the <a href=\"https://pcp.io/\">Performance Co-Pilot</a>\nframework to gather metrics data about the system. This data is used to\ndisplay the history graphs on the \"Metrics and history\" page. Cockpit\ncan use the PCP logging feature to display archived data about the\nsystem from a different point in time. If PCP is not available, then\nCockpit gathers the metrics data itself, but archival features are not\navailable.</p>\n</div>\n<div class=\"paragraph\">\n<p>Whether or not metrics are archived depends on whether the\n<a href=\"https://linux.die.net/man/1/pmlogger\"><code>pmlogger.service</code></a> systemd unit\nis running or not. The \"Enable PCP metrics collector\" button on the\nMetrics page will enable and start this service.</p>\n</div>\n<div class=\"paragraph\">\n<p>To see similar metrics data from the command line, you can use tools\nlike <a href=\"https://linux.die.net/man/1/pmstat\"><code>pmstat</code></a> or\n<a href=\"https://linux.die.net/man/1/pminfo\"><code>pminfo</code></a>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ pmstat\n@ Sat Sep 26 15:30:10 2015\n loadavg                      memory      swap        io    system         cpu\n   1 min   swpd   free   buff  cache   pi   po   bi   bo   in   cs  us  sy  id\n    4.19      0 20710m 605148  6450m    0    0    0 2548 5688  14K  19   3  76\n...</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>These metrics can also be exposed to other machines on a TCP port with\n<a href=\"https://linux.die.net/man/1/pmproxy\">pmproxy</a> and\n<a href=\"https://redis.io/\">Redis</a> or <a href=\"https://valkey.io/\">Valkey</a>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>systemctl enable --now redis pmproxy\n# if you use firewalld, open port 44322:\nfirewall-cmd --permanent --add-service pmproxy\nfirewall-cmd --reload</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This allows you to gather and visualize PCP metrics from multiple\nmachines with <a href=\"https://grafana.com/\">Grafana</a> and the\n<a href=\"https://grafana-pcp.readthedocs.io\">PCP Grafana plugin</a>.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"feature-machines\">Multiple Machines</h3>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>This feature is deprecated as of Cockpit 322.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit can connect to multiple machines from a single Cockpit session.\nThese are listed in the host switcher.</p>\n</div>\n<div class=\"paragraph\">\n<p>These additional machines are accessed via SSH from the machine that the\nfirst machine connected to, and are <a href=\"#authentication\">authenticated</a>\nwith the logged in user&#8217;s password and/or SSH keys.</p>\n</div>\n<div class=\"paragraph\">\n<p>SSH host keys are stored in <code>/etc/ssh/ssh_known_hosts</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The machine data is stored in <code>/etc/cockpit/machines.d/*.json</code>, or\nbelow <code>$XDG_CONFIG_DIRS</code> if set (see\n<a href=\"./cockpit.conf.5.html\">cockpit.conf</a>). Settings in lexicographically\nlater files amend or override settings in earlier ones. Cockpit itself\nwrites into <code>99-webui.json</code>; packages or admins who want to\npre-configure machines should ship files like <code>05-mymachine.json</code> so\nthat changes from the web interface override the pre-configured files.</p>\n</div>\n<div class=\"paragraph\">\n<p>Each JSON file contains an object that maps machine IDs to objects that\ndefine the properties of that machine. The ID can be a human readable\nname or an IP address or any other unique value, and is shown in the web\ninterface until connecting to it the first time, at which point the web\ninterface will show the machine&#8217;s host name.</p>\n</div>\n<div class=\"paragraph\">\n<p>The following properties are recognized:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"address\"</code></dt>\n<dd>\n<p><em>(string, mandatory)</em> IP address or DNS name of the machine</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"visible\"</code></dt>\n<dd>\n<p><em>(boolean, optional)</em> If <code>true</code>, the machine will be displayed and\navailable for managing with Cockpit. If <code>false</code> (the default), it\nwill not be displayed, but still taken into account for type-ahead\nsearch when adding new machines in the web interface.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"user\"</code></dt>\n<dd>\n<p><em>(string, optional)</em> User name on the remote machine. When not given,\nCockpit will default to the user name that was being used to log into\nCockpit itself.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"port\"</code></dt>\n<dd>\n<p><em>(integer, optional)</em> ssh port of the remote machine. When not given,\nthe default port 22 is used.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"color\"</code></dt>\n<dd>\n<p><em>(string, optional)</em> Color to assign to the machine label in the web\ninterface. This can be either given as\n<code>rgb(r_value, g_value, b_value)</code> with each value being an integer\nbetween 0 and 255, or as a color name like <code>yellow</code>. When not given,\nCockpit will assign an unused color automatically.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Example:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n    \"web server\": {\n        \"address\": \"192.168.2.4\",\n        \"visible\": true,\n        \"color\": \"rgb(100, 200, 0)\",\n        \"user\": \"admin\"\n    },\n    \"192.168.2.1\": {\n        \"address\": \"192.168.2.1\",\n        \"port\": 2222,\n        \"visible\": true,\n        \"color\": \"green\"\n    }\n}</pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"feature-selinux\">SELinux Policy</h3>\n<div class=\"paragraph\">\n<p>If present on the system Cockpit can set the SELinux mode to enforcing\nor permissive. It can also use <code>setroubleshootd</code> to show audit issues\nand apply suggested fixes.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line use the <code>setenforce</code>\nand <code>sealert</code> tools.</p>\n</div>\n<div class=\"paragraph\">\n<p>To clear out all the information that <code>setroubleshootd</code> tracks, you\ncan use a commands like:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo killall setroubleshootd\n$ sudo rm -rf /var/lib/setroubleshoot/*</pre>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"feature-tuned\">Tuned Profiles</h3>\n<div class=\"paragraph\">\n<p>If present on the system Cockpit can use Tuned and the DBUS API it\nprovides to set system performance profiles. To perform similar tasks\nfrom the command line, use the <code>tuned-adm</code> command.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"feature-sosreport\">SOS Report</h3>\n<div class=\"paragraph\">\n<p>If present on the system Cockpit can use <code>sosreport</code> to collect system\nconfiguration and diagnostic information.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use the <code>sosreport</code>\ncommand.</p>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"feature-packagekit\">Package Updates</h3>\n<div class=\"paragraph\">\n<p>Cockpit uses the\n<a href=\"https://www.freedesktop.org/software/PackageKit/gtk-doc/api-reference.html\">PackageKit</a>\nD-Bus API to get information about available package updates and to\napply them, in an Operating System independent manner.</p>\n</div>\n<div class=\"paragraph\">\n<p>To perform similar tasks from the command line, use the\n<a href=\"https://www.freedesktop.org/software/PackageKit/pk-using.html\">pkcon</a>\ncommand:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ pkcon refresh\n\n$ pkcon get-updates\nAvailable  sudo-1.8.20p2-1.fc26.x86_64 (updates-testing)\n    Allows restricted root access for specified users\nAvailable  vim-filesystem-2:8.0.617-1.fc26.x86_64 (updates-testing)\n    VIM filesystem layout\nAvailable  vim-minimal-2:8.0.617-1.fc26.x86_64 (updates-testing)\n    A minimal version of the VIM editor\n\n$ pkcon get-update-detail sudo\nDetails about the update:6.x86_64 [fedora]\n Package: sudo-1.8.20p2-1.fc26.x86_64\n Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1452941\n Update text: - update to 1.8.20p2\n    - added sudo package to dnf/yum protected packages\n\n$ pkcon update\nThe following packages have to be updated:\n sudo-1.8.20p2-1.fc26.x86_64    Allows restricted root access for specified users\n vim-filesystem-2:8.0.617-1.fc26.x86_64 VIM filesystem layout\n vim-minimal-2:8.0.617-1.fc26.x86_64    A minimal version of the VIM editor\nProceed with changes? [N/y] y\n[...]</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Of course you can also use your Operating System specific commands for\nthat, such as <code>dnf updateinfo info</code> on Fedora or <code>sudo apt upgrade</code>\non Debian.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"development\">Developer Guide</h2>\n<div class=\"sectionbody\">\n<div class=\"sect2\">\n<h3 id=\"embedding\">Embedding and Integrating Cockpit</h3>\n<div class=\"paragraph\">\n<p>Cockpit can be embedded in other web applications either as a whole or\nspecific Cockpit components can be integrated. Due to frame security\npolicy restrictions, this only works if Cockpit and the web application\nhave the <em>same origin</em>; this is commonly achieved by running both from a\ncommon reverse proxy.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"embedding-full\">Embedding the Cockpit Interface</h4>\n<div class=\"paragraph\">\n<p>Cockpit can be embedded into a larger web page as a frame. To embed the\nentire Cockpit Window use the URI: <code>https://server.example.com:9090/</code></p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-html\" data-lang=\"html\">&lt;html&gt;\n  &lt;head&gt;\n    &lt;title&gt;Embedded Cockpit&lt;/title&gt;\n  &lt;/head&gt;\n  &lt;body&gt;\n    This is Cockpit.\n    &lt;br/&gt;\n    &lt;iframe width=\"800px\" height=\"600px\"\n            src=\"https://server.example.com:9090/\"/&gt;\n  &lt;/body&gt;\n&lt;/html&gt;</code></pre>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"embedding-components\">Integrating Cockpit Components into Web Applications</h4>\n<div class=\"paragraph\">\n<p>Instead of embedding the entirety of Cockpit, you can integrate specific\ncomponents. Only those components explicitly documented as API should be\nintegrated. Other components can and will change regularly.</p>\n</div>\n<div class=\"paragraph\">\n<p>The component will load from the server in question and a WebSocket\nconnection will be established with the server to relay the component&#8217;s\nmessage stream.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit components are HTML files contained in <a href=\"#packages\">packages</a>.\nThese can be placed in an iframe or web browser window. Each documented\nand stable component has a well-known URL and these are documented in\nthe <a href=\"#development\">API reference</a>. Each component URL begins with the\nstring <code>/cockpit/@localhost/</code> followed a package name, and then the\ncomponent itself.</p>\n</div>\n<div class=\"paragraph\">\n<p>For example the <a href=\"#api-terminal-html\">terminal.html</a> in the\n<a href=\"#api-system\">system</a> package, has this URL:\n<code>/cockpit/@localhost/system/terminal.html</code></p>\n</div>\n<div class=\"listingblock\">\n<div class=\"content\">\n<pre class=\"highlight\"><code class=\"language-html\" data-lang=\"html\">&lt;html&gt;\n  &lt;head&gt;\n    &lt;title&gt;Embedded Terminal&lt;/title&gt;\n  &lt;/head&gt;\n  &lt;body&gt;\n    This is a terminal.\n    &lt;br/&gt;\n    &lt;iframe width=\"800px\" height=\"600px\"\n      src=\"https://server.example.com:9090/cockpit/@localhost/system/terminal.html\"/&gt;\n  &lt;/body&gt;\n&lt;/html&gt;</code></pre>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"embedding-deep\">Deep Integration</h4>\n<div class=\"paragraph\">\n<p>Most often <a href=\"#embedding-components\">simple integration</a> will be used\nto bring Cockpit components into web applications. However it is also\npossible to do deep integration for embedders who wish to perform\nnon-standard authentication with the server, and relay the component&#8217;s\nmessage stream to the server themselves.</p>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>Deep integration capability is in heavy flux and is not yet documented.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"embedding-cors\">Pinging Cockpit</h4>\n<div class=\"paragraph\">\n<p>When embedding Cockpit or integrating Cockpit components, it may be\nnecessary to check whether Cockpit is available on a server before\nproceeding.</p>\n</div>\n<div class=\"paragraph\">\n<p>To do this perform a <code>/ping</code> request to Cockpit. This is a simple HTTP\nGET request. It returns the following:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>GET: https://server.example.com:9090/ping\n200 OK: { \"service\": \"cockpit\" }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <code>/ping</code> request allows\n<a href=\"https://en.wikipedia.org/wiki/Cross-origin_resource_sharing\">Cross Origin\nResource Sharing</a> headers and as such can be performed from Javascript\ncode with any origin. The request can also be made via plain HTTP\nwithout SSL. It is by design that no further information is present in\nthe response.</p>\n</div>\n<div class=\"paragraph\">\n<p>A complete example of using <code>/ping</code> is available in the Cockpit\nsources in the <code>/examples/ping-server/</code> directory.</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"packages\">Cockpit Packages</h3>\n<div class=\"paragraph\">\n<p>Cockpit is separated into various packages, each of which brings\nspecific features and/or code.</p>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>In addition, any APIs or behavior not explicitly documented here is an\ninternal API and can be changed at any time.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n<div class=\"sect3\">\n<h4 id=\"package-layout\">Layout of Package Files</h4>\n<div class=\"paragraph\">\n<p>A package consists of one or more files placed in a directory or its\nsubdirectories. It must have a <code>manifest.json</code> file and follow certain\nnaming conventions.</p>\n</div>\n<div class=\"paragraph\">\n<p>The name of a package is the name of the directory.</p>\n</div>\n<div class=\"paragraph\">\n<p>The name of the package must be ASCII alphanumeric, and may contain an\nunderscore. Names of directories and files in the package must consist\nof ASCII alphanumeric along with dash, underscore, dot, and comma. No\nspaces are allowed.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit uses the data directories from the\n<a href=\"https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html\">XDG\nBase Directory Specification</a> to locate packages. The <code>$XDG_DATA_DIRS</code>\nrepresents a colon separate list of system data directories, and\n<code>$XDG_DATA_HOME</code> is a user specific data directory. If the environment\nvariables are not set, defaults are used, according to the spec. If\ncockpit has been built with an alternate <code>--prefix=/path</code> then the\n<code>$prefix/share/cockpit</code> is used by default.</p>\n</div>\n<div class=\"paragraph\">\n<p>A <code>cockpit/</code> subdirectories in any of these data directories is the\nlocation where packages are loaded by Cockpit. If Cockpit finds a\npackage with the same name, in multiple data directories, then the first\none wins. According to the spec the first data directory is\n<code>$XDG_DATA_HOME</code> and then <code>$XDG_DATA_DIRS</code> in order.</p>\n</div>\n<div class=\"paragraph\">\n<p>This means that, by default the following directories are searched for\ncockpit packages, and in this order:</p>\n</div>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><code>~/.local/share/cockpit/</code></p>\n</li>\n<li>\n<p><code>/usr/local/share/cockpit/</code></p>\n</li>\n<li>\n<p><code>/usr/share/cockpit/</code></p>\n</li>\n</ul>\n</div>\n<div class=\"paragraph\">\n<p>Packages placed in <code>$XDG_DATA_HOME</code> are not cached by Cockpit or the\nweb browser. Other packages are cached aggressively, and are accessed\nusing a checksum of the files in the packages and their names.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can use the following command to list the packages installed on a\nserver. You&#8217;ll note that it&#8217;s output may change when you run the command\nas different users, if there are packages installed in the user&#8217;s home\ndirectory.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ cockpit-bridge --packages\n...</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>To further clarify things, here is an example package called\n\"my-package\" and its file layout:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>/usr/share/cockpit/\n    my-package/\n        manifest.json\n        file.html\n        some.js</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Place or symlink packages in your <code>~/.local/share/cockpit</code> directory\n(or appropriate <code>$XDG_DATA_HOME</code> location) that you would like to\nmodify and develop. System installed packages should not change while\nCockpit is running.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_package_manifest\">Package Manifest</h4>\n<div class=\"paragraph\">\n<p>Each package has a <code>manifest.json</code> file. It is a JSON object. The\nfollowing fields may be present in the manifest:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">content-security-policy</dt>\n<dd>\n<p>By default Cockpit serves packages using a strict\n<a href=\"https://en.wikipedia.org/wiki/Content_Security_Policy\">Content Security\nPolicy</a>, which among other things does not allow inline styles or\nscripts. This can be overridden on a per-package basis, with this\nsetting.\n+\nIf the overridden content security policy does not contain a\n<code>default-src</code>, <code>connect-src</code>, <code>base-uri</code>, <code>form-action</code>,\n<code>object-src</code>, or <code>block-all-mixed-content</code> then these will be\nadded to the policy from the manifest.</p>\n</dd>\n<dt class=\"hdlist1\">name</dt>\n<dd>\n<p>An optional string that changes the name of the package. Normally\npackages derive their name from the directory that they are located\nin. This field overrides that name.</p>\n</dd>\n<dt class=\"hdlist1\">priority</dt>\n<dd>\n<p>An optional number that specifies which package is preferred in cases\nwhere there are conflicts. For example given two packages with the\nsame <code>name</code> a package is chosen based on its priority.</p>\n</dd>\n<dt class=\"hdlist1\">conditions</dt>\n<dd>\n<p>An optional list of <code>{\"predicate\": \"value\"}</code> objects. Cockpit will\nonly consider the package if <em>all</em> conditions are met. This is\npreferable to using <code>priority</code>.<br>\n<br>\nCurrently supported predicates are <code>path-exists</code> and <code>path-not-exists</code>\n(since Cockpit 286) and <code>any</code> (since Cockpit 348). <code>any</code> accepts a\nlist of conditions and evaluates to true if <em>at least one</em> of the nested\nconditions is met. Unknown predicates are ignored.</p>\n</dd>\n<dt class=\"hdlist1\">requires</dt>\n<dd>\n<p>An optional JSON object that contains a <code>\"cockpit\"</code> string version\nnumber. The package will only be usable if the Cockpit bridge and\njavascript base are equal or newer than the given version number.</p>\n</dd>\n<dt class=\"hdlist1\">version</dt>\n<dd>\n<p>An informational version number for the package.</p>\n</dd>\n<dt class=\"hdlist1\">preload</dt>\n<dd>\n<p>A list of identifiers of the components that should be preloaded.\nNormally, the files of a component are loaded when the user navigates\nto it for the first time. The files of a preloaded component are\nloaded immediately after the user logs in, and the initialization code\nof the component is invoked.\n+\nThe value of this field is an array of strings, where each string is\none of the keys used in the <code>dashboard</code>, <code>menu</code>, or <code>tool</code>\nfields that are explained below.</p>\n</dd>\n<dt class=\"hdlist1\">parent</dt>\n<dd>\n<p>This option is used when module does not have its own menu item but is\na part of a different module. This is described by JSON object with\nproperties <code>component</code> which takes name of the superordinate\ncomponent and <code>docs</code> with list of documentation URLs for the given\npage. See below for structure of <code>docs</code> property.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>In addition, the following keys contain information about where\ncomponents of the package should appear in Cockpit&#8217;s user interface.\nEach of these keys is optional and contains an object mapping unique\nidentifiers to menu items, which are described below. (The naming of\nthese fields doesn&#8217;t perfectly match the current user interface for\nhistorical reasons.)</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">dashboard</dt>\n<dd>\n<p>Dashboard items appear in the menu under the section <em>Apps</em>.</p>\n</dd>\n<dt class=\"hdlist1\">menu</dt>\n<dd>\n<p>These items appear in the menu under the section <em>System</em>. This\nsection is roughly ordered into these categories (with their <em>order</em>\nin parentheses):\n+</p>\n<div class=\"ulist\">\n<ul>\n<li>\n<p>System Information (10)</p>\n</li>\n<li>\n<p>Logs (20)</p>\n</li>\n<li>\n<p>Configuring major subsystems (30-40)</p>\n</li>\n<li>\n<p>Things running on the machine (VMs, Containers - 50-60)</p>\n</li>\n<li>\n<p>Implementation Details (Accounts, Services - 70-100)</p>\n</li>\n</ul>\n</div>\n</dd>\n<dt class=\"hdlist1\">tools</dt>\n<dd>\n<p>These items appear in the menu under the section <em>Tools</em>.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Menu items and tools are registered using JSON objects that have the\nfollowing properties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">label</dt>\n<dd>\n<p>The label for the menu item or tool.</p>\n</dd>\n<dt class=\"hdlist1\">order</dt>\n<dd>\n<p>An optional order number to place this menu item or tool. Lower\nnumbers are listed first.</p>\n</dd>\n<dt class=\"hdlist1\">path</dt>\n<dd>\n<p>The relative path to the HTML file within the package that implements\nthe menu item or tool.</p>\n</dd>\n<dt class=\"hdlist1\">docs</dt>\n<dd>\n<p>List of documentation URLs for the given page. Each item is an object\ncontaining <code>label</code> and <code>url</code>.</p>\n</dd>\n<dt class=\"hdlist1\">keywords</dt>\n<dd>\n<p>Keywords that describe the page and which are used for searching.\nThese keywords should be lowercase. Keywords is a list containing\nkeyword items as described below. Page label is prepended as first\nkeyword in the first keyword item.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Keyword items are registered using JSON objects that have the following\nproperties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">matches</dt>\n<dd>\n<p>List of keywords to be matched.</p>\n</dd>\n<dt class=\"hdlist1\">goto</dt>\n<dd>\n<p>Optional path that is used for all keywords in this item. When this\nargument starts with slash, then it is used as pathname, otherwise it\nis used as hash. Defining <code>goto:\"page_hash\"</code> in page with\n<code>path:\"/page_path\"</code> would redirect to <code>/page_path#page_hash</code>,\nwhile <code>goto:\"/page_path\"</code> would redirect to <code>/page_path</code> ignoring\ndefault page path.</p>\n</dd>\n<dt class=\"hdlist1\">weight</dt>\n<dd>\n<p>How much keywords are prioritized over others. Default is 3.</p>\n</dd>\n<dt class=\"hdlist1\">translate</dt>\n<dd>\n<p><code>false</code> when keywords should not be localized. Default is <code>true</code>.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>An example manifest.json with some optional properties set:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"version\": 0,\n  \"require\": {\n      \"cockpit\": \"120\"\n  },\n  \"tools\": {\n     \"mytool\": {\n        \"label\": \"My Tool\",\n        \"path\": \"tool.html\"\n     }\n  }\n}</pre>\n</div>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"version\": 0,\n  \"require\": {\n    \"cockpit\": \"120\"\n  },\n  \"conditions\": [\n    {\"path-exists\": \"/usr/bin/mytool\"},\n    {\"path-exists\": \"/etc/mytool.conf\"},\n    {\"path-not-exist\": \"/etc/incompatible-tool\"}\n  ],\n  \"tools\": {\n     \"mytool\": {\n        \"label\": \"My Tool\",\n        \"path\": \"tool.html\"\n     }\n  }\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The following example shows how to use disjunctive conditions with <code>any</code>\nto specify alternative requirements (available since Cockpit 348). This\npackage will be available if either <code>/usr/bin/alt1</code> or <code>/usr/bin/alt2</code>\nexists. In any case, <code>/etc/incompatible-tool</code> must not exist.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>\"conditions\": [\n  {\"any\": [{\"path-exists\": \"/usr/bin/alt1\"}, {\"path-exists\": \"/usr/bin/alt2\"}]},\n  {\"path-not-exists\": \"/etc/incompatible-tool\"}\n]</pre>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"package-manifest-override\">Manifest overrides</h4>\n<div class=\"paragraph\">\n<p>To change a manifest system-wide, a file\n<code>&lt;package-directory-name&gt;.override.json</code> may be placed into\n<code>/etc/cockpit/</code>, or below <code>$XDG_CONFIG_DIRS</code> if set (see\n<a href=\"./cockpit.conf.5.html\">cockpit.conf</a>). To change it for a particular\nuser only, put the override into <code>~/.config/cockpit</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>These override the information in the manifest in the simple\n<a href=\"https://tools.ietf.org/html/rfc7386\">JSON Merge Patch</a> format.</p>\n</div>\n<div class=\"paragraph\">\n<p>This can be used to hide or modify menu items of an existing package.\nFor example <code>/etc/cockpit/systemd.override.json</code> or\n<code>~/.config/cockpit/systemd.override.json</code> could hide the <em>Logs</em> menu\nitem and move the <em>Services</em> menu item to the top of the menu.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"menu\": {\n    \"logs\": null,\n    \"services\": {\n      \"order\": -1\n    }\n  }\n}</pre>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"package-links\">Package Links and Paths</h4>\n<div class=\"paragraph\">\n<p>When referring to files in your package, such as in a hyperlink or a\n<code>&lt;style&gt;</code> tag or <code>&lt;script&gt;</code> tag, simply use a relative path, and\nrefer to the files in the same directory. When you need to refer to\nfiles in another package use a relative link.</p>\n</div>\n<div class=\"paragraph\">\n<p>For example here&#8217;s how to include the base <code>cockpit.js</code> script in your\nHTML from the <code>latest</code> package:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;script src=\"../base1/cockpit.js\"&gt;&lt;/script&gt;</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Do not assume you can link to any file in any other package. Refer to\nthe <a href=\"#development\">list of API packages</a> for those that are available\nfor use.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"package-minified\">Content Negotiation</h4>\n<div class=\"paragraph\">\n<p>In order to support gzipped and/or minified data, the files in a package\nare loaded using content negotiation logic. A HTTP request for the file\n<code>test.js</code> in the package named <code>mypackage</code> will return\n<code>mypackage/test.js</code> or <code>mypackage/test.js.gz</code> (in undefined\npreference). If neither exists, then it returns\n<code>mypackage/test.js.min</code> or <code>mypackage/test.js.min.gz</code> (again in\nundefined preference).</p>\n</div>\n<div class=\"paragraph\">\n<p>When packages are loaded from a system directory, Cockpit optimizes the\nfile system lookups above, by pre-listing the files. This is one of the\nreasons that you should never change packages installed to a system\ndirectory while Cockpit is running.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"package-api\">Using Cockpit API</h4>\n<div class=\"paragraph\">\n<p>Cockpit has API available for writing packages. There is no API\navailable for external callers to invoke via HTTP, REST or otherwise.</p>\n</div>\n<div class=\"paragraph\">\n<p>API from various packages can be used to implement Cockpit packages.\nEach package listed here has some API available for use. Only the API\nexplicitly documented should be used.</p>\n</div>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><a href=\"#development\">API Listing</a></p>\n</li>\n</ul>\n</div>\n<div class=\"paragraph\">\n<p>To include javascript from the API, simply load it into your HTML using\na script tag. Alternatively you can use an javascript loader.</p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"package-bridges\">Bridges for specific tasks</h4>\n<div class=\"paragraph\">\n<p>On the server side the <a href=\"#cockpit-bridge.1\"><code>cockpit-bridge</code></a>\nconnects to various system APIs that the front end UI requests it to.\nThere are additional bridges for specific tasks that the main\n<code>cockpit-bridge</code> cannot handle, such as using the PCP C library API.</p>\n</div>\n<div class=\"paragraph\">\n<p>These additional bridges can be registered in a <code>\"bridges\"</code> section of\na package&#8217;s <code>manifest.json</code> file. Building such a bridge is a complex\ntasks, and we will skip over that here. However it is useful to adjust\nhow these additional bridges are called, and so we&#8217;ll look at how they\nare registered.</p>\n</div>\n<div class=\"paragraph\">\n<p>An example <code>manifest.json</code> with a bridges section:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n    \"bridges\": [\n        {\n            \"match\": { \"payload\": \"metrics1\" },\n            \"spawn\": [ \"/usr/libexec/cockpit-pcp\" ]\n        }\n    ]\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The bridges are considered in the order they are listed in the array.\nUse the <code>manifest.json`</code>\"priority\"` field to control order between\npackages. The bridges are registered using JSON objects that have the\nfollowing properties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">environ</dt>\n<dd>\n<p>Optional, additional environment variables to pass to the bridge\ncommand.</p>\n</dd>\n<dt class=\"hdlist1\">match</dt>\n<dd>\n<p>The <code>\"match\"</code> object describes which channel open command options\nneed to match for a given channel to be handed over to this bridge.</p>\n</dd>\n<dt class=\"hdlist1\">privileged</dt>\n<dd>\n<p>If set to <code>true</code>, this marks the bridge as a superuser bridge.\nCockpit will start one of these explicitly when trying to escalate the\nprivileges of a session. A privileged bridge can not have a\n<code>\"match\"</code> property.</p>\n</dd>\n<dt class=\"hdlist1\">label</dt>\n<dd>\n<p>Setting this enables selection of privileged bridges in the UI. When\nno privileged bridge has a <code>label</code>, then Cockpit will start the\nbridge that runs <code>sudo</code>. This is the case in a default Cockpit\ninstallation. When at least one privileged bridge has a <code>label</code> then\nthe user can select one of them when escalating privileges. As a\nspecial case, if only one bridge has a <code>label</code>, then the step of\nselecting a bridge is omitted in the UI and that one bridge is always\nstarted.\n+\nThus, if you add a privileged bridge with a <code>label</code> in a new\nmanifest, Cockpit will use that bridge the next time a user opens the\n\"Administrative access\" dialog. If you want the user to choose between\nthe <code>sudo</code> method and your new one, you need to duplicate the\n<code>sudo</code> bridge definition in your manifest and give it a label.</p>\n</dd>\n<dt class=\"hdlist1\">problem</dt>\n<dd>\n<p>If a problem is specified, and this bridge fails to start up then\nchannels will be closed with this problem code. Otherwise later\nbridges or internal handlers for the channel will be invoked.</p>\n</dd>\n<dt class=\"hdlist1\">spawn</dt>\n<dd>\n<p>The command and arguments to invoke.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The <code>spawn</code> and <code>environ</code> values can be dynamically taken from a\nmatching open command values. When a value in either the <code>spawn</code> or\n<code>environ</code> array contains a named variable wrapped in <code>${}</code>, the\nvariable will be replaced with the value contained in the matching open\ncommand. Only named variables are supported and name can only contain\nletters, numbers and the following symbols: <code>._-</code></p>\n</div>\n<div class=\"paragraph\">\n<p>For example a bridges section like:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"bridges\": [\n    {\n      \"match\": { \"payload\": \"example\" },\n      \"environ\": [ \"TAG=${tag}\" ],\n      \"spawn: [ \"/example-bridge\", \"--tag\", \"${tag}\" ],\n      \"problem\": \"access-denied\"\n    }\n  ]\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>when a open command is received with a payload of <code>example</code> with\n<code>tag</code> value of <code>tag1</code>. The following command will be spawned</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>TAG=tag1 /example-bridge --tag tag1</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Processes that are reused so if another open command with a \"tag\" of\n<code>tag1</code> is received. The open command will be passed to existing\nprocess, rather than spawning a new one. However a open command with an\ntag of <code>tag2</code> will spawn a new command:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>TAG=tag2 /example-bridge --tag tag2</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If you need to include <code>${}</code>, as an actual value in your arguments you\ncan escape it by prefixing it with a <code>\\</code></p>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"package-replace\">Replacing an existing package</h4>\n<div class=\"paragraph\">\n<p>If the functionality in a package replaces that of another package then\nit can replace that package by claiming the same <code>name</code> and a higher\n<code>priority</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>For example, a package in the <code>/usr/share/cockpit/disks</code> directory\ncould replace Cockpit&#8217;s <em>storage</em> package with a <code>manifest.json</code> like\nthis:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"version\": 0,\n  \"name\": \"storage\",\n  \"priority\": 10,\n  \"menu\": {\n     \"index\": {\n        \"label\": \"Disk Storage\",\n        \"order\": 15\n     }\n  }\n}</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"urls\">Cockpit URLs</h3>\n<div class=\"paragraph\">\n<p>Cockpit URLs follow a specific structure, related to the components they\nare loading. Various components are loaded in <code>&lt;iframe&gt;</code> tags. The\nURLs for these components are described first. Further down below you\ncan find information about the top level bookmarkable Cockpit address\nURLs.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"urls-components\">Component URLs</h4>\n<div class=\"paragraph\">\n<p>Cockpit components are HTML documents. They are organized into\n<a href=\"#packages\">packages</a>. Each package contains information about which\nHTML components are available in that package. Components should always\nuse relative URLs to access resources, such as images, scripts or CSS\nfiles, even if they refer to a resource in another package.</p>\n</div>\n<div class=\"paragraph\">\n<p>The following are valid component URLs, each bit will be discussed\nbelow:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>/cockpit/@localhost/package/component.html#/hash\n/cockpit/$checksum/package/component.html#/hash\n/cockpit/@server.example.com/package/component.html#/hash\n/cockpit+embedder/@localhost/package/component.html#/hash</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>All resource URLs are under the <code>/cockpit</code> namespace. In cases where a\nCockpit component is being <a href=\"#embedding\">embedded</a> the <code>/cockpit</code>\nmay be followed by a plus sign and another <code>embedder</code> specific\nidentifier.</p>\n</div>\n<div class=\"paragraph\">\n<p>What follows is either a <code>@host</code> or <code>$checksum</code> which tells cockpit\nwhere to <a href=\"#packages\">find the package</a>. Checksums are used when more\nthan one host has identical packages and the resources can be cached.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>package</code> name is next, followed by the <code>component</code> HTML path\ninside that package. And lastly a hash allows for navigation within a\nsingle component. The hash should follow a URL path and/or query string\nform.</p>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>Never assume that the <code>@host</code> or <code>$checksum</code> portion is predictable.\nOnly refer to resources in packages on the same host.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"urls-visible\">Visible URLs</h4>\n<div class=\"paragraph\">\n<p>The above Component URLs are usually not visible to the user. Instead\nthe Cockpit Web Service wraps the components in a shell which allows\nnavigation, and provides bookmarkable clean URLs to the component. These\nURLs do not affect <a href=\"#embedding\">embedders</a> or\n<a href=\"#packages\">components</a> directly.</p>\n</div>\n<div class=\"paragraph\">\n<p>If no path is present then the Cockpit will redirect to the default page\nfor the server.</p>\n</div>\n<div class=\"paragraph\">\n<p>If the first segment of the path begins with an <code>@</code> sign, then the\ncomponent is being shown from a non-local host.</p>\n</div>\n<div class=\"paragraph\">\n<p>The next segment of the path, (or first if the component is being shown\non the local host) is the <a href=\"#packages\">package name</a>. The remainder of\nthe path is a component file in the package. If no further path segments\nare present, a default <code>index.html</code> component in the package is\nloaded. An extension of <code>.html</code> is automatically appended.</p>\n</div>\n<div class=\"paragraph\">\n<p>The hash portion of the path is automatically transferred to the\ncomponent as the hash of its <a href=\"#urls-components\">resource URL</a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_api_base1\">API: base1</h3>\n<div class=\"paragraph\">\n<p>This package contains basic support API available to other packages.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_js\">cockpit.js</h4>\n<div class=\"paragraph\">\n<p>Basic cockpit API to interact with the system</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"api-cockpit-loading\">Loading cockpit.js</h5>\n<div class=\"paragraph\">\n<p><code>cockpit.js</code> should be loaded via a script tag.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;script src=\"../base1/cockpit.js\"&gt;</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_js_object_caching\">cockpit.js: Object Caching</h4>\n<div class=\"paragraph\">\n<p>If the same information is displayed by multiple components in Cockpit,\n<code>cockpit.cache()</code> provides a way to share data between them. The\nshared data should be simple objects, arrays, and values, and not\ncontain functions or other objects.</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-cache-func\">cockpit.cache()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cache = cockpit.cache(key, provider, consumer)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new cache object. The <code>key</code> should be a globally unique\nstring that describes the data being cached. This string must describe\nthe data, across all machines and all versions of cockpit. It is\ncustomary to include a version number in the <code>key</code> string.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>function provider(result, key) {\n    result(\"myvalue\");\n\n    return {\n        close: function() {\n            /* closed */\n        }\n    };\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <code>provider</code> is a function that will be invoked to start retrieving\ndata for the cache. It will be passed a <code>result</code> function as its first\nargument. The <code>result</code> should be invoked whenever new data is\navailable. The <code>key</code> argument matches the key string the cache was\ncreated with.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>provider</code> can return an object with a <code>close</code> method. This\nmethod will be invoked when the cache no longer needs data from the\nprovider.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>function consumer(value, key) {\n    /* ... */\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <code>consumer</code> is a function that will be passed new values when they\nare available, whether they come from the <code>provider</code> or a source in a\ndifferent component/frame.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-cache-close\">cache.close()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cache.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close a cache and stop calling its <code>consumer</code>. If the <code>provider</code> was\ninvoked, then the <code>close()</code> method it returned will be invoked.</p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_js_raw_channels\">cockpit.js: Raw Channels</h4>\n<div class=\"paragraph\">\n<p>At a low level Cockpit communicates with the system via messages passed\nthrough various channels. These are usually exposed via higher level\nAPIs, such as the <code>cockpit.spawn()</code> function. It is rare to use raw\nchannels directly.</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-channels-channel\">cockpit.channel()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel = cockpit.channel(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This function creates a new channel for communication with the system.\nIt returns a new channel object. The <code>options</code> argument is a plain\nobject. At least the <code>\"payload\"</code> option is required, and based on the\npayload type, other options may be required.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"binary\"</code></dt>\n<dd>\n<p>Set to <code>true</code> to transfer binary payloads. Both messages sent via\n<a href=\"#cockpit-channels-send\"><code>channel.send()</code></a> and those received via\n<a href=\"#cockpit-channels-message\"><code>channel.onmessage</code></a> should be arrays\nof bytes, either <code>Uint8Array</code> or <code>Array</code> depending on browser\nsupport.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"payload\"</code></dt>\n<dd>\n<p>The payload type for the channel. Only specific payload types are\nsupported.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to open this channel as root. If the currently\nlogged in user is not permitted to become root (eg: via <code>pkexec</code>)\nthen the <code>channel</code> will immediately be\n<a href=\"#cockpit-channels-close-ev\">closed</a> with a <code>\"access-denied\"</code>\nproblem code.\n+\nSet to <code>\"try\"</code> to try to open the channel as root, but if that\nfails, then fall back to an unprivileged channel.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The channel object returned has the following fields and methods and\nevents. You should call the <code>channel.close()</code> method when done with\nthe channel.</p>\n</div>\n<div class=\"paragraph\">\n<p>A valid channel will always be returned and the is ready to\n<code>channel.send()</code>. The channel may\n<a href=\"#cockpit-channels-close-ev\">close shortly afterword</a> due to a\nfailure.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-channels-binary\">channel.binary</h5>\n<div class=\"paragraph\">\n<p>Will be <code>true</code> for an binary channel. Will be set to <code>false</code> if the\nchannel is textual.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-channels-options\">channel.options</h5>\n<div class=\"paragraph\">\n<p>The options used to open this channel. This should not be changed.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-channels-valid\">channel.valid</h5>\n<div class=\"paragraph\">\n<p>Will be <code>true</code> for an open channel. Will be set to <code>false</code> if the\nchannel closes.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-channels-send\">channel.send()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.send(data)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Send a message over the channel. The contents of the message depends on\nthe payload type of the channel. If a binary channel, then <code>data</code> is\nexpected to be an <code>Array</code> of bytes or a <code>Uint8Array</code>. If not binary,\nthen the <code>data</code> will be converted to a string if not already a string.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-channels-control\">channel.control()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.control(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Notify the channel to tune certain parameters on the fly. The\n<code>options</code> is a plain javascript object, and the contents depend on the\n<code>\"payload\"</code> of the channel.</p>\n</div>\n<div class=\"paragraph\">\n<p>One common operation is to set <code>\"command\"</code> to <code>\"done\"</code> in the\noptions field. To indicate that no further messages will be sent through\nthe channel.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-channels-wait\">channel.wait()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = channel.wait([callback])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Returns a <code>promise</code> that is ready when the channel is ready, or fails\nif the client closes. If a <code>callback</code> is specified, it is attached to\nthe promise. The promise will be rejected or resolved with the contents\n<code>options</code> passed to the\n<a href=\"#cockpit-channels-onready\">channel.onready</a> and\n<a href=\"#cockpit-channels-close-ev\">channel.onclose</a> events respectively.</p>\n</div>\n<div class=\"paragraph\">\n<p>In general it&#8217;s not necessary to wait for the channel before starting to\nuse the channel.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-channels-close\">channel.close()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.close([options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the channel.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>options</code> is present it can be a plain javascript object containing\nadditional channel close options to send to the peer. If closing for\nbecause of a problem, set the <code>\"problem\"</code> field to a\n<a href=\"#cockpit-problems\">problem code</a>. If <code>options</code> is not an object it\nwill be treated as a <code>\"problem\"</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-channels-close-ev\">close event</a> will fire. A channel\ncan also be closed by a peer or if the underlying transport closes.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-channels-message\">channel.onmessage</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"message\", function(event, data) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the channel receives a message. The message is\npassed as a string to the handler in the <code>data</code>. In the case of binary\nchannels <code>data</code> is an <code>Uint8Array</code> or an <code>Array</code> of bytes if the\nformer is not supported by the browser. The contents of the message\ndepends on the payload type of the channel.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-channels-oncontrol\">channel.oncontrol</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"control\", function(event, options) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the channel receives an control message in the\nmiddle of the flow. One particular use is when the <code>command</code> is set to\n<code>\"done\"</code> then no further messages will be received in the channel. The\nexact form of these messages depend on the <code>\"payload\"</code> of the channel.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-channels-onready\">channel.onready</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"ready\", function(event, options) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the other end of the channel is ready to start\nprocessing messages. This indicates the channel is completely open. It\nis possible to start sending messages on the channel before this point.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-channels-close-ev\">channel.onclose</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>channel.addEventListener(\"close\", function(event, options) { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the channel closes. This can happen either\nbecause <a href=\"#cockpit-channels-close\">channel.close()</a> function was\ncalled, or if the peer closed the channel, or the underlying transport\ncloses.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> will contain various close information, including a\n<code>\"problem\"</code> field which will be set if the channel was closed because\nof a problem.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-transport-origin\">cockpit.transport.origin</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.origin</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The HTTP origin that is being used by the underlying channel transport.\nThis is read-only, you should not assign a value. If the browser\nsupports <code>window.location.origin</code> then this will be identical to that\nvalue.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-transport-host\">cockpit.transport.host</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.host</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The host that this transport is going to talk to by default. This is\nread-only, you should not assign a value. If the value is null that\nmeans that the transport has not been setup yet.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-transport-csrf-token\">cockpit.transport.csrf_token</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.csrf_token</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>A cross site request forgery token for use with external channels. This\nbecomes valid once the connection is properly established.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-transport-options\">cockpit.transport.options</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.options</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Initialization options received over the underlying channel transport.\nThese will be empty until connection is properly established.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-transport-wait\">cockpit.transport.wait()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.wait(callback)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Call the <code>callback</code> function once the underlying channel transport is\ninitialized. This will start the initialization if not already in\nprogress or completed. If the channel transport is already initialized,\nthen <code>callback</code> will be called immediately.</p>\n</div>\n<div class=\"paragraph\">\n<p>In general it&#8217;s not necessary to wait for the transport before starting\nto open channels.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-transport-close\">cockpit.transport.close()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the underlying channel transport. All channels open channels will\nclose. The <code>problem</code> argument should be a problem code string. If not\nspecified it will default to <code>\"disconnected\"</code>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-transport-filter\">cockpit.transport.filter()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.filter((message, channelid, control) =&gt;  { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Add a filter to the underlying channel transport. All incoming messages\nwill be passed to each of the filter callbacks that are registered.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is rarely used.</p>\n</div>\n<div class=\"paragraph\">\n<p>Filter callbacks are called in the order they are registered. If a\nfilter callback returns <code>false</code> then the message will not be\ndispatched further, whether to other filters, or to channels, etc.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>message</code> is the string or array with the raw message including,\nthe framing. The <code>channelid</code> is the channel identifier or an empty\nstring for control messages. If <code>control</code> is set then this is a\ncontrol message,d and the <code>control</code> argument contains the parsed JSON\nobject of the control message.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-transport-inject\">cockpit.transport.inject()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.transport.inject(message, [out])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Inject a message into the underlying channel transport. The <code>message</code>\nshould be a <code>string</code> or an array of bytes, and should be valid\naccording to the Cockpit message protocol. If the <code>out</code> argument is\nequal to <code>false</code> then the message will be injected as an incoming\nmessage as if it was received on the underlying channel transport.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is rarely used. In general you should only <code>inject()</code>\nmessages you got from a <code>filter()</code>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-base64-encode\">cockpit.base64_encode()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.base64_encode(data)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Encode binary data into a string using the Base64 encoding. The <code>data</code>\nargument can either be a <code>string</code>, an <code>Array</code>, an <code>ArrayBuffer</code> or\na <code>Uint8Array</code>. The return value is a string.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-base64-decode\">cockpit.base64_decode()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>data = cockpit.base64_decode(string, [constructor])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Decode binary data from a Base64 encoded string. The <code>string</code> argument\nshould be a javascript string. The returned <code>data</code>&gt; will be an array\nof bytes.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can pass <code>Uint8Array</code>, <code>Array</code> or <code>String</code> as an alternate\n<code>constructor</code> if you want the decoded data in an alternate form. The\ndefault is to return an <code>Array</code>. Note that if you use a <code>String</code> for\nthe decoded data, then you must guarantee that the data does not contain\nbytes that would be invalid for a string.</p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_js_dbus_client\">cockpit.js: DBus Client</h4>\n<div class=\"paragraph\">\n<p>Cockpit allows access to DBus services via this API.</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-types\">DBus Types</h5>\n<div class=\"paragraph\">\n<p>DBus values are represented as javascript values and objects as follows:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>BYTE 'y'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>BOOLEAN 'b'</code></dt>\n<dd>\n<p>Javascript boolean.</p>\n</dd>\n<dt class=\"hdlist1\"><code>INT16 'n'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>UINT16 'q'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>INT32 'i'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>UINT32 'u'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>INT64 'x'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>UINT64 't'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>DOUBLE 'd'</code></dt>\n<dd>\n<p>Javascript number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>STRING 's'</code></dt>\n<dd>\n<p>Javascript string.</p>\n</dd>\n<dt class=\"hdlist1\"><code>OBJECT_PATH 'o'</code></dt>\n<dd>\n<p>Javascript string.</p>\n</dd>\n<dt class=\"hdlist1\"><code>SIGNATURE 'g'</code></dt>\n<dd>\n<p>Javascript string.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of BYTE 'ay'</code></dt>\n<dd>\n<p>A string containing base64 encoded data.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of DICT_ENTRY with STRING keys 'a{s?}'</code></dt>\n<dd>\n<p>A javascript plain object with the keys as property names.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of DICT_ENTRY with other keys 'a{??}'</code></dt>\n<dd>\n<p>A javascript plain object each key JSON encoded into a string property\nname.</p>\n</dd>\n<dt class=\"hdlist1\"><code>ARRAY of other</code></dt>\n<dd>\n<p>A javascript array.</p>\n</dd>\n<dt class=\"hdlist1\"><code>VARIANT</code></dt>\n<dd>\n<p>A javascript plain object with the <code>\"t\"</code> property set to a DBus type\nstring, and the <code>\"v\"</code> property set to a value.</p>\n</dd>\n<dt class=\"hdlist1\"><code>HANDLE 'h'</code></dt>\n<dd>\n<p>A javascript object that describes a cockpit channel which represents\nthe passed file descriptor. The <code>payload</code> is always set to\n<code>stream</code>. Pass it to\n<a href=\"#cockpit-channels-channel\">cockpit.channel()</a> to create the\nchannel and start reading or writing on it. Handles can only be\nreceived, not sent from within cockpit.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-dbus\">cockpit.dbus()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client = cockpit.dbus(name, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a DBus client for the given bus <code>name</code> (eg: service name). Use\nthe following functions to make DBus method calls, watch for events,\netc. The optional <code>options</code> argument is a javascript plain object, and\nmay include:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"bus\"</code></dt>\n<dd>\n<p>The DBus bus to connect to. Specifying <code>\"session\"</code> will connect to\nthe DBus user session bus, <code>\"user\"</code> will connect to the user bus (on\nsome systems this is identical to the session bus), <code>\"system\"</code> will\nconnect to the DBus system bus, and <code>\"none\"</code> to the non-standard bus\nspecified with the <code>address</code> option. This defaults to \"system\" if\nnot present.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"address\"</code></dt>\n<dd>\n<p>The bus address to connect to in case <code>bus</code> is <code>\"none\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to talk to this service as root. The DBus service\nwill see the DBus method calls and accesses as coming from root,\nrather than the logged in user. This is useful for talking to services\nthat do not correctly use\n<a href=\"https://www.freedesktop.org/software/polkit\">polkit</a> to authorize\nadministrative users. If the currently logged in user is not permitted\nto become root (eg: via <code>pkexec</code>) then the <code>client</code> will\nimmediately be <a href=\"#cockpit-dbus-onclose\">closed</a> with a\n<code>\"access-denied\"</code> problem code.\n+\nSet to <code>\"try\"</code> to try to talk as root, but if that fails, fall back\nto unprivileged.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"track\"</code></dt>\n<dd>\n<p>It is valid for a DBus service to exit, and be restarted in such a way\nthat clients continue to talk to it across the restart. Some services\nare not written with this in mind. If the <code>\"track\"</code> option is set to\n<code>true</code> then the channel will close when the service exits and/or\ndisconnects from the DBus bus.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>If the <code>name</code> argument is null, and no options other than <code>\"bus\"</code>\nare specified, then a shared DBus <code>client</code> is created. When using such\na client with a DBus bus, a <code>\"name\"</code> option must be specified on\nvarious other methods in order to specify which client to talk to.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-wait\">client.wait()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = client.wait([callback])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Returns a <code>promise</code> that is ready when the client is ready, or fails\nif the client closes. If a <code>callback</code> is specified, it is attached to\nthe promise.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-close\">client.close()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the DBus client. If <code>problem</code> is specified it should be a\n<a href=\"#cockpit-problems\">problem code</a> string.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-onclose\">client.onclose</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.addEventListener(\"close\", options =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the DBus client closes. This can happen either\nbecause <a href=\"#cockpit-dbus-close\">client.close()</a> function was called, or\nthe DBus service went away, or some other problem or disconnection.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> will contain various close information, including a\n<code>\"problem\"</code> field which will be set if the channel was closed because\nof a problem.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-onowned\">client.onowner</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.addEventListener(\"owner\", (event, owner) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the owner of the DBus name changes. The owner\nvalue will be the id of the name owner on the bus or null if the name is\nunowned. The absence of an owner should not be treated as a\ndisconnection. However this makes it possible to take some action based\non the actual status of the service, for example disconnecting a pending\nsignal handler.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-options\">client.options</h5>\n<div class=\"paragraph\">\n<p>Set to the options used when creating the client. Will not change for\nthe life of the client.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-unique-name\">client.unique_name</h5>\n<div class=\"paragraph\">\n<p>The unique DBus name of the client. Initially null, and becomes valid\nonce the the client is ready.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxy\">client.proxy()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy = client.proxy([interface, path], [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create proxy javascript object for a DBus <code>interface</code>. At the\nspecified DBus object <code>path</code>. The proxy will have properties, methods\nand signals from to the DBus interface, and allows for natural\ninteraction. If no <code>interface</code> is specified then the DBus bus name of\nthe client is used. If no <code>path</code> is specified, then the DBus name of\nthe client is converted to a path.</p>\n</div>\n<div class=\"paragraph\">\n<p>If creating lots of proxies for a given <code>interface</code> it is more\nefficient to use the <a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a>\nfunction.</p>\n</div>\n<div class=\"paragraph\">\n<p>The proxy is loaded when the\n<a href=\"#cockpit-dbus-proxy-valid\"><code>proxy.valid</code></a> field is <code>true</code>, and\nit is set to <code>false</code> if the underlying <code>interface</code> and/or <code>path</code>\ndon&#8217;t or no longer exist, or the <code>client</code> has closed. You can wait for\nproxy to become valid by passing a callback to its\n<a href=\"#cockpit-dbus-proxy-wait\"><code>proxy.wait()</code></a> function. The\n<a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a> event will also\nfire when the proxy becomes valid or invalid. DBus properties and\nmethods on the proxy are not defined until the proxy becomes valid.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>value = proxy.Prop1\nproxy.WritableProp = value</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>All DBus properties on the <code>interface</code> that start with an upper case\nletter (as is convention) will be automatically defined on this proxy,\nand will update their values as the DBus property values change. In\naddition the <a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a>\nevent will fire every time the properties change.</p>\n</div>\n<div class=\"paragraph\">\n<p>If you assign a value to a writable property on the proxy, the proxy\nwill try to set that property on the DBus <code>interface</code> at <code>path</code>. The\nactual proxy property value will not update until the DBus service has\nnotified the proxy of the change. If setting a property fails a warning\nwill be logged. In order to have more reliable setting of properties, or\ntrack when they have been set, or if setting fails, use the\n<a href=\"#cockpit-dbus-call\"><code>client.call()</code></a> directly. It should be noted\nthat DBus service implementations may also be inconsistent in their\nbehavior when setting a property fails.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can access the raw property data using the\n<a href=\"#cockpit-dbus-proxy-data\"><code>proxy.data</code></a> field, including data for\nproperties that do not start with an upper case letter.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.Method(arg1, arg2)\n    .then((retval1, retval2) =&gt; {\n        ...\n    })\n    .catch(ex =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>All DBus methods on the <code>interface</code> that start with an upper case\nletter (as is convention) will be automatically defined on this proxy.\nThese methods are called with arguments as normal javascript arguments.\nA\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the method returns, or fail if an\nerror occurs. The return values from the DBus method will be passed to\nthe <code>then</code> handler function directly.</p>\n</div>\n<div class=\"paragraph\">\n<p>Methods that do not start with an upper case letter can be invoked by\nusing the usual <a href=\"#cockpit-dbus-proxy-call\"><code>proxy.call()</code></a>\ndirectly.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.addEventListener(\"signal\", (event, arg1, arg2) =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>All DBus signals on the <code>interface</code> that start with an upper case\nletter (as is convention) will be automatically emit events on this\nproxy. These events will contain the signal arguments after the standard\n<code>event</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>Signals that do not start with an upper case letter can be subscribed to\nby using <a href=\"#cockpit-dbus-proxy-signal\"><code>proxy.onsignal</code></a> directly.</p>\n</div>\n<div class=\"paragraph\">\n<p>Usually a proxy asks the <code>client</code> to watch and notify it of changes to\nthe relevant object or path. You can pass an <code>options</code> argument with\nthe <code>watch</code> field set to <code>false</code> to prevent this.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxy-client\">proxy.client</h5>\n<div class=\"paragraph\">\n<p>Set to the DBus client of the proxy. Will not change for the life of the\nproxy.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxy-path\">proxy.path</h5>\n<div class=\"paragraph\">\n<p>Set to the DBus object path of the proxy. Will not change for the life\nof the proxy.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxy-iface\">proxy.iface</h5>\n<div class=\"paragraph\">\n<p>Set to the DBus interface name of the proxy. Will not change for the\nlife of the proxy.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxy-valid\">proxy.valid</h5>\n<div class=\"paragraph\">\n<p>Set to <code>true</code> when the proxy&#8217;s DBus interface is present at its DBus\npath, and all information for the proxy has loaded. Is set to <code>false</code>\nwhile loading, and after the proxy no longer refers a DBus interface and\npath. Also set to <code>false</code> if the <code>client</code> closes.</p>\n</div>\n<div class=\"paragraph\">\n<p>Use the by <a href=\"#cockpit-dbus-proxy-wait\"><code>proxy.wait()</code></a> function to\nwait for a proxy to load. The\n<a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a> event will also\nbe emitted when the proxy becomes valid or invalid. DBus properties and\nmethods on the proxy are not defined until the proxy becomes valid.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxy-data\">proxy.data</h5>\n<div class=\"paragraph\">\n<p>A plain javascript object containing all the raw property data that this\nproxy has loaded. This will be updated automatically as the proxy is\nnotified of property changes from the DBus service. The\n<a href=\"#cockpit-dbus-proxy-onchanged\"><code>proxy.onchanged</code></a> event will be\nemitted when it changes.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxy-call\">proxy.call()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation = proxy.call(method, args, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Make a DBus method call on this proxy.</p>\n</div>\n<div class=\"paragraph\">\n<p>For DBus methods that start with an upper case letter, is usually more\nconvenient <a href=\"#cockpit-dbus-proxy\">to call the method directly on the\nproxy</a>. However if methods that do not follow the usual DBus convention,\nor specify additional options, or the caller cannot be sure that the\nmethod actually exists, you can use this method.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function also works on proxies that have are still loading and have\nnot become valid yet.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>method</code> should be a DBus method name, and the <code>args</code> should be\nan array of arguments to pass to the method. The <code>options</code> are\n<a href=\"#cockpit-dbus-call\">described elsewhere</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The returned value is identical to the one returned from\n<a href=\"#cockpit-dbus-call\">client.call()</a>. It is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the method returns, or fail if an\nerror occurs.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxy-wait\">proxy.wait()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = proxy.wait()\nproxy.wait(() =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Wait for a proxy to finish loading. This function returns a promise. If\na callback function is passed as an argument then that function will be\ninvoked when the proxy is ready. If this method is called after a proxy\nhas already loaded, then the promise will be resolved immediately, and\nany callback will be invoked immediately. Use the promise or\n<code>proxy.valid</code> to determine whether the proxy is valid.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxy-onchanged\">proxy.onchanged</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.addEventListener(\"changed\", (event, data) =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when the proxy&#8217;s properties change.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> has the following form, and will only include properties\nthat have changed:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n    \"Prop1\": \"value\",\n    \"Prop2\": 5\n}</pre>\n</div>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxy-signal\">proxy.onsignal</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy.addEventListener(\"signal\", (event, name, args) =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when the proxy&#8217;s emits an event.</p>\n</div>\n<div class=\"paragraph\">\n<p>For most events, that have names which start with an upper case letter,\nyou can just <a href=\"#cockpit-dbus-proxy\">connect to that event as a signal\ndirectly</a>. However if you wish to be notified when any signal is\nemitted, or for signals that do not follow the usual DBus convention,\nyou can connect to this event.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>name</code> is the DBus signal name, and the <code>args</code> is an array of\narguments that were emitted with the signal.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxies\">client.proxies()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies = client.proxies([interface], [path_namespace], [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create <a href=\"#cockpit-dbus-proxy\">proxy javascript objects</a> for a DBus\ninterfaces. The proxies will have properties, methods and signals from\nthe DBus <code>interface</code>, and allow for natural interaction. If no\n<code>interface</code> is specified then the DBus bus name of the client is used.\nIf no <code>path_namespace</code> is provided then <code>\"/\"</code> will be used.</p>\n</div>\n<div class=\"paragraph\">\n<p>Proxies will be automatically created for instances of the <code>interface</code>\navailable at the DBus service. The optional <code>path_namespace</code> argument\ncan be used to restrict the proxies for instances that have DBus paths\nwhich have the namespace path prefix.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxy1 = proxies[\"/dbus/path1\"];\nproxy2 = proxies[\"/dbus/path2\"];\nfor (proxy in proxies) {\n    ...\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The returned <code>proxies</code> object will is used as a dictionary, and will\nhave values containing proxies for DBus interface instances, with the\nkeys being the DBus paths of those instances. It is possible to\nenumerate over the returned <code>proxies</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>Proxies will be automatically added and removed from the <code>proxies</code>\nobject as they appear and disappear in the service. The\n<a href=\"#cockpit-dbus-proxies-onadded\"><code>proxies.onadded</code></a> and\n<a href=\"#cockpit-dbus-proxies-onremoved\"><code>proxies.onremoved</code></a> events will\nbe emitted. DBus services may not support notifications of paths\ndisappearing.</p>\n</div>\n<div class=\"paragraph\">\n<p>Use the <code>proxies.wait()</code> function to be notified when the initial set\nof proxies has been populated.</p>\n</div>\n<div class=\"paragraph\">\n<p>Usually a proxies ask the <code>client</code> to watch and be notified of changes\nto the relevant object or path. You can pass an <code>options</code> argument\nwith the <code>watch</code> field set to <code>false</code> to prevent this.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxies-wait\">proxies.wait()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>promise = proxies.wait()\nproxies.wait(() =&gt; {\n    ...\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Wait for a <code>proxies</code> object to populate its initial set of proxies.\nThis function returns a promise. If a callback function is passed as an\nargument then that function will be invoked when the proxies are ready.\nIf this method is called after the proxies have populated, then the\npromise will be resolved immediately, and any callback will be invoked\nimmediately.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxies-client\">proxies.client</h5>\n<div class=\"paragraph\">\n<p>Set to the DBus client of the proxies. Will not change.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxies-iface\">proxies.iface</h5>\n<div class=\"paragraph\">\n<p>Set to the DBus interface name of the proxies. Will not change.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxies-path_namespace\">proxies.path_namespace</h5>\n<div class=\"paragraph\">\n<p>Set to the DBus path namespace used which the proxies must have as a\nDBus path prefix. Will not change.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxies-onadded\">proxies.onadded</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies.addEventListener(\"added\", (event, proxy) =&gt; {\n    ...\n})</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when a proxy is added to the <code>proxies</code> object.\nThe proxy will already have loaded.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxies-onchanged\">proxies.onchanged</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies.addEventListener(\"changed\", (event, proxy) =&gt; {\n    ...\n})</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when one of the proxy in the <code>proxies</code> object\nchanges its properties.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-proxies-onremoved\">proxies.onremoved</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>proxies.addEventListener(\"removed\", (event, proxy) =&gt; {\n    ...\n})</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when a proxy is removed to the <code>proxies</code> object.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-call\">client.call()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation = client.call(path, interface, method, args, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Make a DBus method call.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>path</code> is the DBus object path to make the call on, <code>interface</code>\nis the DBus interface for the method and <code>method</code> is the name of the\nmethod to call. The <code>args</code> is an array of arguments to pass to the\nmethod, each of which must be appropriate for the expected\n<a href=\"#cockpit-dbus\">DBus type</a> of that argument. The <code>args</code> may be\n<code>null</code> if no arguments are to be sent.</p>\n</div>\n<div class=\"paragraph\">\n<p>The returned value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the method returns, or fail if an\nerror occurs.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>options</code> is specified it should be a plain javascript object,\nwhich may contain the following properties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>flags</code></dt>\n<dd>\n<p>A string containing DBus message flags. The character <code>\"i\"</code>\nindicates to the dbus service that interactive authentication is\nallowed. If the entire <code>flags</code> field is missing, then <code>\"i\"</code> is set\nby default.</p>\n</dd>\n<dt class=\"hdlist1\"><code>type</code></dt>\n<dd>\n<p>A valid DBus type signature to use when calling the method. In the\nabsence of this, the DBus service will be introspected (and the result\ncached) to ask what the method type signature is.</p>\n</dd>\n<dt class=\"hdlist1\"><code>timeout</code></dt>\n<dd>\n<p>The timeout of the call in milliseconds. The call will fail with the\n<code>\"timeout\"</code> problem code. If \"timeout\" is not given, the call will\nnever time out.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-then\">invocation.then()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation.then((args, options) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the DBus method call\nfinishes successfully.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>args</code> argument is an array of return values from the DBus method.\nEach of them will be converted to an appropriate\n<a href=\"#cockpit-dbus\">javascript type</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> argument may contain additional information about the\nreply. If the <code>type</code> option was specified when performing the method\ncall, then the <code>options</code> in the reply here will also contain a\n<code>type</code> field containing the DBus type signature of the output. If the\n<code>flags</code> option was specified when performing the call then the\n<code>options</code> in the reply here will contain message flags. Possible out\nmessage flags are:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>&gt;</code></dt>\n<dd>\n<p>A big endian message.</p>\n</dd>\n<dt class=\"hdlist1\"><code>&lt;</code></dt>\n<dd>\n<p>A little endian message.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-catch\">invocation.catch()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>invocation.catch(exception =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the DBus method call\nfails.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>exception</code> object passed to the handler can have the following\nproperties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>problem</code></dt>\n<dd>\n<p>A <a href=\"#cockpit-problems\">problem code</a> string when a problem occurred\nstarting or communicating with the DBus service. This is <code>null</code> in\nthe cases where an actual DBus error was occurred.</p>\n</dd>\n<dt class=\"hdlist1\"><code>name</code></dt>\n<dd>\n<p>The DBus error name. This will be <code>null</code> in cases where the failure\nwas not due to a DBus error.</p>\n</dd>\n<dt class=\"hdlist1\"><code>message</code></dt>\n<dd>\n<p>A DBus error message. This will be <code>null</code> in cases where the failure\nwas not due to a DBus error.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-subscribe\">client.subscribe()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>subscription = client.subscribe(match, (path, interface, signal, args) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Subscribe to signals. The <code>match</code> argument is a javascript plain\nobject which defines what signals to subscribe to. Each property in the\n<code>match</code> argument restricts signals subscribed to. If a property is not\npresent then it is treated as a wildcard, matching anything. If an empty\nobject is specified as <code>match</code> then all signals will be subscribed to.\nThe <code>match</code> argument may contain the following properties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>interface</code></dt>\n<dd>\n<p>A DBus interface to match.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path</code></dt>\n<dd>\n<p>A DBus object path to match. May not be used together with the\n<code>path_namespace</code> property. It should be a valid DBus object path,\nthat is, it should have no trailing slash.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path_namespace</code></dt>\n<dd>\n<p>A DBus object path prefix to match. Any paths in the hierarchy below\nthis top path will match. May not be used together with the <code>path</code>\nproperty.</p>\n</dd>\n<dt class=\"hdlist1\"><code>member</code></dt>\n<dd>\n<p>The DBus signal name to match.</p>\n</dd>\n<dt class=\"hdlist1\"><code>arg0</code></dt>\n<dd>\n<p>Matches the first argument of a DBus message, which must be a string.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The handler passed as the second argument will be invoked when the\nsignal is received. A <code>subscription</code> is returned which can be used to\nremove the subscription by calling its <code>subscription.remove()</code> method.</p>\n</div>\n<div class=\"paragraph\">\n<p>It is not a problem to subscribe to the same signals more than once,\nwith identical or slightly different <code>match</code> arguments.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-remove\">subscription.remove()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>subscription.remove()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Unsubscribe from the DBus signal subscription.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-watch\">client.watch()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch = client.watch(path)\nwatch = client.watch({ \"path_namespace\": path_namespace, \"interface\": interface })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Watch for property and interface changes on the given DBus object\n<code>path</code> DBus <code>path_namespace</code>. If <code>interface</code> is specified only\nproperties on that DBus interface will be watched.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-dbus-proxy\"><code>client.proxy()</code></a> and\n<a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a> functions and the\nobjects they return are high level wrappers around <code>client.watch()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The property and interface changes will be available in raw form on the\n<a href=\"#cockpit-dbus-onnotify\"><code>client.onnotify</code></a> event.</p>\n</div>\n<div class=\"paragraph\">\n<p>Property and interface changes that are caused by a method call or\nsignal will show up before that method call reply is received, or signal\nevent is triggered. It should be possible to rely on this guarantee,\nunless the DBus service in question behaves incorrectly. Internally\nthese watches work well with code that implements the\n<a href=\"https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-objectmanager\">ObjectManager</a>\nportion of the DBus specification. If no ObjectManager implementation is\navailable, the watch falls back to using DBus\n<a href=\"https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-introspectable\">Introspection</a>\nalong with the usual\n<a href=\"https://dbus.freedesktop.org/doc/dbus-specification.html#standard-interfaces-properties\">PropertiesChanged</a>\nsignal. If the DBus service implements none of these, or implements them\nin an inconsistent manner, then this function will provide inconsistent\nor unexpected results.</p>\n</div>\n<div class=\"paragraph\">\n<p>The parameter is either a DBus <code>path</code> or a plain javascript object\nwith zero or more of the following fields. If an empty javascript object\nis used as an argument, then all paths, interfaces and properties will\nbe watched.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>interface</code></dt>\n<dd>\n<p>Watch properties on this DBus interface.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path</code></dt>\n<dd>\n<p>Watch interfaces and properties at this DBus path. May not be used\ntogether with the <code>path_namespace</code> property.</p>\n</dd>\n<dt class=\"hdlist1\"><code>path_namespace</code></dt>\n<dd>\n<p>Watch interfaces and properties under this DBus path. It should be a\nvalid DBus object path, that is, it should have no trailing slash. If\nan ObjectManager implementation is available at this interface, then\nit is used. May not be used together with the <code>path</code> property.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The returned value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete successfully when the watch has populated its initial\nset of properties and interfaces, and these have been notified via\n<a href=\"#cockpit-dbus-onnotify\"><code>client.onnotify</code></a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>A watch can be removed by calling the\n<a href=\"#cockpit-dbus-watch-remove\"><code>watch.remove()</code></a> method on the\nreturned value. If identical watches are added more than once, then they\nmust also be removed the same number of times before the removal takes\neffect.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-watch-then\">watch.then()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch.then(() =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the watch has populated\nits initial properties and interfaces.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-watch-catch\">watch.catch()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch.catch(ex =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called if the watch fails to populate\nits initial properties and interfaces. Note that a watch will only fail\nif the DBus client closes or is somehow disconnected. It does not fail\nin the case of missing interfaces or properties.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-watch-remove\">watch.remove()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>watch.remove()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Remove the watch. This may not have any immediate effect if other\nwatches are in place. In particular, if identical watches are added more\nthan once, then they must also be removed the same number of times\nbefore the removal takes effect.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-onnotify\">client.onnotify</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.addEventListener(\"notify\", data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when <a href=\"#cockpit-dbus-watch\">watched</a> properties or\ninterfaces change.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-dbus-proxy\"><code>client.proxy()</code></a> and\n<a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a> functions and the\nobjects they return are high level wrappers around the <code>data</code> provided\nby this event.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> has the following form:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n    \"/path1\": {\n        \"org.Interface1\": {\n            \"Prop1\": \"value\",\n            \"Prop2\": 5\n        },\n        \"org.Interface2\": null\n    }\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Multiple paths may be present, each of which may have multiple\ninterfaces, each of which may have multiple properties. The first time a\ngiven path and interface is emitted from this signal, it will have all\nits properties and interfaces. Thereafter only changes are noted. If an\ninterface is set to <code>null</code>, then that interface has disappeared.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-notify\">client.notify()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.notify(data)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Emits a synthetic <a href=\"#cockpit-dbus-onnotify\"><code>notify</code></a> event. The\n<code>data</code> argument should follow the same layout as described for the\n<code>notify</code> event.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-onmeta\">client.onmeta</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>client.onmeta = (ev, data) =&gt; { ... }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when the meta data about\n<a href=\"#cockpit-dbus-watch\">watched</a> interfaces is loaded.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-dbus-proxy\"><code>client.proxy()</code></a> and\n<a href=\"#cockpit-dbus-proxies\"><code>client.proxies()</code></a> functions and the\nobjects they return are high level wrappers around the <code>data</code> provided\nby this event.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> has the following form:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>  {\n      \"org.Interface\": {\n          \"methods\": {\n              \"Method1\": {\n                  \"in\": [ \"s\", \"v\" ],\n                  \"out\": [ \"i\" ]\n              },\n              \"Method2\": { }\n          },\n          \"signals\": {\n              \"Signal\": {\n                  \"in\": [ \"b\", \"s\" ]\n              }\n          },\n          \"properties\": {\n              \"Prop1\": {\n                  \"flags\": \"rw\",\n                  \"type\": \"s\"\n              },\n              \"Prop2\": {\n                  \"flags\": \"r\",\n                  \"type\": \"b\"\n              }\n          }\n      }\n  }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Multiple interfaces may be present, each of which may have methods and\nproperties. This is emitted before the first\n<a href=\"#cockpit-dbus-proxy\"><code>client.onnotify</code></a> event for the relevant\ninterface.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-dbus-variant\">cockpit.variant()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>variant = cockpit.variant(type, value)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>A DBus variant is represented as a plain javascript object with a\n<code>\"t\"</code> property represesting the full DBus type of the variant, and a\n<code>\"v\"</code> property containing the variant value.</p>\n</div>\n<div class=\"paragraph\">\n<p>This is a helper function for creating such a variant object.</p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_js_errors\">cockpit.js: Errors</h4>\n<div class=\"paragraph\">\n<p>cockpit.js: Errors</p>\n</div>\n<div class=\"paragraph\">\n<p>Problem codes and messages</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-problems\">Problem Codes</h5>\n<div class=\"paragraph\">\n<p>Cockpit represents problems with standardized problem string codes.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"access-denied\"</code></dt>\n<dd>\n<p>The user is not permitted to perform the action in question.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"authentication-failed\"</code></dt>\n<dd>\n<p>User authentication failed.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"internal-error\"</code></dt>\n<dd>\n<p>An unexpected internal error without further info. This should not\nhappen during the normal course of operations.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"no-cockpit\"</code></dt>\n<dd>\n<p>The system does not have a compatible version of Cockpit installed or\ninstalled properly.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"no-session\"</code></dt>\n<dd>\n<p>Cockpit is not logged in.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"not-found\"</code></dt>\n<dd>\n<p>Something specifically requested was not found, such as a file,\nexecutable etc.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"terminated\"</code></dt>\n<dd>\n<p>Something was terminated forcibly, such as a connection, process\nsession, etc.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"timeout\"</code></dt>\n<dd>\n<p>Something timed out.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"unknown-hostkey\"</code></dt>\n<dd>\n<p>The remote host had an unexpected or unknown key.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"no-forwarding\"</code></dt>\n<dd>\n<p>Could not forward authentication credentials to the remote host.</p>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-messages\">cockpit.message()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>message = cockpit.message(problem)\nmessage = cockpit.message(exception)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Return a message for the <code>exception</code> or <code>problem</code> code passed as an\nargument. If the argument is an object with a <code>\"message\"</code> property, as\nis the case with most exceptions, that will be returned directly. If the\nargument is an object with a <code>\"problem\"</code> property, then it will be\nused as the problem code. An appropriate message will be returned for\nproblem codes.</p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_js_file_access\">cockpit.js: File Access</h4>\n<div class=\"paragraph\">\n<p>The <code>cockpit.file</code> API lets you read, write, and watch regular files\nin their entirety. It cannot efficiently do random access in a big file\nor read non-regular files such as <code>/dev/random</code>.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>file = cockpit.file(path,\n                    { syntax: syntax_object,\n                      binary: boolean,\n                      max_read_size: int,\n                      superuser: string,\n                    })\n\npromise = file.read()\npromise\n    .then((content, tag) =&gt; { ... })\n    .catch(error =&gt; { ... })\n\npromise = file.replace(content, [ expected_tag ])\npromise\n    .then(new_tag =&gt; { ... })\n    .catch(error =&gt; { ... })\n\npromise = file.modify(callback, [ initial_content, initial_tag ]\npromise\n    .then((new_content, new_tag) =&gt; { ... })\n    .catch(error =&gt; { ... })\n\nfile.watch((content, tag, [error]) =&gt; { }, [ { read: boolean } ])\n\nfile.close()</pre>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-file-simple\">Simple reading and writing</h5>\n<div class=\"paragraph\">\n<p>You can read a file with code like this:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.file(\"/path/to/file\").read()\n    .then((content, tag) =&gt; {\n        ...\n    })\n    .catch(error =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>It is recommended to use absolute paths. Relative paths are resolved\nagainst <code>/</code>. To work with the current user&#8217;s files\n<a href=\"#cockpit-user\">cockpit.user()</a> can be used to get the user&#8217;s home\ndirectory.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>read()</code> method returns a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>When successful, the promise will be resolved with the content of the\nfile. Unless you specify options to change this (see below), the file is\nassumed to be text in the UTF-8 encoding, and <code>content</code> will be a\nstring.</p>\n</div>\n<div class=\"paragraph\">\n<p>The tag that is passed to the <code>then()</code> callback is a short string that\nis associated with the file and changes whenever the content of the file\nchanges. It is meant to be used with <code>replace()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>It is not an error when the file does not exist. In this case, the\n<code>then()</code> callback will be called with a <code>null</code> value for <code>content</code>\nand <code>tag</code> is <code>\"-\"</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>superuser</code> option can be used the same way as described in the\n<a href=\"#cockpit-channels-channel\">cockpit.channel()</a> to provide a different\naccess level to the file.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can use the <code>max_read_size</code> option to limit the amount of data\nthat is read. If the file is larger than the given number of bytes, no\ndata is read and the channel is closed with problem code <code>too-large</code>.\nThe default limit is 16 MiB. The limit can be completely removed by\nsetting it to -1.</p>\n</div>\n<div class=\"paragraph\">\n<p>To write to a file, use code like this:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.file(\"/path/to/file\").replace(\"my new content\\n\")\n    .then(tag =&gt; {\n        ...\n    })\n    .catch(error =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <code>replace()</code> method returns a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>When the promise is resolved, the file has been atomically replaced (via\nthe <code>rename()</code> syscall) with the new content. As with <code>read()</code>, by\ndefault the new content is a string and will be written to the file as\nUTF-8. The returned tag corresponds to the new content of the file.</p>\n</div>\n<div class=\"paragraph\">\n<p>When the promise is rejected because of an error, the file or its meta\ndata has not been changed in any way.</p>\n</div>\n<div class=\"paragraph\">\n<p>As a special case, passing the value <code>null</code> to <code>replace()</code> will\nremove the file.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>replace()</code> method can also check for conflicting changes to a\nfile. You can pass a tag (as returned by <code>read()</code> or <code>replace()</code>) to\n<code>replace()</code>, and the file will only be replaced if it still has the\ngiven tag. If the tag of the file has changed, <code>replace()</code> will fail\nwith an error object that has <code>error.problem == \"change-conflict\"</code>.\nSee <code>modify()</code> below for a convenient way to achieve transactional\nupdates to a file.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-file-format\">File format</h5>\n<div class=\"paragraph\">\n<p>By default, a file is assumed to be text encoded in UTF-8, and the\n<code>read()</code> and <code>replace()</code> functions use strings to represent the\ncontent.</p>\n</div>\n<div class=\"paragraph\">\n<p>By specifying the <code>syntax.parser()</code> and <code>syntax.stringify()</code>\noptions, you can cause <code>read()</code> to parse the content before passing it\nback to you, and <code>replace()</code> to unparse it before writing.</p>\n</div>\n<div class=\"paragraph\">\n<p>The main idea is to be able to write <code>{ syntax: JSON }</code>, of course,\nbut you can easily pass in individual functions or make your own\nparser/unparser object:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.file(\"/path/to/file.json\", { syntax: JSON })\n\nvar syntax_object = {\n    parse:     my_parser,\n    stringify: my_unparser\n};\n\ncockpit.file(\"/path/to/file\", { syntax: syntax_object })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Any exceptions thrown by the <code>parse()</code> and <code>stringify()</code> functions\nare caught and reported as read or write errors.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>null</code> value that is used to represent the content of a\nnon-existing file (see \"Simple reading and writing\", above) is not\npassed through the <code>parse()</code> and <code>stringify()</code> functions.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-file-binary\">Binary files</h5>\n<div class=\"paragraph\">\n<p>By default the content of the file is assumed to be text encoded as\nUTF-8 and it can not contain zero bytes. The content is represented as a\nJavaScript string with <code>read()</code>, <code>replace()</code>, etc. By setting the\n<code>binary</code> option to true when creating the proxy, no assumptions are\nplaced on the content, and it is represented as a <code>Uint8Array</code> in\nJavaScript.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-file-atomic\">Atomic modifications</h5>\n<div class=\"paragraph\">\n<p>Use <code>modify()</code> to modify the content of the file safely. A call to\n<code>modify()</code> will read the content of the file, call <code>callback</code> on the\ncontent, and then replace the content of the file with the return value\nof the callback.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>modify()</code> method uses the <code>read()</code> and <code>replace()</code> methods\ninternally in the obvious way. Thus, the <code>syntax.parse()</code> and\n<code>syntax.stringify()</code> options work as expected, <code>null</code> represents a\nnon-existing file, and the watch callbacks are fired.</p>\n</div>\n<div class=\"paragraph\">\n<p>It will do this one or more times, until no other conflicting changes\nhave been made to the file between reading and replacing it.</p>\n</div>\n<div class=\"paragraph\">\n<p>The callback is called like this</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>new_content = callback (old_content)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The callback is allowed to mutate <code>old_content</code>, but note that this\nwill also mutate the objects that are passed to the watch callbacks.\nReturning <code>undefined</code> from the proxy is the same as returning\n<code>old_content</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>modify()</code> method returns a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The promise will be resolved with the new content and its tag, like so</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>function shout(old_content) {\n    return old_content.toUpperCase();\n}\n\ncockpit.file(\"/path/to/file\").modify(shout)\n    .then((content, tag) =&gt; {\n        ...\n    })\n    .catch(error =&gt; {\n        ...\n    });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If you have cached the last content and tag results of the <code>read()</code> or\n<code>modify()</code> method, or the last values passed to a watch callback, you\ncan pass them to <code>modify()</code> as the second and third argument. In this\ncase, <code>modify()</code> will skip the initial read and start with the given\nvalues.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-file-notify\">Change notifications</h5>\n<div class=\"paragraph\">\n<p>Calling <code>watch()</code> will start monitoring the file for external changes.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>handle = file.watch(callback);\n\nhandle_no_read = file.watch(callback, { read: false });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Whenever a change occurs, the <code>callback()</code> is called with the new\ncontent and tag of the file. This might happen because of external\nchanges, but also as part of calls to <code>read()</code>, <code>replace()</code>, and\n<code>modify()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>When a read error occurs, the <code>callback()</code> is called with an error as\na third argument. Write errors are not reported via the watch callback.</p>\n</div>\n<div class=\"paragraph\">\n<p>Calling <code>watch()</code> will also automatically call <code>read()</code> to get the\ninitial content of the file. Thus, you normally don&#8217;t need to call\n<code>read()</code> at all when using <code>watch()</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>To disable the automatic reading, e.g. for large files or unreadable\nfile system objects, set the <code>read</code> option to <code>false</code>. The first\n<code>content</code> argument of the callback will then always be <code>null</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>To free the resources used for monitoring, call <code>handle.remove()</code>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-file-path\">file.path</h5>\n<div class=\"paragraph\">\n<p>A string containing the path that was passed to the <code>cockpit.file()</code>\nmethod.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-file-close\">Closing</h5>\n<div class=\"paragraph\">\n<p>Call the <code>close()</code> method on a file proxy to cancel all ongoing\noperations, such as reading, writing, and monitoring. The proxy should\nnot be used after closing it.</p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_js_http_client\">cockpit.js: HTTP Client</h4>\n<div class=\"paragraph\">\n<p>Cockpit allows access to local HTTP and REST services via this API.</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-http-constructor\">cockpit.http()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>http = cockpit.http(endpoint, [options])\nhttp = cockpit.http(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new HTTP client. The <code>endpoint</code> can be a file path starting\nwith <code>/</code> to connect to a unix socket, or it can be a port number to\nconnect to. The optional <code>options</code> argument is a javascript plain\nobject, and may include:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"address\"</code></dt>\n<dd>\n<p>Connect to an address other than localhost. Must be a valid host name\nor IP address. To use this option you also must provide a port number.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"port\"</code></dt>\n<dd>\n<p>Port number to use with \"address\" option, when not given in\n<code>endpoint</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"tls\"</code></dt>\n<dd>\n<p>Object properties for an https connection. See\n<code>http-stream2 TLS options</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"headers\"</code></dt>\n<dd>\n<p>Additional HTTP headers to include with the HTTP request. This is a\nplain javascript object with each key as a header name, and each value\nas the header value.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to open this channel as root. If the currently\nlogged in user is not permitted to become root (eg: via <code>pkexec</code>)\nthen the <code>channel</code> will immediately be\n<a href=\"#cockpit-channels-close-ev\">closed</a> with a <code>\"access-denied\"</code>\nproblem code.\n+\nSet to <code>\"try\"</code> to try to make the request as root, but if that\nfails, fall back to perform an unprivileged request.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"tls\"</code></dt>\n<dd>\n<p>If set to a plain javascript object, then the connection will be an\nHTTPS connection and include TLS encryption. The fields of the <code>tls</code>\nobject declare various TLS configuration and data. All fields are\noptional:\n+</p>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><code>\"authority\"</code>: Certificate authority(s) to expect as signers of\nthe server&#8217;s TLS certificate, represented as a plain javascript\nobject. It should have either a <code>\"file\"</code> field containing a readable\nPEM file on the system containing authorities, or a <code>\"data\"</code> with\nPEM encoded certificate data.</p>\n</li>\n<li>\n<p><code>\"certificate\"</code>: A client certificate to use, represented as a\nplain javascript object. It should have either a <code>\"file\"</code> field\ncontaining a readable PEM file on the system to use as a certificate,\nor a <code>\"data\"</code> with PEM encoded certificate data.</p>\n</li>\n<li>\n<p><code>\"key\"</code>: A client key to use, represented as a plain javascript\nobject. It should have either a <code>\"file\"</code> field containing a readable\nPEM file on the system to use as a key, or a <code>\"data\"</code> with PEM\nencoded key data.</p>\n</li>\n<li>\n<p><code>\"validate\"</code>: A boolean that describes whether to validate the\nserver&#8217;s TLS certificate or not. By default local connections are not\nvalidated, and remote connections are validated.</p>\n</li>\n</ul>\n</div>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Here is a somewhat complex example of using most of the above\n<code>options</code> when when calling <code>cockpit.http()</code>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>http = cockpit.http({\n    \"address\": \"localhost\",\n    \"headers\": {\n        \"Authorization\": \"Basic dXNlcjpwYXNzd29yZA==\"\n    },\n    \"port\": 443,\n    \"tls\": {\n        \"validate\": true,\n        \"authority\": {\n            \"file\": \"/etc/pki/tls/certs/ca-bundle.crt\",\n        },\n        \"certificate\": {\n            \"data\": \"-----BEGIN CERTIFICATE-----\\nMIIDsDCCA...\"\n        },\n        \"key\": {\n            \"data\": \"-----BEGIN RSA PRIVATE KEY-----\\nMIIEogIBA...\"\n        }\n    }\n});</pre>\n</div>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-http-get\">http.get()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request = http.get(path, [params, [headers]])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Perform an HTTP GET request for the given <code>path</code>. If the <code>params</code> is\nspecified it should be a plain javascript object, which will be turned\ninto a query string.</p>\n</div>\n<div class=\"paragraph\">\n<p>Optionally a plain javascript object containing headers can be included\nin the <code>headers</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>The return value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete if the request happens successfully, or fail if\nthere&#8217;s a problem.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-http-post\">http.post()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request = http.post(path, body, [headers])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Perform an HTTP POST request for the given <code>path</code>. The <code>body</code> can be\na string, or a javascript plain object, which will be encoded as JSON\ndata. If <code>body</code> is <code>undefined</code> or <code>null</code> then an empty HTTP body\nwill be sent.</p>\n</div>\n<div class=\"paragraph\">\n<p>Optionally a plain javascript object containing headers can be included\nin the <code>headers</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>The return value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete if the request happens successfully, or fail if\nthere&#8217;s a problem.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-http-request\">http.request()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request = http.request(options)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Perform an HTTP request. The <code>options</code> can contain the following:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"body\"</code></dt>\n<dd>\n<p>The HTTP request body. If you do not specify a body, then you must\ncall <a href=\"#cockpit-http-input\">request.input()</a> to complete the body\nand allow the request to start.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"headers\"</code></dt>\n<dd>\n<p>A javascript plain object containing HTTP headers.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"method\"</code></dt>\n<dd>\n<p>The HTTP method. Defaults to <code>\"GET\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"params\"</code></dt>\n<dd>\n<p>A javascript plain object containing query string parameters.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"path\"</code></dt>\n<dd>\n<p>The HTTP path. Defaults to <code>/</code>.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The return value is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nthat will complete if the request happens successfully, or fail if\nthere&#8217;s a problem.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-http-then\">request.then()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.then(data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the request finishes\nsuccessfully.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> argument contains the body result of the request. If it a\nstring, unless the process was opened in binary mode, in which case the\n<code>data</code> is an array of bytes. If a <code>request.stream()</code> handler is set\nup, then any standard output data consumed by the handler will not be\nincluded in the <code>data</code> argument.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-http-catch\">request.catch()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.catch((exception[, data]) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the request fails, or\nreturns an error code.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>exception</code> object passed to the handler can have the following\nfields:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>problem</code></dt>\n<dd>\n<p>A <a href=\"#cockpit-problems\">problem code</a> string when a problem occurred\nstarting or communicating with the server. This is <code>null</code> if the\nprocess exited or was terminated.</p>\n</dd>\n<dt class=\"hdlist1\"><code>status</code></dt>\n<dd>\n<p>The numeric status of the response. This is <code>null</code> if no response\nwas received.</p>\n</dd>\n<dt class=\"hdlist1\"><code>reason</code></dt>\n<dd>\n<p>A string reason returned in the response. This is <code>null</code> if no\nresponse was received.</p>\n</dd>\n<dt class=\"hdlist1\"><code>message</code></dt>\n<dd>\n<p>A string message returned in the response. This is <code>null</code> if no\nresponse was received.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>If the request returned a response body, it will be available in the\n<code>data</code> argument. Otherwise this argument will be <code>undefined</code>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-http-response\">request.response()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.response((status, headers) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This sets up a handler to be called when the HTTP request gets the\ninitial response from the server. The <code>status</code> argument is the HTTP\nstatus integer, and the <code>headers</code> is a plain javascript object\ncontaining the headers of the response.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-http-stream\">request.stream()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.stream(data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This sets up a handler to be called when the request returns output\ndata. The handler will be called multiple times.</p>\n</div>\n<div class=\"paragraph\">\n<p>Only one handler may be registered at a time. Registering an additional\nhandler replaces the previous one. The handler receives either string\n<code>data</code> or an array of binary bytes as its argument. A stream handler\nmay return a number, which indicates the number of characters or bytes\nconsumed from <code>data</code>. Any data not consumed will be included again the\nnext time the handler is called.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>request.stream()</code> handler is set up, then the <code>request.then()</code>\nhandlers will only get any remaining data not consumed by the stream\nhandler.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-http-input\">request.input()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.input(data, [stream])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This method writes <code>data</code> to the HTTP request body. It is only valid\nif no <code>\"body\"</code> has been specified in\n<a href=\"#cockpit-http-request\">http.request()</a> options. If <code>stream</code> is\n<code>true</code> then this function can be called again to provide further data.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-http-close\">request.close()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>request.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cancel the request. If <code>problem</code> is specified it should be a standard\n<a href=\"#cockpit-problems\">problem code</a> string.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-http-close-all\">http.close()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>http.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cancel all outstanding requests with the given problem code. This is\nuseful when you know that the server is going down soon.</p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_js_localization\">cockpit.js: Localization</h4>\n<div class=\"paragraph\">\n<p>Cockpit provides a <a href=\"https://www.gnu.org/software/gettext/\"><code>gettext()</code></a>\nlike API for easy translation of strings.</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-locale-language\">cockpit.language</h5>\n<div class=\"paragraph\">\n<p>The current locale language code. This is set based on the\n<a href=\"#cockpit-locale-locale\"><code>cockpit.locale()</code></a> data loaded.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-locale-locale\">cockpit.locale()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.locale(po)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Load locale information for a given <code>po</code> data. The data should be JSON\ndata in the <a href=\"https://www.npmjs.org/package/po2json\">po2json</a> format. The\ndata will be loaded globally. If <code>po</code> data has already been loaded,\nthen this will extend that loaded data with additional strings. Any\nidentical translations strings will be replaced with the new strings. A\n<code>null</code> argument clears all the locale information previously loaded.</p>\n</div>\n<div class=\"paragraph\">\n<p>Various methods such as\n<a href=\"#cockpit-locale-gettext\"><code>cockpit.gettext()</code></a> make use of the\nloaded data.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-locale-gettext\">cockpit.gettext()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>translated = cockpit.gettext([context], string)\nvar _ = cockpit.gettext\nvar C_ = cockpit.gettext\ntranslated = _(\"string\")\ntranslated = C_(\"context\", \"string\")</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Lookup <code>string</code> for translation in the loaded locale data. The\ntranslated string will be returned, or <code>string</code> will be returned if no\nsuch translated string is present. The <code>context</code> argument is an\noptional string used to qualify the string.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function can be assigned to a variable called <code>_</code> (underscore)\nwhich will make your code work with the typical <code>_(\"string\")</code> syntax.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-locale-noop\">cockpit.noop()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>var N_ = cockpit.noop\nvar NC_ = cockpit.noop</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>A noop function suitable for assigning to <code>N_</code> or <code>NC_</code> so that\ngettext scanners will be able to find translatable strings. More\nspecifically this function returns its last argument.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-locale-ngettext\">cockpit.ngettext()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>translated = cockpit.ngettext([context], string1, stringN, number)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Lookup a string appropriate for a pluralization form of the <code>number</code>.\nVarious languages have complex pluralization forms that go far between\nthe singular and plural forms speakers of English are familiar with. If\nno such translated string is found then either one of <code>string1</code> or\n<code>stringN</code> is returned according to simple pluralization rules.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>context</code> argument is an optional string used to qualify the\nstring.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-locale-translate\">cockpit.translate()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.translate()\ncockpit.translate(element, ...)\ncockpit.translate(selection)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The document will be scanned for <code>translate</code> tags and they will be\ntranslated according to the strings in loaded locale data. One or more\n<code>element</code> arguments may be specified. These are DOM elements for\nspecific parts of the document to be translated. If no <code>element</code> is\nspecified then the entire document is translated.</p>\n</div>\n<div class=\"paragraph\">\n<p>If an array or array-like object is passed as a <code>selection</code> then all\nDOM elements in the array will be treated as parts of the document to be\ntranslated.</p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_js_page_location_and_jumping\">cockpit.js: Page Location and Jumping</h4>\n<div class=\"paragraph\">\n<p>Page location and navigation between components</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-location-general\">Page location</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>location = cockpit.location\ncockpit.location = \"/path\"</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit components often have different views, without changing the HTML\nfile that is being viewed. These are known as pages.\n<code>cockpit.location</code> is an object that can be used to read the current\npage and to navigate to a different page location. It works by updating\n<code>window.location.hash</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>cockpit.location</code> looks like a HTTP path with a possible query\nstring:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>/path/sub/page?option=value,option2</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The <a href=\"#cockpit-location-path\"><code>location.path</code></a> and\n<a href=\"#cockpit-location-options\"><code>location.options</code></a> contain a parsed\nform of the location. While the location cannot be modified in place, a\nnew one can be created by assigning a string to <code>cockpit.location</code> or\nby calling the <a href=\"#cockpit-location-go\"><code>location.go()</code></a> function.</p>\n</div>\n<div class=\"paragraph\">\n<p><code>cockpit.location</code> is designed similarly to <code>window.location</code> in\nthat the location object is preplaced whenever the current page location\nchanges. To be aware of when the page location changes listen for the\n<a href=\"#cockpit-location-changed\"><code>cockpit.onlocationchanged</code></a> event.</p>\n</div>\n<div class=\"paragraph\">\n<p>Using the location object as a string will result in the\n<a href=\"#cockpit-location-href\"><code>location.href</code></a>.</p>\n</div>\n<div class=\"sect5\">\n<h6 id=\"cockpit-location-href\">location.href</h6>\n<div class=\"paragraph\">\n<p>The string representation of this page location, including any options.</p>\n</div>\n</div>\n<div class=\"sect5\">\n<h6 id=\"cockpit-location-path\">location.path</h6>\n<div class=\"paragraph\">\n<p>An array of path segments, parsed and decoded appropriately. An empty\narray denotes the root path.</p>\n</div>\n</div>\n<div class=\"sect5\">\n<h6 id=\"cockpit-location-options\">location.options</h6>\n<div class=\"paragraph\">\n<p>A javascript object containing the various options present in the\nlocation.</p>\n</div>\n<div class=\"paragraph\">\n<p>If an option appears more than once, its value will be an array.</p>\n</div>\n</div>\n<div class=\"sect5\">\n<h6 id=\"cockpit-location-go\">location.go()</h6>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>location.go(path, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Changes the current location to the given <code>path</code> and <code>options</code>. If\nthe <code>path</code> argument is a string, it will be parsed into a path. If it\nis a relative path, then the result will be relative to the current\n<code>location.path</code>. If the <code>path</code> argument is an array of path\nsegments, it will be treated as a full parsed absolute path.</p>\n</div>\n<div class=\"paragraph\">\n<p>Any options found in a <code>path</code> will be added to those in the optional\n<code>options</code> argument, and used in the result.</p>\n</div>\n<div class=\"paragraph\">\n<p>The location change will only take effect if the location has not\nchanged in the meantime. This can be to good effect by saving a\n<code>cockpit.location</code> object and doing a conditional navigation, by\ncalling the saved <code>location.go()</code> method later. This will only\nnavigate if the user or other code has not navigated in the meantime.</p>\n</div>\n</div>\n<div class=\"sect5\">\n<h6 id=\"cockpit-location-replace\">location.replace()</h6>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>location.replace(path, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Similar to <a href=\"#cockpit-location-go\"><code>location.go()</code></a> except the\nlocation change will not result in a navigation change in the browser&#8217;s\nhistory.</p>\n</div>\n</div>\n<div class=\"sect5\">\n<h6 id=\"cockpit-location-decode\">location.decode()</h6>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>path = location.decode(href, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Decode a cockpit href into its <code>path</code> array. If the <code>options</code>\nargument is specified, then it will be populated with options found in\nthe href.</p>\n</div>\n<div class=\"paragraph\">\n<p>If href is a relative path it will be resolved relative to\n<code>location.href</code>.</p>\n</div>\n</div>\n<div class=\"sect5\">\n<h6 id=\"cockpit-location-encode\">location.encode()</h6>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>href = location.encode(path, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Encode the given <code>path</code> and <code>options</code> into a cockpit href. The\n<code>path</code> argument may be an array of path segments, or a string path. If\na relative path is passed, it will be resolved relative to\n<code>location.href</code>.</p>\n</div>\n</div>\n<div class=\"sect5\">\n<h6 id=\"cockpit-location-changed\">cockpit.onlocationchanged</h6>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.addEventListener(\"locationchanged\", function() { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event emitted when over the <code>cockpit.location</code> changes. Typically a\ncomponent reacts to this event by updating its interface to reflect the\nnew <a href=\"#cockpit-location-path\"><code>cockpit.location.path</code></a> and\n<a href=\"#cockpit-location-options\"><code>cockpit.location.options</code></a>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This event is not triggered immediately during a <code>location.go()</code> or\nsimilar call. It will be triggered asynchronously at a later time.</p>\n</div>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-jump\">Jumping between components</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.jump(\"/system/log\")</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>In Cockpit in there multiple components shown. In order to tell Cockpit\nto jump to and show another component and a certain location within that\ncomponent, use the <code>cockpit.jump()</code> function. Stable component paths\nare documented. Don&#8217;t assume you can navigate into paths that are not\nstable API.</p>\n</div>\n<div class=\"sect5\">\n<h6 id=\"cockpit-jump-jump\">cockpit.jump()</h6>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.jump(path, [ host ])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Ask Cockpit to jump to another component. The location of the current\ncomponent will not be affected. The <code>path</code> argument can be a string\npath, starting with <code>/</code> or an array containing the parts of a path\nthat will be joined to create a path. If <code>host</code> is not specified, then\nthe component on the same host as the caller will be displayed. If host\nis null, then the host portion of the path will be removed, displaying\nthe component on the host that cockpit is connected directly to.</p>\n</div>\n<div class=\"paragraph\">\n<p>If the calling component is not running within Cockpit, or the calling\ncomponent is not currently displayed, then the jump will not happen, and\nthis function has no effect.</p>\n</div>\n</div>\n<div class=\"sect5\">\n<h6 id=\"cockpit-jump-hidden\">cockpit.hidden</h6>\n<div class=\"paragraph\">\n<p>A boolean property that indicates if the current component page is\nvisible or hidden. When the code or user jumps to another component, the\nprior one remains loaded and initialized but is hidden. Use this\nproperty together with the\n<a href=\"#cockpit-jump-visibilitychange\"><code>cockpit.onvisibilitychange</code></a>\nevent to decide whether or not to perform expensive tasks to update the\ninterface.</p>\n</div>\n<div class=\"paragraph\">\n<p>This property is analogous to the <code>document.hidden</code> page visibility\nAPI, but works with the document and frame implementation of Cockpit.</p>\n</div>\n</div>\n<div class=\"sect5\">\n<h6 id=\"cockpit-jump-visibilitychange\">cockpit.onvisibilitychange</h6>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.onvisibilitychange = function() { ... }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is emitted when the\n<a href=\"#cockpit-jump-hidden\"><code>cockpit.hidden</code></a> property changes. This\nevent is similar to the <code>document.onvisibilitychange</code> API, but works\nwith the document and frame implementation of Cockpit.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_js_user_session\">cockpit.js: User Session</h4>\n<div class=\"paragraph\">\n<p>User information and login session state</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-logout\">cockpit.logout()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.logout([reload])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Logout of Cockpit. Unless <code>reload</code> is <code>false</code> this will also cause\nthe page to be reloaded, so that the user can see the logged out state.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-user\">cockpit.user()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>var promise = cockpit.user();\npromise.then(user =&gt; { ... });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This object contains information about the user that&#8217;s currently logged\ninto cockpit. The following fields are defined:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"id\"</code></dt>\n<dd>\n<p>This is unix user id.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"gid\"</code></dt>\n<dd>\n<p>This is unix user group id.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"name\"</code></dt>\n<dd>\n<p>This is the unix user name like <code>\"root\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"full_name\"</code></dt>\n<dd>\n<p>This is a readable name for the user.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"groups\"</code></dt>\n<dd>\n<p>This is an array of group names to which the user belongs. Since\nversion 318, the first item in this list is the primary group.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"home\"</code></dt>\n<dd>\n<p>This is user&#8217;s home directory.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"shell\"</code></dt>\n<dd>\n<p>This is unix user shell.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Returns a promise that completes once the user information is available.</p>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p><code>cockpit.user()</code> is soft-deprecated since Cockpit 336, if your page\ndoes not need to maintain compatibility with older Cockpit versions you\ncan use<a href=\"#cockpit-info\">cockpit.info</a> to obtain the user information.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-permission\">Permission lookup</h5>\n<div class=\"paragraph\">\n<p>Cockpit provides a mechanism for checking if the current user satisfies\na given criteria. This is meant for updating UI elements based on what\nactions the user can perform. It is <em>not an access control mechanism</em>.</p>\n</div>\n<div class=\"sect5\">\n<h6 id=\"cockpit-permission-constructor\">cockpit.permission()</h6>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>permission = cockpit.permission([options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new permission object to check if the current user has a\nparticular permission specified by <code>options</code>:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>admin: true</code></dt>\n<dd>\n<p>True if the session has superuser privileges, i.e. can run channels as\nroot with <code>{ superuser: \"require\" }</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>group:</code> <em>name</em></dt>\n<dd>\n<p>True if the currently logged user is a member of group <em>name</em>.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The permission result is always true for the \"root\" user. When\n<code>options</code> is not given, check if the current user is root.</p>\n</div>\n</div>\n<div class=\"sect5\">\n<h6 id=\"cockpit-permission-allowed\">permission.allowed</h6>\n<div class=\"paragraph\">\n<p>A boolean value which indicates if the permission is allowed or not.\nThis will be <code>null</code> if the permission is unknown, or there was an\nerror checking the permission or the permission data has not yet loaded.\nThis property will update asynchronously and if you wish to be notified\nof changes connect to the\n<a href=\"#cockpit-permission-changed\">permission.onchanged</a> event.</p>\n</div>\n</div>\n<div class=\"sect5\">\n<h6 id=\"cockpit-permission-changed\">permission.onchanged</h6>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>permission.addEventListener(\"changed\", function() { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This event is fired when the permission changes. In particular the\n<a href=\"#cockpit-permission-allowed\">permission.allowed</a> property.</p>\n</div>\n</div>\n<div class=\"sect5\">\n<h6 id=\"cockpit-permission-close\">permission.close()</h6>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>permission.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Closes the permission object and tears down any registered callbacks and\ndbus subscriptions.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_js_manifests\">cockpit.js: Manifests</h4>\n<div class=\"sect4\">\n<h5 id=\"cockpit-manifest-loading\">Loading Manifests</h5>\n<div class=\"paragraph\">\n<p>For a convenient access to all page manifests, include\n<code>&lt;script src=\"../manifests.js\"&gt;&lt;/script&gt;</code> into your page to register\nthe manifests at the <code>cockpit.manifests</code> global variable.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can also load <code>../manifests.json</code> directly in your page, with\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch\"><code>fetch()</code></a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_js_metrics\">cockpit.js: Metrics</h4>\n<div class=\"paragraph\">\n<p>Metrics about the system can be retrieved from several sources using\n<a href=\"#cockpit-metrics\"><code>cockpit.metrics()</code></a> metrics channels. The\nmetrics are made available as series data, and can be used with the\n<a href=\"#cockpit-series\"><code>cockpit.series()</code></a> and\n<a href=\"#cockpit-grid\"><code>cockpit.grid()</code></a> facilities.</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-metrics-function\">cockpit.metrics()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics = cockpit.metrics(interval, options, cache)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Opens a new metrics channel. The data retrieved will be available in the\n<a href=\"#cockpit-metrics-series\"><code>metrics.series</code></a> series sink, and can be\nused together with <a href=\"#cockpit-grid\"><code>cockpit.grid()</code></a> objects.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>interval</code> is in milliseconds, and is the granularity of the\nseries data retrieved. Any grids consuming the data must have the same\ninterval.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>cache</code> argument is a cache identifier. If specified, then this\nmetrics channel will share data with other metrics channels of the same\nidentifier. Make sure to use a globally unique string.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> argument is either a javascript plain object, or an\narray of those. Each object can have the following fields.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"metrics\"</code></dt>\n<dd>\n<p>An array of full metric descriptions, as javascript objects. The\nspecifics of these, and how to determine which ones to use, can\nunfortunately only be found in the low-level protocol documentation.\nThis option is required.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"source\"</code></dt>\n<dd>\n<p>The source to use for real-time data. This is used by the <code>follow</code>\nmethod, see below. Set to <code>\"internal\"</code> to retrieve internal metrics\nread by the bridge. If set to <code>\"direct\"</code> or <code>\"pmcd\"</code> then data\nwill be retrieved from <a href=\"https://pcp.io\">PCP</a>if it is available. The\ndefault is <code>\"internal\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"archive_source\"</code></dt>\n<dd>\n<p>The source to use for retrieving historical data. This is used by the\n<code>fetch</code> method, see below. Set to <code>\"pcp-archive\"</code> to retrieve data\nfrom PCP archives. The default is not to try to retrieve historical\ndata.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>When the <code>options</code> argument is an array of javascript objects, then\nthe metrics channel tries to use them in order until one succeeds. This\nway, you can prefer PCP as the source but fall back to internal metrics\nwhen PCP is not available, for example. The channel gives no indication\nwhich of the options has been used, and <code>fetch</code> and <code>follow</code> might\nuse different entries from the list.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-metrics-fetch\">metrics.fetch()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.fetch(beg, end)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Retrieve archived metrics data between <code>beg</code> and <code>end</code>. The\narguments can either be numbers, in which case they are interval based\noffsets, or they can be javascript Date objects.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-metrics-follow\">metrics.follow()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.follow()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Start retrieving live metrics data as it become available.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-metrics-close\">metrics.close()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Stop the retrieval of metrics and release resources.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-metrics-series\">metrics.series</h5>\n<div class=\"paragraph\">\n<p>The series sink where data retrieved data will be processed.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-metrics-meta\">metrics.meta</h5>\n<div class=\"paragraph\">\n<p>The metrics meta data last received.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-metrics-onchanged\">metrics.onchanged</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>metrics.onchanged = function() { }</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event triggered when one of the properties on this metrics object\nchanges.</p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_js_series_data\">cockpit.js: Series Data</h4>\n<div class=\"paragraph\">\n<p>Series data consists of values along a continuous (usually time) axis.\nWe can place these in grids which expose a distinct subset of these\nvalues. These are the underlying mechanism for displaying metrics data\nin graphs.</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-grid\">cockpit.grid()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid = cockpit.grid(interval, [beg, end])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Creates a grid object to contain series data.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>interval</code> is the granularity of the grid. Usually this is a\nnumber of milliseconds, when used with time series data. The <code>beg</code> and\n<code>end</code> are the bounds of the grid. If omitted they will be set to zero\nfor an initially empty grid.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>beg</code> and/or <code>end</code> are negative (including negative zero) then\nthey are interpreted in number of intervals relative to the current\ntime. Thus cockpit.grid(1000, -300, -0) will create a grid for the most\nrecent 5 minutes.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-grid-add\">grid.add()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>row = grid.add(series, path)\nrow = grid.add(callback, [early])\nrow = grid.add()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Adds a row to the grid. The returned <code>row</code> is a Javascript array that\nwill contain series data. The arguments control how the row is populated\nfrom the series data. The <code>row</code> is a sparse array. Its <code>row.length</code>\nwill not match the expected size of the grid, unless and until the row\nhas been completely filled in. The first index of the <code>row</code> will\ncontain the data from the series data at the\n<a href=\"#cockpit-grid-beg\"><code>grid.beg</code></a> offset.</p>\n</div>\n<div class=\"paragraph\">\n<p>When no arguments are passed, an empty row is added, and it is not\npopulated with data.</p>\n</div>\n<div class=\"paragraph\">\n<p>When called with a <code>series</code> and <code>path</code> argument then the row will be\npopulated directly with series data. The <code>series</code> can either be a\n<a href=\"#cockpit-series\">series object</a> or an object that has an\n<code>obj.series</code> property. The <a href=\"#cockpit-series-interval\">series\ninterval</a> must match the interval of this grid. If <code>path</code> is missing\nor empty, then the series data is placed into the row directly.\nOtherwise <code>path</code> indicates which part of the series data to place in\nthe row. When <code>path</code> is an array, it is used as a set of property\nnames or array indexes to follow into nested series data. When <code>path</code>\nis a dotted string, it is split and used the same way to locate the\ncorrect value in nested series data. The exact format of the series data\ndepends on its producer, and relevant paths will be documented there.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>callback</code> function is specified, then it will be invoked to\nprovide series data for the row. The function is invoked as\n<code>callback(row, index, count)</code>, where the <code>row</code> is the row to fill\nin, the <code>index</code> is the index to start filling in and <code>count</code> is the\nnumber of items to fill in. The <code>this</code> variable will be set to the\ngrid while invoking the <code>callback</code>. The callback is called after other\ndata rows for a given series have been filled in. Callbacks are called\nin the order added, unless the <code>early</code> argument is set to <code>true</code>, in\nwhich case the callback is called earlier than callbacks without the\n<code>early</code> argument set.</p>\n</div>\n<div class=\"paragraph\">\n<p>To remove the row use the <a href=\"#cockpit-grid-remove\"><code>grid.remove()</code>\nmethod.</a></p>\n</div>\n<div class=\"paragraph\">\n<p>The row will start being populated with data when the <code>series</code>\nproduces data. To make this happen right away, use the\n<a href=\"#cockpit-grid-sync\"><code>grid.sync()</code></a> method.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-grid-remove\">grid.remove()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.remove(row)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Remove a previously added <code>row</code> from the grid. The row will no longer\nbe updated with series data.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-grid-sync\">grid.sync()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.sync()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Load or reload data from the series into the rows. This does not clear\nthe rows before populating them. Some data may be populated immediately,\nothers may have to wait until data can be loaded. Internally this\nfunction calls <a href=\"#cockpit-series-load\"><code>series.load()</code></a> for each\nseries.</p>\n</div>\n<div class=\"paragraph\">\n<p>All rows with callbacks will be invoked to regenerate all the data. The\n<a href=\"#cockpit-grid-onnotify\"><code>grid.onnotify</code></a> event will be triggered.\nIt is not necessary to call this function after a call of the\n<a href=\"#cockpit-grid-move\"><code>grid.move()</code></a> method.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-grid-move\">grid.move()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.move(beg[, end])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Move the grid to new <code>beg</code> and <code>end</code> range. Data will be discarded\nfrom the rows and <a href=\"#cockpit-grid-sync\"><code>grid.sync()</code></a> will be\ncalled to load or reload series data for the new range of offsets.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>end</code> is not specified it will be set to <code>beg</code>. If <code>beg</code> and/or\n<code>end</code> are negative (including negative zero) then they will be set to\nthe number of intervals prior to the current time taken as an interval.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>beg</code> and/or <code>end</code> are negative (including negative zero) then\nthey are interpreted in number of intervals relative to the current\ntime. Thus cockpit.grid(1000, -300, -0) will create a grid for the most\nrecent 5 minutes.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-grid-walk\">grid.walk()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.walk()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Move the grid forward every\n<a href=\"#cockpit-grid-interval\"><code>grid.interval</code></a> milliseconds. To stop\nmoving forward, call <a href=\"#cockpit-grid-move\"><code>grid.move()</code></a>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-grid-notify\">grid.notify()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.notify(index, count)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This function is called to have rows with callbacks recalculate their\ndata. It is not normally necessary to call this function, as it will be\ninvoked automatically when new series data is available or has been\nloaded. This function triggers the\n<a href=\"#cockpit-grid-onnotify\"><code>grid.onnotify</code></a> event.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-grid-onnotify\">grid.onnotify</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.addEventListener(\"notify\", function(index, count) { ... });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>An event that is triggered when some part of the series data in grid\nchanges. The <code>index</code> is the row index where things changed, and the\n<code>count</code> is the length of the data that changed.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-grid-close\">grid.close()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>grid.close()</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the grid, and stop updating the rows.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-grid-interval\">grid.interval</h5>\n<div class=\"paragraph\">\n<p>The granularity of the grid. For time series data this is an interval in\nmilliseconds. In order to use a given <a href=\"#cockpit-grid\">grid</a> and\n<a href=\"#cockpit-series\">series</a> together, their interval properties must\nmatch.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-grid-beg\">grid.beg</h5>\n<div class=\"paragraph\">\n<p>The beginning offset of the series data in the grid. Do not set this\nproperty directly. Use the <a href=\"#cockpit-grid-move\">grid.move()</a> method\ninstead.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-grid-end\">grid.end</h5>\n<div class=\"paragraph\">\n<p>The ending offset of the series data in the grid. Do not set this\nproperty directly. Use the <a href=\"#cockpit-grid-move\">grid.move()</a> method\ninstead.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-series\">cockpit.series()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>series = cockpit.series(interval, [cache, fetch])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Create a new sink of series data. This is usually done by producers of\nseries data, and it is rare to invoke this function directly.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>interval</code> is the granularity of the series data. For time series\ndata this is an interval in milliseconds. If a <code>cache</code> string is\nspecified, series data will be cached across frames for series with the\nsame <code>cache</code> cache identifier to load and/or reload.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>fetch</code> callback is specified, then it will be invoked when grids\nrequest certain ranges of data. The <code>fetch</code> callback is invoked with\n<code>function fetch(beg, end) { ... }</code> range offsets. The\n<a href=\"#cockpit-series-input\">series.input()</a> should be called with data\nretrieved, either immediately or at a later time. The callback may be\ncalled multiple times for the same ranges of data. It is up to the\ncallback to determine when or whether it should retrieve the data more\nthan once.</p>\n</div>\n<div class=\"paragraph\">\n<p>A producer of series data, usually calls this function and creates\nitself a <code>obj.series</code> property containing this series object.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-series-input\">series.input()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>series.input(beg, items[, mapping])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Send series data into the series sink. Any grids that have added rows\nbased on this series, will have data filled in. The <code>beg</code> is the\nbeginning offset of <code>items</code>. The <code>items</code> are an array one or more\nseries data items.</p>\n</div>\n<div class=\"paragraph\">\n<p>Producers may wish to provide additional properties that can be used in\nlookup paths that rows can pull from. This is done in the <code>mapping</code>\nargument. If specified it is a tree of objects. Each sub object should\nhave a property with the name <code>\"\"</code> empty string, which will be used as\nthe property name or index in place of the one used in the lookup path.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-series-load\">series.load()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>series.load(beg, end)</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Load data from the series into any grids that have rows based on this\nseries data. Any cached data will be filled in immediately. Any data not\ncached, will be requested from the producer, if possible, and may arrive\nat a later time.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>beg</code> and <code>end</code> denote the range of data to load.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-series-interval\">series.interval</h5>\n<div class=\"paragraph\">\n<p>The granularity of the series. For time series data this is an interval\nin milliseconds. In order to use a given <a href=\"#cockpit-grid\">grid</a> and\n<a href=\"#cockpit-series\">series</a> together, their interval properties must\nmatch.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-series-limit\">series.limit</h5>\n<div class=\"paragraph\">\n<p>The maximum number of items to cache for loading and/or reloading. You\ncan change this value to a different number. Having a number close to\nzero will break certain usage of grids, such as\n<a href=\"#cockpit-grid-walk\"><code>grid.walk()</code></a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_js_spawning_processes\">cockpit.js: Spawning Processes</h4>\n<div class=\"paragraph\">\n<p>This is the API for spawning a process and receiving its output, as well\nas exit codes.</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-spawn-spawn\">cockpit.spawn()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process = cockpit.spawn(args, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Spawns a process on the system.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>args</code> should be an array starting with the executable and\ncontaining all the arguments to pass on the command line. If <code>args</code> is\na string then it is interpreted as an executable name. The optional\n<code>options</code> argument is a javascript plain object and can contain any of\nthe following fields:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>\"binary\"</code></dt>\n<dd>\n<p>If set to <code>true</code> then handle the input and output of the process as\narrays of binary bytes.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"directory\"</code></dt>\n<dd>\n<p>The directory to spawn the process in.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"err\"</code></dt>\n<dd>\n<p>Controls where the standard error is sent. By default it is logged to\nthe journal. If set to <code>\"out\"</code> it is included in with the output\ndata. If set to <code>\"ignore\"</code> then the error output is discarded. If\nset to <code>\"message\"</code>, then it will be returned as the error message.\nWhen the <code>\"pty\"</code> field is set, this field has no effect.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"environ\"</code></dt>\n<dd>\n<p>An optional array that contains strings to be used as additional\nenvironment variables for the new process. These are <code>\"NAME=VALUE\"</code>\nstrings.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"pty\"</code></dt>\n<dd>\n<p>Launch the process in its own PTY terminal, and send/receive terminal\ninput and output.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"batch\"</code></dt>\n<dd>\n<p>Batch data coming from the process in blocks of at least this size.\nThis is not a guarantee. After a short timeout the data will be sent\neven if the data doesn&#8217;t match the batch size. Defaults to zero.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"latency\"</code></dt>\n<dd>\n<p>The timeout for flushing any cached data in milliseconds.</p>\n</dd>\n<dt class=\"hdlist1\"><code>\"superuser\"</code></dt>\n<dd>\n<p>Set to <code>\"require\"</code> to spawn the process as root instead of the\nlogged in user. If the currently logged in user is not permitted to\nbecome root (eg: via <code>pkexec</code>) then the <code>client</code> will immediately\nbe <a href=\"#cockpit-dbus-onclose\">closed</a> with a <code>\"access-denied\"</code>\nproblem code.\n+\nSet to <code>\"try\"</code> to try to run the process as root, but if that fails,\nfall back to an unprivileged process.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The spawned process is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">promise</a>\nthat will complete if the process exits successfully, or fail if there&#8217;s\na problem. Some additional methods besides the standard promise methods\nare documented below.</p>\n</div>\n<div class=\"paragraph\">\n<p>The standard output of the process is made available via the spawned\nprocess object. Any non-UTF8 output from the process will be coerced\ninto textual form. It is highly recommended that only textual output be\nproduced by the command. The standard error is logged to the journal.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-spawn-script\">cockpit.script()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process = cockpit.script(script, [args], [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Run a shell script on the system.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function <a href=\"#cockpit-spawn-spawn\">spawns</a> a Bourne shell script\nprocess. The full text of the <code>/bin/sh</code> shell script should be passed\nin as the first argument. The <code>args</code> can be an array of arguments, not\nincluding the executable, which are passed to the script as <code>$1</code>,\n<code>$2</code> and so on. Shebang options are not used or respected.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>options</code> is an optional javascript plain object and can include\nany of the fields listed for the\n<a href=\"#cockpit-spawn-spawn\"><code>cockpit.spawn()</code></a> function.</p>\n</div>\n<div class=\"paragraph\">\n<p>The spawned process is a\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">promise</a>\nthat will complete if the script exits successfully, or fail if there&#8217;s\na problem. Some additional methods besides the standard promise methods\nare documented below.</p>\n</div>\n<div class=\"paragraph\">\n<p>The standard output of the process is made available via the spawned\nprocess object. Any non-UTF8 output from the process will be coerced\ninto textual form. It is highly recommended that only textual output be\nproduced by the command. The standard error is logged to the journal by\ndefault.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-spawn-then\">process.then()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.then((data[, message]) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">promise</a>\nmethod. It sets up a handler to be called when the process finishes\nsuccessfully.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>data</code> argument contains the standard output of the process. If it\na string, unless the process was opened in binary mode, in which case\nthe <code>data</code> is an array of bytes. If a <code>process.stream()</code> handler is\nset up, then any standard output data consumed by the handler will not\nbe included in the <code>data</code> argument.</p>\n</div>\n<div class=\"paragraph\">\n<p>If the process was spawned with the <code>\"err\"</code> option set to\n<code>\"message\"</code> then the second argument will contain the standard error\noutput of the process.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-spawn-catch\">process.catch()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.catch((exception[, data]) =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a standard\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise\">Promise</a>\nmethod. It sets up a handler to be called when the process fails,\nterminates or exits.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>exception</code> object passed to the handler can have the following\nfields:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>message</code></dt>\n<dd>\n<p>A message describing the exception. If the process was spawned with\nthe <code>\"err\"</code> option set to <code>\"message\"</code> then the second argument\nwill contain the standard error output of the process.</p>\n</dd>\n<dt class=\"hdlist1\"><code>problem</code></dt>\n<dd>\n<p>A <a href=\"#cockpit-problems\">problem code</a> string when a problem occurred\nstarting or communicating with the process. This is <code>null</code> if the\nprocess exited or was terminated.</p>\n</dd>\n<dt class=\"hdlist1\"><code>exit_status</code></dt>\n<dd>\n<p>The numeric exit status of the process. This is <code>null</code> if the\nprocess did not exit.</p>\n</dd>\n<dt class=\"hdlist1\"><code>exit_signal</code></dt>\n<dd>\n<p>A string representing a unix signal that caused the process to\nterminate. This is <code>null</code> if the process did not terminate because\nof a signal.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>If the process actually ran and produced output before failing, it will\nbe available in the <code>data</code> argument. Otherwise this argument will be\n<code>undefined</code>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-spawn-stream\">process.stream()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.stream(data =&gt; { ... })</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This sets up a handler to be called when the process has standard\noutput. The handler will be called multiple times. The handler will be\ncalled regardless of whether the process ends up exiting successfully or\nnot.</p>\n</div>\n<div class=\"paragraph\">\n<p>Only one handler may be registered at a time. Registering an additional\nhandler replaces the previous one. The handler receives either string\n<code>data</code> or an array of binary bytes as its argument. A stream handler\nmay return a number, which indicates the number of characters or bytes\nconsumed from <code>data</code>. Any data not consumed will be included again the\nnext time the handler is called.</p>\n</div>\n<div class=\"paragraph\">\n<p>If a <code>process.stream()</code> handler is set up, then the <code>process.then()</code>\nhandlers will only get any remaining data not consumed by the stream\nhandler.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-spawn-input\">process.input()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.input(data, [stream])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This method writes <code>data</code> to the standard input of the process. If\n<code>data</code> is <code>null</code> or <code>undefined</code> it is not sent. The <code>data</code>\nshould be a string or an array of bytes if the process was opened in\nbinary mode.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>stream</code> is set to <code>true</code> then this function may be called again\nwith further input. Otherwise the standard input of the process is\nclosed.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-spawn-close\">process.close()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>process.close([problem])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Close the process by closing its standard input and output. If\n<code>problem</code> is specified it should be a standard\n<a href=\"#cockpit-problems\">problem code</a> string. In this case the process\nwill be terminated with a signal.</p>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_cockpit_js_utilities\">cockpit.js: Utilities</h4>\n<div class=\"paragraph\">\n<p>Various utility functions</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-format\">cockpit.format()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format(template, args)\nstring = cockpit.format(template, [arg, ...])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Format a string interpolating <code>args</code> into <code>template</code> using shell\nlike syntax. The <code>args</code> may be either an array or javascript object.\nThe <code>template</code> can contain fields that look like <code>$name</code> or\n<code>${name}</code> or <code>$0</code>. Numeric fields are used with array <code>args</code> and\nstart at zero.</p>\n</div>\n<div class=\"paragraph\">\n<p>In the second form, multiple <code>arg</code> arguments may be passed directly,\nand interpolated as as numeric fields in the <code>template</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>All falsy arguments except the numbers <code>0</code> and `0.0`are replaced by\nan empty string.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-format-number\">cockpit.format_number()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_number(number, [precision])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Formats <code>number</code> into a displayable <code>string</code>. If the number is not\nan integer, it is rounded to the given number of decimal places,\ndefaulting to 3. If the number is near zero, but not quite zero it is\nrounded to the smallest non-zero value of the given precision; i.e.\n±0.001 for default precision 3.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>number</code> is <code>null</code> or <code>undefined</code> an empty string will be\nreturned.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-format-bytes\">cockpit.format_bytes()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_bytes(number, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Formats <code>number</code> into a displayable <code>string</code> with a suffix, such as\n<em>kB</em> or <em>MB</em>.</p>\n</div>\n<div class=\"paragraph\">\n<p>By default, SI units are used. IEC units (1024-based) can be requested\nby including <code>base2: true</code> in <code>options</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>By default, non-integer numbers will be formatted with 3 digits of\nprecision. This can be changed with <code>options.precision</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>If <code>number</code> is <code>null</code> or <code>undefined</code> an empty string will be\nreturned.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-format-bytes-per-sec\">cockpit.format_bytes_per_sec()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_bytes_per_sec(number, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Format <code>number</code> of bytes into a displayable speed <code>string</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is mostly equivalent to <code>cockpit.format_bytes()</code> but the\nreturned value contains a unit like <em>kB/s</em> or <em>MB/s</em>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-format-bits-per-sec\">cockpit.format_bits_per_sec()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>string = cockpit.format_bits_per_sec(number, [options])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Format <code>number</code> of bits into a displayable speed <code>string</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function is mostly equivalent to <code>cockpit.format_bytes()</code> but the\nreturned value contains a unit like <em>kbps</em> or <em>Mbps</em>.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function does not support IEC units. <code>base2</code> may not be passed as\npart of <code>options</code>.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-init\">cockpit.init()</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>await cockpit.init();\n\ncockpit.init().then(() =&gt; { ... });</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Requests initialization of the Cockpit client library. This will ensure\nthat the transport is connected and we are ready to create channels. It\nalso populates the <code>cockpit.info</code> field.</p>\n</div>\n<div class=\"paragraph\">\n<p>This function returns a promise. Initialization isn&#8217;t complete until the\npromise has resolved. You can either <code>await</code> it or call <code>.then()</code> on\nit.</p>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-info\">cockpit.info</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.info.channels[payload]\n\ncockpit.info.os_release[field]\n\ncockpit.info.user\n\ncockpit.info.ws.version</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This object contains information about Cockpit itself. It is only\navailable after cockpit.init() has been called and awaited.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>channels</code></dt>\n<dd>\n<p>This is a mapping of channel payload types (keys, strings) supported\nby the bridge to capabilities advertised by those channels (values,\nlists of strings). Channels are listed even if they don&#8217;t advertise\nany capabilities, making this useful as a way to determine which\nchannel types are supported by the bridge.</p>\n</dd>\n<dt class=\"hdlist1\"><code>os_release</code></dt>\n<dd>\n<p>This is the data from the <code>/etc/os-release</code> or\n<code>/usr/lib/os-release</code> on the system that the bridge is running on.\nIt is a mapping from the key names to their values. See the\n<a href=\"https://www.freedesktop.org/software/systemd/man/latest/os-release.html\">os-release\nSpecification</a> for information about the available keys.</p>\n</dd>\n<dt class=\"hdlist1\"><code>user</code></dt>\n<dd>\n<p>Contains information about the user we&#8217;re logged in as.</p>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>uid</code></dt>\n<dd>\n<p>This is unix user id as an integer.</p>\n</dd>\n<dt class=\"hdlist1\"><code>gid</code></dt>\n<dd>\n<p>This is unix user group id as an integer.</p>\n</dd>\n<dt class=\"hdlist1\"><code>name</code></dt>\n<dd>\n<p>This is the unix user name like <code>\"root\"</code>.</p>\n</dd>\n<dt class=\"hdlist1\"><code>fullname</code></dt>\n<dd>\n<p>This is a readable name for the user, from the GECOS field.</p>\n</dd>\n<dt class=\"hdlist1\"><code>group</code></dt>\n<dd>\n<p>This is the primary group name of the user.</p>\n</dd>\n<dt class=\"hdlist1\"><code>groups</code></dt>\n<dd>\n<p>This is an array of group names to which the user belongs. The first\nitem in this list is the primary group.</p>\n</dd>\n<dt class=\"hdlist1\"><code>home</code></dt>\n<dd>\n<p>This is user&#8217;s home directory.</p>\n</dd>\n<dt class=\"hdlist1\"><code>shell</code></dt>\n<dd>\n<p>This is unix user shell.</p>\n</dd>\n</dl>\n</div>\n</dd>\n<dt class=\"hdlist1\"><code>ws</code></dt>\n<dd>\n<p>Contains information about the webserver Cockpit is being served with.</p>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><code>version</code></dt>\n<dd>\n<p>The version of the webserver.</p>\n</dd>\n</dl>\n</div>\n</dd>\n</dl>\n</div>\n</div>\n<div class=\"sect4\">\n<h5 id=\"cockpit-event-target\">cockpit.event_target</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>cockpit.event_target(object, [handlers])</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Adds an\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/EventTarget\">EventTarget</a>\nimplementation to the <code>object</code>. Optionally store the handlers in\n<code>handlers</code> if its specified.</p>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_api_shell\">API: shell</h3>\n<div class=\"paragraph\">\n<p>This package contains the shell that loads other components.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_index_html\">index.html</h4>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;iframe src=\"http://127.0.0.1:9090/cockpit+app/@localhost/shell/index.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a Cockpit component that provides an interface to configure a\nsingle machine. It loads other components on demand to make that happen.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Component URL</dt>\n<dd>\n<p><code>/cockpit+app/@localhost/shell/index.html</code></p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect2\">\n<h3 id=\"_api_system\">API: system</h3>\n<div class=\"paragraph\">\n<p>This package contains general components for basic control of a system.</p>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_logs_html\">logs.html</h4>\n<div class=\"paragraph\">\n<p>System log component</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"api-logs-html-description\">Description</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;iframe src=\"http://127.0.0.1:9090/cockpit+app/@localhost/system/logs.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a Cockpit component that brings up system log viewer, with\nfiltering capabilities. On systemd based systems this displays the\nentries from journal.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Component URL</dt>\n<dd>\n<p><code>/cockpit+app/@localhost/system/logs.html</code></p>\n</dd>\n<dt class=\"hdlist1\">Filter by priority</dt>\n<dd>\n<p><code>#?prio=notice</code><br>\n<br>\nFilters the log to show entries below the specific priority,\ninclusive. These\n<a href=\"https://en.wikipedia.org/wiki/Syslog#Severity_levels\">priorities are\nsyslog level keywords</a>. Specifying <code>*</code> as a priority will show all\navailable entries. The default priority is <code>err</code>.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by service</dt>\n<dd>\n<p><code>#?service=sshd.service</code><br>\n<br>\nFilters the log to show entries related to the specific service. The\nformat of the service is specific to the logging implementation. For\njournald these are systemd service unit names.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by tag</dt>\n<dd>\n<p><code>#?tag=kernel</code><br>\n<br>\nFilters the log to show entries related to the specific syslog\nidentifier.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by message</dt>\n<dd>\n<p><code>#?grep=</code><br>\n<br>\nFilters the log to show entries where the <code>MESSAGE=</code> field matches\nthe specified regular expression. PERL-compatible regular expressions\nare used. If the pattern is all lowercase, matching is case\ninsensitive. Otherwise, matching is case sensitive.</p>\n</dd>\n<dt class=\"hdlist1\">Filter by any field</dt>\n<dd>\n<p><code>#?FIELD=VALUE</code><br>\n<br>\nA field is referring to the components of a structured journal entry.\nThe match must be exact. Value can be comma separated list in which\ncase they are automatically matched as alternatives.</p>\n</dd>\n<dt class=\"hdlist1\">Start at point</dt>\n<dd>\n<p><code>#?start=boot</code><br>\n<br>\nFilters the log to show entries after the specific point in time.\nValid values are <code>boot</code> (since last boot), <code>last-24h</code> (last 24\nhours), <code>last-week</code> (last seven days) and <code>previous-boot</code>\n(previous boot).</p>\n</dd>\n<dt class=\"hdlist1\">Follow the journal</dt>\n<dd>\n<p><code>#?follow=true</code><br>\n<br>\nKeep listening on new entries. Valid values are <code>true</code> (follow) and\n<code>false</code> (do not follow).</p>\n</dd>\n<dt class=\"hdlist1\">Show log entry</dt>\n<dd>\n<p><code>#/6e272d82993c4e0d...</code><br>\n<br>\nTo show a specific log entry, put the log entry cursor in a path after\nthe hash above. Note that cursors are logging system specific, and\njournal cursors are subject to change.</p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect3\">\n<h4 id=\"_terminal_html\">terminal.html</h4>\n<div class=\"paragraph\">\n<p>Server terminal component</p>\n</div>\n<div class=\"sect4\">\n<h5 id=\"api-terminal-html-description\">Description</h5>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;iframe src=\"http://127.0.0.1:9090/cockpit+app/@localhost/system/terminal.html\"\n    width=\"600\" height=\"400\"&gt;&lt;/iframe&gt;</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>This is a Cockpit component that brings up a web-based terminal for the\nlogged in user.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Component URL</dt>\n<dd>\n<p><code>/cockpit+app/@localhost/system/terminal.html</code></p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/listen.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>TCP Port and Address</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"listen\" class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>TCP Port and Address</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#listen-systemd\">Cockpit systemd Socket</a></li>\n<li><a href=\"#listen-selinux\">SELinux Port</a></li>\n<li><a href=\"#listen-firewalld\">Firewalld Port</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit&#8217;s <code>cockpit-ws</code> component is configured by default to accept\nconnections on port <code>9090</code>. This is the port that is documented for a\n\"Web-based System Manager\" to listen on. It is also relatively\nmemorable.</p>\n</div>\n<div class=\"paragraph\">\n<p>However there are many reasons you may wish to change the default port.\nFor example other software may use port <code>9090</code> or you may wish to\nsetup Cockpit to listen on <code>443</code> instead. It is also possible to have\nCockpit only listen on one specific IP address.</p>\n</div>\n<div class=\"paragraph\">\n<p>Note that it is only required to have Cockpit listening on a TCP port on\nthe server that you access with your web browser. If you add multiple\nservers with host switcher, Cockpit will connect to those servers via\n<code>ssh</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>The systems that Cockpit runs on are typically locked down with\nfirewalls, SELinux, so changing the default port is not as easy as\nediting a configuration file.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"listen-systemd\">Cockpit systemd Socket</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>On servers with\n<a href=\"https://www.freedesktop.org/wiki/Software/systemd/\"><code>systemd</code></a> Cockpit\nstarts on demand via socket activation. To change its port and/or\naddress you should place the following content in the\n<code>/etc/systemd/system/cockpit.socket.d/listen.conf</code> file. Create the\nfile and directories in that path which not already exist. The\n<code>ListenStream</code> option specifies the desired address and TCP port.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>[Socket]\nListenStream=\nListenStream=443</pre>\n</div>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>[Socket]\nListenStream=\nListenStream=7777\nListenStream=192.168.1.1:443\nFreeBind=yes</pre>\n</div>\n</div>\n<div class=\"admonitionblock note\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Note</div>\n</td>\n<td class=\"content\">\nThe first line with an empty value is intentional. <code>systemd</code>\nallows multiple <code>Listen</code> directives to be declared in a single socket\nunit; an empty value in a drop-in file resets the list and thus disables\nthe default port 9090 from the original unit.\n</td>\n</tr>\n</table>\n</div>\n<div class=\"paragraph\">\n<p>The <code>FreeBind</code> option is highly recommended when defining specific IP\naddresses. See the\n<a href=\"https://www.freedesktop.org/software/systemd/man/systemd.socket.html\"><code>systemd.socket</code>\nmanpage</a> for details.</p>\n</div>\n<div class=\"paragraph\">\n<p>In order for the changes to take effect, run the following commands:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo systemctl daemon-reload\n$ sudo systemctl restart cockpit.socket</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"listen-selinux\">SELinux Port</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>If <a href=\"https://selinuxproject.org/page/Main_Page\">SELinux</a> is protecting your\nserver, then you will need to tell it to allow Cockpit to listen on the\nnew port. Run the following command to do so. The last argument\nspecifies the desired TCP port.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo semanage port -a -t websm_port_t -p tcp 9999</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If the port is already defined by some other part of the SELinux policy,\nthen you will need to use the <code>-m</code> argument to modify the definition.\nThat&#8217;s the case with the <code>443</code> SSL port, which is typically defined as\nan <code>http_port_t</code> port.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo semanage port -m -t websm_port_t -p tcp 443</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The changes should take effect immediately.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"listen-firewalld\">Firewalld Port</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>If <a href=\"https://fedoraproject.org/wiki/FirewallD\">Firewalld</a> is configured as\nyour firewall, then you will need to tell it to allow Cockpit to receive\nconnections on the new port. Run the following commands to do so. The\nlast options specify the desired TCP port.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo firewall-cmd [--zone=ZONE] --add-port=443/tcp\n$ sudo firewall-cmd --permanent [--zone=ZONE] --add-port=443/tcp</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/multi-host.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Managing multiple hosts at the same time</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"multi-host\" class=\"article\">\n<div id=\"header\">\n<h1>Managing multiple hosts at the same time</h1>\n</div>\n<div id=\"content\">\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>This feature is deprecated as of Cockpit 322.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit allows you to access multiple hosts in a single session, by\nestablishing SSH connections to other hosts. This is quite similar to\nlogging into these other hosts using the <code>ssh</code> command on the command\nline, with one very important difference:</p>\n</div>\n<div class=\"paragraph\">\n<p>Code from the local host and all the remote hosts run at the same time,\nin the same browser context. They are not isolated from each other in\nthe browser. All code effectively has the same privileges as the primary\nsession on the local host.</p>\n</div>\n<div class=\"paragraph\">\n<p>Thus, <em>you should only only connect to remote hosts that you trust</em>. You\nmust be sure that none of the hosts that you connect to will cause\nCockpit to load malicious JavaScript code into your browser.</p>\n</div>\n<div class=\"paragraph\">\n<p>Therefore, Cockpit will warn you before connecting to more than one\nhost. It is also possible to disable multiple hosts entirely, and some\noperating systems do this already by default.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can prevent loading of JavaScript, HTML, etc from more than one host\nby adding this to <code>cockpit.conf</code>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>    [WebService]\n    AllowMultiHost=false</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>When you allow multiple hosts in a single Cockpit session by setting\n<code>AllowMultiHost</code> to true, then the user will be warned once per\nsession, before connecting to the second host. If that is still too\nmuch, you can switch the warning off completely by adding the following\nto <code>cockpit.conf</code>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>    [Session]\n    WarnBeforeConnecting=false</pre>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/packages.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Cockpit Packages</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"packages\" class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>Cockpit Packages</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#package-layout\">Layout of Package Files</a></li>\n<li><a href=\"#_package_manifest\">Package Manifest</a></li>\n<li><a href=\"#package-manifest-override\">Manifest overrides</a></li>\n<li><a href=\"#package-links\">Package Links and Paths</a></li>\n<li><a href=\"#package-minified\">Content Negotiation</a></li>\n<li><a href=\"#package-api\">Using Cockpit API</a></li>\n<li><a href=\"#package-bridges\">Bridges for specific tasks</a></li>\n<li><a href=\"#package-replace\">Replacing an existing package</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit is separated into various packages, each of which brings\nspecific features and/or code.</p>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>In addition, any APIs or behavior not explicitly documented here is an\ninternal API and can be changed at any time.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"package-layout\">Layout of Package Files</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>A package consists of one or more files placed in a directory or its\nsubdirectories. It must have a <code>manifest.json</code> file and follow certain\nnaming conventions.</p>\n</div>\n<div class=\"paragraph\">\n<p>The name of a package is the name of the directory.</p>\n</div>\n<div class=\"paragraph\">\n<p>The name of the package must be ASCII alphanumeric, and may contain an\nunderscore. Names of directories and files in the package must consist\nof ASCII alphanumeric along with dash, underscore, dot, and comma. No\nspaces are allowed.</p>\n</div>\n<div class=\"paragraph\">\n<p>Cockpit uses the data directories from the\n<a href=\"https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html\">XDG\nBase Directory Specification</a> to locate packages. The <code>$XDG_DATA_DIRS</code>\nrepresents a colon separate list of system data directories, and\n<code>$XDG_DATA_HOME</code> is a user specific data directory. If the environment\nvariables are not set, defaults are used, according to the spec. If\ncockpit has been built with an alternate <code>--prefix=/path</code> then the\n<code>$prefix/share/cockpit</code> is used by default.</p>\n</div>\n<div class=\"paragraph\">\n<p>A <code>cockpit/</code> subdirectories in any of these data directories is the\nlocation where packages are loaded by Cockpit. If Cockpit finds a\npackage with the same name, in multiple data directories, then the first\none wins. According to the spec the first data directory is\n<code>$XDG_DATA_HOME</code> and then <code>$XDG_DATA_DIRS</code> in order.</p>\n</div>\n<div class=\"paragraph\">\n<p>This means that, by default the following directories are searched for\ncockpit packages, and in this order:</p>\n</div>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><code>~/.local/share/cockpit/</code></p>\n</li>\n<li>\n<p><code>/usr/local/share/cockpit/</code></p>\n</li>\n<li>\n<p><code>/usr/share/cockpit/</code></p>\n</li>\n</ul>\n</div>\n<div class=\"paragraph\">\n<p>Packages placed in <code>$XDG_DATA_HOME</code> are not cached by Cockpit or the\nweb browser. Other packages are cached aggressively, and are accessed\nusing a checksum of the files in the packages and their names.</p>\n</div>\n<div class=\"paragraph\">\n<p>You can use the following command to list the packages installed on a\nserver. You&#8217;ll note that it&#8217;s output may change when you run the command\nas different users, if there are packages installed in the user&#8217;s home\ndirectory.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ cockpit-bridge --packages\n...</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>To further clarify things, here is an example package called\n\"my-package\" and its file layout:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>/usr/share/cockpit/\n    my-package/\n        manifest.json\n        file.html\n        some.js</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Place or symlink packages in your <code>~/.local/share/cockpit</code> directory\n(or appropriate <code>$XDG_DATA_HOME</code> location) that you would like to\nmodify and develop. System installed packages should not change while\nCockpit is running.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_package_manifest\">Package Manifest</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Each package has a <code>manifest.json</code> file. It is a JSON object. The\nfollowing fields may be present in the manifest:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">content-security-policy</dt>\n<dd>\n<p>By default Cockpit serves packages using a strict\n<a href=\"https://en.wikipedia.org/wiki/Content_Security_Policy\">Content Security\nPolicy</a>, which among other things does not allow inline styles or\nscripts. This can be overridden on a per-package basis, with this\nsetting.\n+\nIf the overridden content security policy does not contain a\n<code>default-src</code>, <code>connect-src</code>, <code>base-uri</code>, <code>form-action</code>,\n<code>object-src</code>, or <code>block-all-mixed-content</code> then these will be\nadded to the policy from the manifest.</p>\n</dd>\n<dt class=\"hdlist1\">name</dt>\n<dd>\n<p>An optional string that changes the name of the package. Normally\npackages derive their name from the directory that they are located\nin. This field overrides that name.</p>\n</dd>\n<dt class=\"hdlist1\">priority</dt>\n<dd>\n<p>An optional number that specifies which package is preferred in cases\nwhere there are conflicts. For example given two packages with the\nsame <code>name</code> a package is chosen based on its priority.</p>\n</dd>\n<dt class=\"hdlist1\">conditions</dt>\n<dd>\n<p>An optional list of <code>{\"predicate\": \"value\"}</code> objects. Cockpit will\nonly consider the package if <em>all</em> conditions are met. This is\npreferable to using <code>priority</code>.<br>\n<br>\nCurrently supported predicates are <code>path-exists</code> and <code>path-not-exists</code>\n(since Cockpit 286) and <code>any</code> (since Cockpit 348). <code>any</code> accepts a\nlist of conditions and evaluates to true if <em>at least one</em> of the nested\nconditions is met. Unknown predicates are ignored.</p>\n</dd>\n<dt class=\"hdlist1\">requires</dt>\n<dd>\n<p>An optional JSON object that contains a <code>\"cockpit\"</code> string version\nnumber. The package will only be usable if the Cockpit bridge and\njavascript base are equal or newer than the given version number.</p>\n</dd>\n<dt class=\"hdlist1\">version</dt>\n<dd>\n<p>An informational version number for the package.</p>\n</dd>\n<dt class=\"hdlist1\">preload</dt>\n<dd>\n<p>A list of identifiers of the components that should be preloaded.\nNormally, the files of a component are loaded when the user navigates\nto it for the first time. The files of a preloaded component are\nloaded immediately after the user logs in, and the initialization code\nof the component is invoked.\n+\nThe value of this field is an array of strings, where each string is\none of the keys used in the <code>dashboard</code>, <code>menu</code>, or <code>tool</code>\nfields that are explained below.</p>\n</dd>\n<dt class=\"hdlist1\">parent</dt>\n<dd>\n<p>This option is used when module does not have its own menu item but is\na part of a different module. This is described by JSON object with\nproperties <code>component</code> which takes name of the superordinate\ncomponent and <code>docs</code> with list of documentation URLs for the given\npage. See below for structure of <code>docs</code> property.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>In addition, the following keys contain information about where\ncomponents of the package should appear in Cockpit&#8217;s user interface.\nEach of these keys is optional and contains an object mapping unique\nidentifiers to menu items, which are described below. (The naming of\nthese fields doesn&#8217;t perfectly match the current user interface for\nhistorical reasons.)</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">dashboard</dt>\n<dd>\n<p>Dashboard items appear in the menu under the section <em>Apps</em>.</p>\n</dd>\n<dt class=\"hdlist1\">menu</dt>\n<dd>\n<p>These items appear in the menu under the section <em>System</em>. This\nsection is roughly ordered into these categories (with their <em>order</em>\nin parentheses):\n+</p>\n<div class=\"ulist\">\n<ul>\n<li>\n<p>System Information (10)</p>\n</li>\n<li>\n<p>Logs (20)</p>\n</li>\n<li>\n<p>Configuring major subsystems (30-40)</p>\n</li>\n<li>\n<p>Things running on the machine (VMs, Containers - 50-60)</p>\n</li>\n<li>\n<p>Implementation Details (Accounts, Services - 70-100)</p>\n</li>\n</ul>\n</div>\n</dd>\n<dt class=\"hdlist1\">tools</dt>\n<dd>\n<p>These items appear in the menu under the section <em>Tools</em>.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Menu items and tools are registered using JSON objects that have the\nfollowing properties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">label</dt>\n<dd>\n<p>The label for the menu item or tool.</p>\n</dd>\n<dt class=\"hdlist1\">order</dt>\n<dd>\n<p>An optional order number to place this menu item or tool. Lower\nnumbers are listed first.</p>\n</dd>\n<dt class=\"hdlist1\">path</dt>\n<dd>\n<p>The relative path to the HTML file within the package that implements\nthe menu item or tool.</p>\n</dd>\n<dt class=\"hdlist1\">docs</dt>\n<dd>\n<p>List of documentation URLs for the given page. Each item is an object\ncontaining <code>label</code> and <code>url</code>.</p>\n</dd>\n<dt class=\"hdlist1\">keywords</dt>\n<dd>\n<p>Keywords that describe the page and which are used for searching.\nThese keywords should be lowercase. Keywords is a list containing\nkeyword items as described below. Page label is prepended as first\nkeyword in the first keyword item.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Keyword items are registered using JSON objects that have the following\nproperties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">matches</dt>\n<dd>\n<p>List of keywords to be matched.</p>\n</dd>\n<dt class=\"hdlist1\">goto</dt>\n<dd>\n<p>Optional path that is used for all keywords in this item. When this\nargument starts with slash, then it is used as pathname, otherwise it\nis used as hash. Defining <code>goto:\"page_hash\"</code> in page with\n<code>path:\"/page_path\"</code> would redirect to <code>/page_path#page_hash</code>,\nwhile <code>goto:\"/page_path\"</code> would redirect to <code>/page_path</code> ignoring\ndefault page path.</p>\n</dd>\n<dt class=\"hdlist1\">weight</dt>\n<dd>\n<p>How much keywords are prioritized over others. Default is 3.</p>\n</dd>\n<dt class=\"hdlist1\">translate</dt>\n<dd>\n<p><code>false</code> when keywords should not be localized. Default is <code>true</code>.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>An example manifest.json with some optional properties set:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"version\": 0,\n  \"require\": {\n      \"cockpit\": \"120\"\n  },\n  \"tools\": {\n     \"mytool\": {\n        \"label\": \"My Tool\",\n        \"path\": \"tool.html\"\n     }\n  }\n}</pre>\n</div>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"version\": 0,\n  \"require\": {\n    \"cockpit\": \"120\"\n  },\n  \"conditions\": [\n    {\"path-exists\": \"/usr/bin/mytool\"},\n    {\"path-exists\": \"/etc/mytool.conf\"},\n    {\"path-not-exist\": \"/etc/incompatible-tool\"}\n  ],\n  \"tools\": {\n     \"mytool\": {\n        \"label\": \"My Tool\",\n        \"path\": \"tool.html\"\n     }\n  }\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The following example shows how to use disjunctive conditions with <code>any</code>\nto specify alternative requirements (available since Cockpit 348). This\npackage will be available if either <code>/usr/bin/alt1</code> or <code>/usr/bin/alt2</code>\nexists. In any case, <code>/etc/incompatible-tool</code> must not exist.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>\"conditions\": [\n  {\"any\": [{\"path-exists\": \"/usr/bin/alt1\"}, {\"path-exists\": \"/usr/bin/alt2\"}]},\n  {\"path-not-exists\": \"/etc/incompatible-tool\"}\n]</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"package-manifest-override\">Manifest overrides</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>To change a manifest system-wide, a file\n<code>&lt;package-directory-name&gt;.override.json</code> may be placed into\n<code>/etc/cockpit/</code>, or below <code>$XDG_CONFIG_DIRS</code> if set (see\n<a href=\"./cockpit.conf.5.html\">cockpit.conf</a>). To change it for a particular\nuser only, put the override into <code>~/.config/cockpit</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>These override the information in the manifest in the simple\n<a href=\"https://tools.ietf.org/html/rfc7386\">JSON Merge Patch</a> format.</p>\n</div>\n<div class=\"paragraph\">\n<p>This can be used to hide or modify menu items of an existing package.\nFor example <code>/etc/cockpit/systemd.override.json</code> or\n<code>~/.config/cockpit/systemd.override.json</code> could hide the <em>Logs</em> menu\nitem and move the <em>Services</em> menu item to the top of the menu.</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"menu\": {\n    \"logs\": null,\n    \"services\": {\n      \"order\": -1\n    }\n  }\n}</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"package-links\">Package Links and Paths</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>When referring to files in your package, such as in a hyperlink or a\n<code>&lt;style&gt;</code> tag or <code>&lt;script&gt;</code> tag, simply use a relative path, and\nrefer to the files in the same directory. When you need to refer to\nfiles in another package use a relative link.</p>\n</div>\n<div class=\"paragraph\">\n<p>For example here&#8217;s how to include the base <code>cockpit.js</code> script in your\nHTML from the <code>latest</code> package:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>&lt;script src=\"../base1/cockpit.js\"&gt;&lt;/script&gt;</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Do not assume you can link to any file in any other package. Refer to\nthe <a href=\"#development\">list of API packages</a> for those that are available\nfor use.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"package-minified\">Content Negotiation</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>In order to support gzipped and/or minified data, the files in a package\nare loaded using content negotiation logic. A HTTP request for the file\n<code>test.js</code> in the package named <code>mypackage</code> will return\n<code>mypackage/test.js</code> or <code>mypackage/test.js.gz</code> (in undefined\npreference). If neither exists, then it returns\n<code>mypackage/test.js.min</code> or <code>mypackage/test.js.min.gz</code> (again in\nundefined preference).</p>\n</div>\n<div class=\"paragraph\">\n<p>When packages are loaded from a system directory, Cockpit optimizes the\nfile system lookups above, by pre-listing the files. This is one of the\nreasons that you should never change packages installed to a system\ndirectory while Cockpit is running.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"package-api\">Using Cockpit API</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit has API available for writing packages. There is no API\navailable for external callers to invoke via HTTP, REST or otherwise.</p>\n</div>\n<div class=\"paragraph\">\n<p>API from various packages can be used to implement Cockpit packages.\nEach package listed here has some API available for use. Only the API\nexplicitly documented should be used.</p>\n</div>\n<div class=\"ulist\">\n<ul>\n<li>\n<p><a href=\"#development\">API Listing</a></p>\n</li>\n</ul>\n</div>\n<div class=\"paragraph\">\n<p>To include javascript from the API, simply load it into your HTML using\na script tag. Alternatively you can use an javascript loader.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"package-bridges\">Bridges for specific tasks</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>On the server side the <a href=\"#cockpit-bridge.1\"><code>cockpit-bridge</code></a>\nconnects to various system APIs that the front end UI requests it to.\nThere are additional bridges for specific tasks that the main\n<code>cockpit-bridge</code> cannot handle, such as using the PCP C library API.</p>\n</div>\n<div class=\"paragraph\">\n<p>These additional bridges can be registered in a <code>\"bridges\"</code> section of\na package&#8217;s <code>manifest.json</code> file. Building such a bridge is a complex\ntasks, and we will skip over that here. However it is useful to adjust\nhow these additional bridges are called, and so we&#8217;ll look at how they\nare registered.</p>\n</div>\n<div class=\"paragraph\">\n<p>An example <code>manifest.json</code> with a bridges section:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n    \"bridges\": [\n        {\n            \"match\": { \"payload\": \"metrics1\" },\n            \"spawn\": [ \"/usr/libexec/cockpit-pcp\" ]\n        }\n    ]\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The bridges are considered in the order they are listed in the array.\nUse the <code>manifest.json`</code>\"priority\"` field to control order between\npackages. The bridges are registered using JSON objects that have the\nfollowing properties:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">environ</dt>\n<dd>\n<p>Optional, additional environment variables to pass to the bridge\ncommand.</p>\n</dd>\n<dt class=\"hdlist1\">match</dt>\n<dd>\n<p>The <code>\"match\"</code> object describes which channel open command options\nneed to match for a given channel to be handed over to this bridge.</p>\n</dd>\n<dt class=\"hdlist1\">privileged</dt>\n<dd>\n<p>If set to <code>true</code>, this marks the bridge as a superuser bridge.\nCockpit will start one of these explicitly when trying to escalate the\nprivileges of a session. A privileged bridge can not have a\n<code>\"match\"</code> property.</p>\n</dd>\n<dt class=\"hdlist1\">label</dt>\n<dd>\n<p>Setting this enables selection of privileged bridges in the UI. When\nno privileged bridge has a <code>label</code>, then Cockpit will start the\nbridge that runs <code>sudo</code>. This is the case in a default Cockpit\ninstallation. When at least one privileged bridge has a <code>label</code> then\nthe user can select one of them when escalating privileges. As a\nspecial case, if only one bridge has a <code>label</code>, then the step of\nselecting a bridge is omitted in the UI and that one bridge is always\nstarted.\n+\nThus, if you add a privileged bridge with a <code>label</code> in a new\nmanifest, Cockpit will use that bridge the next time a user opens the\n\"Administrative access\" dialog. If you want the user to choose between\nthe <code>sudo</code> method and your new one, you need to duplicate the\n<code>sudo</code> bridge definition in your manifest and give it a label.</p>\n</dd>\n<dt class=\"hdlist1\">problem</dt>\n<dd>\n<p>If a problem is specified, and this bridge fails to start up then\nchannels will be closed with this problem code. Otherwise later\nbridges or internal handlers for the channel will be invoked.</p>\n</dd>\n<dt class=\"hdlist1\">spawn</dt>\n<dd>\n<p>The command and arguments to invoke.</p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>The <code>spawn</code> and <code>environ</code> values can be dynamically taken from a\nmatching open command values. When a value in either the <code>spawn</code> or\n<code>environ</code> array contains a named variable wrapped in <code>${}</code>, the\nvariable will be replaced with the value contained in the matching open\ncommand. Only named variables are supported and name can only contain\nletters, numbers and the following symbols: <code>._-</code></p>\n</div>\n<div class=\"paragraph\">\n<p>For example a bridges section like:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"bridges\": [\n    {\n      \"match\": { \"payload\": \"example\" },\n      \"environ\": [ \"TAG=${tag}\" ],\n      \"spawn: [ \"/example-bridge\", \"--tag\", \"${tag}\" ],\n      \"problem\": \"access-denied\"\n    }\n  ]\n}</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>when a open command is received with a payload of <code>example</code> with\n<code>tag</code> value of <code>tag1</code>. The following command will be spawned</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>TAG=tag1 /example-bridge --tag tag1</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Processes that are reused so if another open command with a \"tag\" of\n<code>tag1</code> is received. The open command will be passed to existing\nprocess, rather than spawning a new one. However a open command with an\ntag of <code>tag2</code> will spawn a new command:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>TAG=tag2 /example-bridge --tag tag2</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If you need to include <code>${}</code>, as an actual value in your arguments you\ncan escape it by prefixing it with a <code>\\</code></p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"package-replace\">Replacing an existing package</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>If the functionality in a package replaces that of another package then\nit can replace that package by claiming the same <code>name</code> and a higher\n<code>priority</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>For example, a package in the <code>/usr/share/cockpit/disks</code> directory\ncould replace Cockpit&#8217;s <em>storage</em> package with a <code>manifest.json</code> like\nthis:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"version\": 0,\n  \"name\": \"storage\",\n  \"priority\": 10,\n  \"menu\": {\n     \"index\": {\n        \"label\": \"Disk Storage\",\n        \"order\": 15\n     }\n  }\n}</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/pam_ssh_add.8.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>pam_ssh_add(8)</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>pam_ssh_add(8)</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#_name\">Name</a></li>\n<li><a href=\"#_description\">Description</a></li>\n<li><a href=\"#_options\">Options</a></li>\n<li><a href=\"#_examples\">Examples</a></li>\n<li><a href=\"#_bugs\">Bugs</a></li>\n<li><a href=\"#_author\">Author</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div class=\"sect1\">\n<h2 id=\"_name\">Name</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>pam_ssh_add - PAM module to auto load ssh keys into an agent</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_description\">Description</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p><strong>pam_ssh_add</strong> provides authentication and session modules that allow users\nto start their session with a running ssh-agent with as many ssh keys\nloaded as possible.</p>\n</div>\n<div class=\"paragraph\">\n<p>If used, the authentication module simply stores the authentication\ntoken for later use by the session module. Because this module performs\nno actual authentication it returns PAM_CRED_INSUFFICIENT on success and\nshould always be accompanied by an actual authentication module in your\npam configuration.</p>\n</div>\n<div class=\"paragraph\">\n<p>By default the session module will start a new ssh-agent and run\nssh-add, loading any keys that exist in the default path for the newly\nlogged in user. If any keys prompt for a password, and a authentication\ntoken was successfully stored, that token will be provided as the\npassword.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_options\">Options</h2>\n<div class=\"sectionbody\">\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"><strong>debug</strong></dt>\n<dd>\n<p>This option will turn on debug logging to syslog.</p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_examples\">Examples</h2>\n<div class=\"sectionbody\">\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>        auth     required  pam_unix.so\n        auth     optional  pam_ssh_add.so\n        session  optional  pam_ssh_add.so</pre>\n</div>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_bugs\">Bugs</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Please send bug reports to either the distribution bug tracker or the <a href=\"https://github.com/cockpit-project/cockpit/issues/new\">upstream bug tracker</a>.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"_author\">Author</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit has been written by many\n<a href=\"https://github.com/cockpit-project/cockpit\">contributors</a>.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/privileges.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Privileges and Permissions</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"privileges\" class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>Privileges and Permissions</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#privileges-polkit\">Customizing Polkit Privileges</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>When a user is logged into Cockpit, they are logged into a normal\nsession that has exactly the same privileges as if they logged in via\nSSH or on the console.</p>\n</div>\n<div class=\"paragraph\">\n<p>However, Cockpit will usually try to escalate the privileges of the user\nusing <a href=\"https://www.freedesktop.org/wiki/Software/polkit/\">Policy Kit</a> or\n<a href=\"https://www.sudo.ws/\">sudo</a>. If the user is able to escalate privileges\nfrom the command line by typing in their password again (or without\ntyping in any password), then Cockpit will be able to escalate the\nprivileges of the session to \"root\" immediately upon login.</p>\n</div>\n<div class=\"paragraph\">\n<p>The user can change the privileges of a session from within that\nsession, via the \"Administrative access\" indicator in the top bar. From\nthat indicator, the user can drop \"root\" privileges and regain them. On\nthe next login, Cockpit will give the session the same privileges.</p>\n</div>\n<div class=\"paragraph\">\n<p>Usually a user needs to be in the <code>wheel</code> Unix user group for the user\nto be able to escalate privileges in this way. However both Policy Kit\nand sudo may be configured to use other criteria.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"privileges-polkit\">Customizing Polkit Privileges</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Services like\n<a href=\"https://www.freedesktop.org/wiki/Software/systemd/\">systemd</a> and\n<a href=\"https://wiki.gnome.org/Projects/NetworkManager\">NetworkManager</a> use\n<a href=\"https://www.freedesktop.org/wiki/Software/polkit/\">Polkit</a> to validate\nand escalate privileges. It is possible to customize these rules with\nfiles in <code>/etc/polkit-1/rules.d</code>.</p>\n</div>\n<div class=\"paragraph\">\n<p>Polkit rules files are\n<a href=\"https://www.freedesktop.org/software/polkit/docs/latest/polkit.8.html\">javascript\nwith specific methods and objects</a>. For example, placing the following\npolkit rule to <code>/etc/polkit-1/rules.d/10-operators.rule</code> allows all\nusers in the <code>operators</code> group to start, stop, restart and otherwise\nmanage systemd services:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>polkit.addRule(function(action, subject) {\n    if (action.id == \"org.freedesktop.systemd1.manage-units\") {\n        if (subject.isInGroup(\"operators\")) {\n            return polkit.Result.YES;\n        }\n    }\n});</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>In order to allow a certain group to perform any administrative action\nyou could add a rule like this:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>polkit.addAdminRule(function(action, subject) {\n    return [\"unix-group:operators\"];\n});</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/sso.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Single Sign On</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"sso\" class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>Single Sign On</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#sso-server\">Server Requirements</a></li>\n<li><a href=\"#sso-client\">Client Requirements</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit can use Kerberos for Single Sign On authentication, where users\nare automatically authenticated if they have a valid Kerberos ticket.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"sso-server\">Server Requirements</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>To authenticate users, the server that Cockpit is running on must be\njoined to a domain. This can usually be accomplished using the\n<a href=\"https://freedesktop.org/software/realmd/docs/realm.html\"><code>realm join example.com</code></a>\ncommand.</p>\n</div>\n<div class=\"paragraph\">\n<p>The domain must be resolvable by DNS. For instance, the SRV records of\nthe kerberos server should be resolvable:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ host -t SRV  _kerberos._udp.example.com\n_kerberos._udp.example.com has SRV record 0 100 88 dc.example.com</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The server running Cockpit should have a fully qualified name that ends\nwith the domain name.</p>\n</div>\n<div class=\"paragraph\">\n<p>There must be a valid Kerberos host key for the server in the\n<code>/etc/krb5.keytab</code> file. Alternatively, if you would like to use a\ndifferent keytab, you can do so by placing it in\n<code>/etc/cockpit/krb5.keytab</code>, or below <code>$XDG_CONFIG_DIRS</code> if set (see\n<a href=\"./cockpit.conf.5.html\">cockpit.conf</a>). It may be necessary to create\na kerberos service principal and update the keytab if it is not present.\nDepending on your domain type different service names are required:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Active Directory</dt>\n<dd>\n<p><code>HOST/server.example.com@EXAMPLE.COM</code></p>\n</dd>\n<dt class=\"hdlist1\">IPA and MIT</dt>\n<dd>\n<p><code>HTTP/server.example.com@EXAMPLE.COM</code></p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>When joining an IPA domain with Cockpit and the <code>ipa</code> command line\ntool is available, both the service principal name and a\n<code>/etc/cockpit/krb5.keytab</code> get created automatically, so that Kerberos\nbased single sign on into Cockpit works out of the box. If you want/need\nto do this by hand or in a script, first create or modify the <code>HTTP/</code>\nservice principal:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo ipa service-add --ok-as-delegate=true --ok-to-auth-as-delegate=true \\\n    HTTP/server.example.com@EXAMPLE.COM\n# or, if it already exists, just enable delegation:\n$ sudo ipa service-mod --ok-as-delegate=true --ok-to-auth-as-delegate=true \\\n    HTTP/server.example.com@EXAMPLE.COM</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Then generate a key for that principal:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo ipa-getkeytab -p HTTP/server.example.com@EXAMPLE.COM -k /etc/cockpit/krb5.keytab</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>The following command can be used to list the\n<code>/etc/cockpit/krb5.keytab</code>:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo klist -k /etc/cockpit/krb5.keytab</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Lastly accounts from the domain must be resolvable to unix accounts on\nthe server running Cockpit. For example:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ getent passwd user@example.com\nuser@example.com:*:381001109:381000513:User Name:/home/user:/bin/sh</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If you wish to delegate your kerberos credentials to Cockpit, and allow\nCockpit to then connect to other machines using those credentials, you\nshould enable delegation for the hosts running Cockpit, and in some\ncases the <code>HTTP</code> service as well. When joining an IPA domain, this is\nenabled by default.</p>\n</div>\n<div class=\"paragraph\">\n<p>Domain admins (usually the <code>admins@example.com</code> group) should normally\nalso be able to administer any joined machine. Enable sudo access for\nthat group with the following command on the IPA server, for version\n4.7.1 and later:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>ipa-advise enable-admins-sudo | sh -ex</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>On earlier FreeIPA versions, run these commands instead, as a domain\nadmin on any joined machine:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>ipa sudorule-add --hostcat=all --cmdcat=all All\nipa sudorule-add-user --groups=admins All</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Note that this does not change security properties; domain admins can\ngive this privilege to themselves, so it is safe to enable by default.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"sso-client\">Client Requirements</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The client side, where your web browser is running, should have a valid\nkerberos ticket in the current user session. A command like this will\nget one:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ kinit user@EXAMPLE.COM\nPassword for user@EXAMPLE.COM:</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>In addition your browser must be usually be configured to allow kerberos\nauthentication for the domain.</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Mozilla Firefox</dt>\n<dd>\n<p>Go to <code>about:config</code> and set the\n<code>network.negotiate-auth.trusted-uris</code> setting to your domain name\npreceded by a dot, ie: <code>.example.com</code></p>\n</dd>\n<dt class=\"hdlist1\">Google Chrome</dt>\n<dd>\n<p>On Linux: create the file\n<code>/etc/opt/chrome/policies/managed/example-com.json</code> with the\ncontents:</p>\n</dd>\n<dt class=\"hdlist1\"></dt>\n</dl>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"AuthServerWhitelist\": \"*example.com\"\n}</pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"></dt>\n<dd>\n<p>and restart the browser. On other platforms, exit your browser\ncompletely, and start it with a command line like this:\n<code>google-chrome --auth-server-whitelist=*example.com</code></p>\n</dd>\n</dl>\n</div>\n<div class=\"paragraph\">\n<p>Use a fully qualified server name (with the domain name at the end) to\naccess Cockpit in your web browser.</p>\n</div>\n<div class=\"paragraph\">\n<p>If you wish to connect from one server to another in Cockpit using\nkerberos SSO, then you have to explicitly enable all sorts of things.\nFor starters, make sure that delegated credentials are allowed by your\ndomain (see above). Next when requesting your kerberos ticket make sure\nthat forwardable tickets are requested:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ kinit -f user@EXAMPLE.COM\nPassword for user@EXAMPLE.COM:</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Make sure that the forwardable flag <code>F</code> is present in your ticket:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ klist -f\nTicket cache: KEYRING:persistent:1000:1000\nDefault principal: user@EXAMPLE.COM\n\nValid starting       Expires              Service principal\n18.03.2017 05:39:23  19.03.2017 05:39:20  krbtgt/EXAMPLE.COM@EXAMPLE.COM\n    Flags: FIA</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>Lastly configure your browser to allow delegated, forwardable kerberos\ncredentials to be sent to Cockpit:</p>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\">Mozilla Firefox</dt>\n<dd>\n<p>Go to <code>about:config</code> and set the\n<code>network.negotiate-auth.delegation-uris</code> setting to your domain name\npreceded by a dot, ie: <code>.example.com</code></p>\n</dd>\n<dt class=\"hdlist1\">Google Chrome</dt>\n<dd>\n<p>On Linux: create the file\n<code>/etc/opt/chrome/policies/managed/example-com.json</code> with the\ncontents:</p>\n</dd>\n<dt class=\"hdlist1\"></dt>\n</dl>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>{\n  \"AuthServerWhitelist\": \"*example.com\",\n  \"AuthNegotiateDelegateWhitelist\": \"*example.com\"\n}</pre>\n</div>\n</div>\n<div class=\"dlist\">\n<dl>\n<dt class=\"hdlist1\"></dt>\n<dd>\n<p>and restart the browser. On other platforms, exit your browser\ncompletely, and start it with a command line like this:\n<code>google-chrome --auth-server-whitelist=*example.com --auth-negotiate-delegate-whitelist=*example.com</code></p>\n</dd>\n</dl>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/startup.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Start up</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"startup\" class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>Start up</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#startup-shutdown\">Process exit</a></li>\n<li><a href=\"#startup-boot\">Boot start up</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit&#8217;s <code>cockpit-ws</code> component is what the browser connects to and\nit typically starts on demand via\n<a href=\"https://www.freedesktop.org/wiki/Software/systemd/\"><code>systemd</code></a> socket\nactivation.</p>\n</div>\n<div class=\"paragraph\">\n<p>The actual <code>cockpit.service</code> and <code>cockpit-ws</code> process will start on\ndemand when a browser accesses the <code>cockpit.socket</code>,\n<a href=\"#listen\">usually on port 9090</a>. Once a user logs in then a\n<code>cockpit-bridge</code> process will be started in a Linux user login\nsession.</p>\n</div>\n<div class=\"paragraph\">\n<p>Only systems that you connect to with your browser need to have the\n<code>cockpit.socket</code> enabled. For systems that you add through host\nswitcher the bridge is started via SSH on demand.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"startup-shutdown\">Process exit</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The <code>cockpit-bridge</code> process will exit when the user logs out. In\naddition, after 10 minutes of inactivity, the <code>cockpit-ws</code> process\nwill exit on its own. The browser will automatically disconnect if it\nfails to hear from the <code>cockpit-ws</code> process for 30 seconds.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"startup-boot\">Boot start up</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>To make Cockpit available by default after system boot the\n<code>cockpit.socket</code> needs to be enabled:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo systemctl enable cockpit.socket</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>If you wish to not have Cockpit available by default via a browser, then\nthe <code>cockpit.socket</code> should be disabled:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>$ sudo systemctl disable cockpit.socket</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "guide/latest/urls.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"UTF-8\">\n<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n<meta name=\"generator\" content=\"Asciidoctor 2.0.26\">\n<title>Cockpit URLs</title>\n<style>\n/*! Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */\n/* Uncomment the following line when using as a custom stylesheet */\n/* @import \"https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700\"; */\nhtml{font-family:sans-serif;-webkit-text-size-adjust:100%}\na{background:none}\na:focus{outline:thin dotted}\na:active,a:hover{outline:0}\nh1{font-size:2em;margin:.67em 0}\nb,strong{font-weight:bold}\nabbr{font-size:.9em}\nabbr[title]{cursor:help;border-bottom:1px dotted #dddddf;text-decoration:none}\ndfn{font-style:italic}\nhr{height:0}\nmark{background:#ff0;color:#000}\ncode,kbd,pre,samp{font-family:monospace;font-size:1em}\npre{white-space:pre-wrap}\nq{quotes:\"\\201C\" \"\\201D\" \"\\2018\" \"\\2019\"}\nsmall{font-size:80%}\nsub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}\nsup{top:-.5em}\nsub{bottom:-.25em}\nimg{border:0}\nsvg:not(:root){overflow:hidden}\nfigure{margin:0}\naudio,video{display:inline-block}\naudio:not([controls]){display:none;height:0}\nfieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}\nlegend{border:0;padding:0}\nbutton,input,select,textarea{font-family:inherit;font-size:100%;margin:0}\nbutton,input{line-height:normal}\nbutton,select{text-transform:none}\nbutton,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}\nbutton[disabled],html input[disabled]{cursor:default}\ninput[type=checkbox],input[type=radio]{padding:0}\nbutton::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}\ntextarea{overflow:auto;vertical-align:top}\ntable{border-collapse:collapse;border-spacing:0}\n*,::before,::after{box-sizing:border-box}\nhtml,body{font-size:100%}\nbody{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;line-height:1;position:relative;cursor:auto;-moz-tab-size:4;-o-tab-size:4;tab-size:4;word-wrap:anywhere;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}\na:hover{cursor:pointer}\nimg,object,embed{max-width:100%;height:auto}\nobject,embed{height:100%}\nimg{-ms-interpolation-mode:bicubic}\n.left{float:left!important}\n.right{float:right!important}\n.text-left{text-align:left!important}\n.text-right{text-align:right!important}\n.text-center{text-align:center!important}\n.text-justify{text-align:justify!important}\n.hide{display:none}\nimg,object,svg{display:inline-block;vertical-align:middle}\ntextarea{height:auto;min-height:50px}\nselect{width:100%}\n.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}\ndiv,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0}\na{color:#2156a5;text-decoration:underline;line-height:inherit}\na:hover,a:focus{color:#1d4b8f}\na img{border:0}\np{line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}\np aside{font-size:.875em;line-height:1.35;font-style:italic}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}\nh1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}\nh1{font-size:2.125em}\nh2{font-size:1.6875em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}\nh4,h5{font-size:1.125em}\nh6{font-size:1em}\nhr{border:solid #dddddf;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em}\nem,i{font-style:italic;line-height:inherit}\nstrong,b{font-weight:bold;line-height:inherit}\nsmall{font-size:60%;line-height:inherit}\ncode{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;font-weight:400;color:rgba(0,0,0,.9)}\nul,ol,dl{line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}\nul,ol{margin-left:1.5em}\nul li ul,ul li ol{margin-left:1.25em;margin-bottom:0}\nul.circle{list-style-type:circle}\nul.disc{list-style-type:disc}\nul.square{list-style-type:square}\nul.circle ul:not([class]),ul.disc ul:not([class]),ul.square ul:not([class]){list-style:inherit}\nol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}\ndl dt{margin-bottom:.3125em;font-weight:bold}\ndl dd{margin-bottom:1.25em}\nblockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}\nblockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}\n@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}\nh1{font-size:2.75em}\nh2{font-size:2.3125em}\nh3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}\nh4{font-size:1.4375em}}\ntable{background:#fff;margin-bottom:1.25em;border:1px solid #dedede;word-wrap:normal}\ntable thead,table tfoot{background:#f7f8f7}\ntable thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}\ntable tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}\ntable tr.even,table tr.alt{background:#f8f8f7}\ntable thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{line-height:1.6}\nh1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}\nh1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}\n.center{margin-left:auto;margin-right:auto}\n.stretch{width:100%}\n.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:\" \";display:table}\n.clearfix::after,.float-group::after{clear:both}\n:not(pre).nobreak{word-wrap:normal}\n:not(pre).nowrap{white-space:nowrap}\n:not(pre).pre-wrap{white-space:pre-wrap}\n:not(pre):not([class^=L])>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background:#f7f7f8;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}\npre{color:rgba(0,0,0,.9);font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;line-height:1.45;text-rendering:optimizeSpeed}\npre code,pre pre{color:inherit;font-size:inherit;line-height:inherit}\npre.nowrap,pre.nowrap pre{white-space:pre;word-wrap:normal}\nem em{font-style:normal}\nstrong strong{font-weight:400}\n.keyseq{color:rgba(51,51,51,.8)}\nkbd{font-family:\"Droid Sans Mono\",\"DejaVu Sans Mono\",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background:#f7f7f7;border:1px solid #ccc;border-radius:3px;box-shadow:0 1px 0 rgba(0,0,0,.2),inset 0 0 0 .1em #fff;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}\n.keyseq kbd:first-child{margin-left:0}\n.keyseq kbd:last-child{margin-right:0}\n.menuseq,.menuref{color:#000}\n.menuseq b:not(.caret),.menuref{font-weight:inherit}\n.menuseq{word-spacing:-.02em}\n.menuseq b.caret{font-size:1.25em;line-height:.8}\n.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}\nb.button::before,b.button::after{position:relative;top:-1px;font-weight:400}\nb.button::before{content:\"[\";padding:0 3px 0 2px}\nb.button::after{content:\"]\";padding:0 2px 0 3px}\np a>code:hover{color:rgba(0,0,0,.9)}\n#header,#content,#footnotes,#footer{width:100%;margin:0 auto;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}\n#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:\" \";display:table}\n#header::after,#content::after,#footnotes::after,#footer::after{clear:both}\n#content{margin-top:1.25em}\n#content::before{content:none}\n#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}\n#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #dddddf}\n#header>h1:only-child{border-bottom:1px solid #dddddf;padding-bottom:8px}\n#header .details{border-bottom:1px solid #dddddf;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:flex;flex-flow:row wrap}\n#header .details span:first-child{margin-left:-.125em}\n#header .details span.email a{color:rgba(0,0,0,.85)}\n#header .details br{display:none}\n#header .details br+span::before{content:\"\\00a0\\2013\\00a0\"}\n#header .details br+span.author::before{content:\"\\00a0\\22c5\\00a0\";color:rgba(0,0,0,.85)}\n#header .details br+span#revremark::before{content:\"\\00a0|\\00a0\"}\n#header #revnumber{text-transform:capitalize}\n#header #revnumber::after{content:\"\\00a0\"}\n#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #dddddf;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}\n#toc{border-bottom:1px solid #e7e7e9;padding-bottom:.5em}\n#toc>ul{margin-left:.125em}\n#toc ul.sectlevel0>li>a{font-style:italic}\n#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}\n#toc ul{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;list-style-type:none}\n#toc li{line-height:1.3334;margin-top:.3334em}\n#toc a{text-decoration:none}\n#toc a:active{text-decoration:underline}\n#toctitle{color:#7a2518;font-size:1.2em}\n@media screen and (min-width:768px){#toctitle{font-size:1.375em}\nbody.toc2{padding-left:15em;padding-right:0}\nbody.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #dddddf;padding-bottom:8px}\n#toc.toc2{margin-top:0!important;background:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #e7e7e9;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}\n#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}\n#toc.toc2>ul{font-size:.9em;margin-bottom:0}\n#toc.toc2 ul ul{margin-left:0;padding-left:1em}\n#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}\nbody.toc2.toc-right{padding-left:0;padding-right:15em}\nbody.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #e7e7e9;left:auto;right:0}}\n@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}\n#toc.toc2{width:20em}\n#toc.toc2 #toctitle{font-size:1.375em}\n#toc.toc2>ul{font-size:.95em}\n#toc.toc2 ul ul{padding-left:1.25em}\nbody.toc2.toc-right{padding-left:0;padding-right:20em}}\n#content #toc{border:1px solid #e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;border-radius:4px}\n#content #toc>:first-child{margin-top:0}\n#content #toc>:last-child{margin-bottom:0}\n#footer{max-width:none;background:rgba(0,0,0,.8);padding:1.25em}\n#footer-text{color:hsla(0,0%,100%,.8);line-height:1.44}\n#content{margin-bottom:.625em}\n.sect1{padding-bottom:.625em}\n@media screen and (min-width:768px){#content{margin-bottom:1.25em}\n.sect1{padding-bottom:1.25em}}\n.sect1:last-child{padding-bottom:0}\n.sect1+.sect1{border-top:1px solid #e7e7e9}\n#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}\n#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:\"\\00A7\";font-size:.85em;display:block;padding-top:.1em}\n#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}\n#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}\n#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}\ndetails,.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}\ndetails{margin-left:1.25rem}\ndetails>summary{cursor:pointer;display:block;position:relative;line-height:1.6;margin-bottom:.625rem;outline:none;-webkit-tap-highlight-color:transparent}\ndetails>summary::-webkit-details-marker{display:none}\ndetails>summary::before{content:\"\";border:solid transparent;border-left:solid;border-width:.3em 0 .3em .5em;position:absolute;top:.5em;left:-1.25rem;transform:translateX(15%)}\ndetails[open]>summary::before{border:solid transparent;border-top:solid;border-width:.5em .3em 0;transform:translateY(15%)}\ndetails>summary::after{content:\"\";width:1.25rem;height:1em;position:absolute;top:.3em;left:-1.25rem}\n.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:\"Noto Serif\",\"DejaVu Serif\",serif;font-size:1rem;font-style:italic}\ntable.tableblock.fit-content>caption.title{white-space:nowrap;width:0}\n.paragraph.lead>p,#preamble>.sectionbody>[class=paragraph]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}\n.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}\n.admonitionblock>table td.icon{text-align:center;width:80px}\n.admonitionblock>table td.icon img{max-width:none}\n.admonitionblock>table td.icon .title{font-weight:bold;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;text-transform:uppercase}\n.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #dddddf;color:rgba(0,0,0,.6);word-wrap:anywhere}\n.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}\n.exampleblock>.content{border:1px solid #e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;border-radius:4px}\n.sidebarblock{border:1px solid #dbdbd6;margin-bottom:1.25em;padding:1.25em;background:#f3f3f2;border-radius:4px}\n.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}\n.exampleblock>.content>:first-child,.sidebarblock>.content>:first-child{margin-top:0}\n.exampleblock>.content>:last-child,.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}\n.literalblock pre,.listingblock>.content>pre{border-radius:4px;overflow-x:auto;padding:1em;font-size:.8125em}\n@media screen and (min-width:768px){.literalblock pre,.listingblock>.content>pre{font-size:.90625em}}\n@media screen and (min-width:1280px){.literalblock pre,.listingblock>.content>pre{font-size:1em}}\n.literalblock pre,.listingblock>.content>pre:not(.highlight),.listingblock>.content>pre[class=highlight],.listingblock>.content>pre[class^=\"highlight \"]{background:#f7f7f8}\n.literalblock.output pre{color:#f7f7f8;background:rgba(0,0,0,.9)}\n.listingblock>.content{position:relative}\n.listingblock pre>code{display:block}\n.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:inherit;opacity:.5}\n.listingblock:hover code[data-lang]::before{display:block}\n.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:inherit;opacity:.5}\n.listingblock.terminal pre .command:not([data-prompt])::before{content:\"$\"}\n.listingblock pre.highlightjs{padding:0}\n.listingblock pre.highlightjs>code{padding:1em;border-radius:4px}\n.listingblock pre.prettyprint{border-width:0}\n.prettyprint{background:#f7f7f8}\npre.prettyprint .linenums{line-height:1.45;margin-left:2em}\npre.prettyprint li{background:none;list-style-type:inherit;padding-left:0}\npre.prettyprint li code[data-lang]::before{opacity:1}\npre.prettyprint li:not(:first-child) code[data-lang]::before{display:none}\ntable.linenotable{border-collapse:separate;border:0;margin-bottom:0;background:none}\ntable.linenotable td[class]{color:inherit;vertical-align:top;padding:0;line-height:inherit;white-space:normal}\ntable.linenotable td.code{padding-left:.75em}\ntable.linenotable td.linenos,pre.pygments .linenos{border-right:1px solid;opacity:.35;padding-right:.5em;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}\npre.pygments span.linenos{display:inline-block;margin-right:.75em}\n.quoteblock{margin:0 1em 1.25em 1.5em;display:table}\n.quoteblock:not(.excerpt)>.title{margin-left:-1.5em;margin-bottom:.75em}\n.quoteblock blockquote,.quoteblock p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}\n.quoteblock blockquote{margin:0;padding:0;border:0}\n.quoteblock blockquote::before{content:\"\\201c\";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}\n.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}\n.quoteblock .attribution{margin-top:.75em;margin-right:.5ex;text-align:right}\n.verseblock{margin:0 1em 1.25em}\n.verseblock pre{font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}\n.verseblock pre strong{font-weight:400}\n.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}\n.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}\n.quoteblock .attribution br,.verseblock .attribution br{display:none}\n.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}\n.quoteblock.abstract blockquote::before,.quoteblock.excerpt blockquote::before,.quoteblock .quoteblock blockquote::before{display:none}\n.quoteblock.abstract blockquote,.quoteblock.abstract p,.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{line-height:1.6;word-spacing:0}\n.quoteblock.abstract{margin:0 1em 1.25em;display:block}\n.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}\n.quoteblock.excerpt>blockquote,.quoteblock .quoteblock{padding:0 0 .25em 1em;border-left:.25em solid #dddddf}\n.quoteblock.excerpt,.quoteblock .quoteblock{margin-left:0}\n.quoteblock.excerpt blockquote,.quoteblock.excerpt p,.quoteblock .quoteblock blockquote,.quoteblock .quoteblock p{color:inherit;font-size:1.0625rem}\n.quoteblock.excerpt .attribution,.quoteblock .quoteblock .attribution{color:inherit;font-size:.85rem;text-align:left;margin-right:0}\np.tableblock:last-child{margin-bottom:0}\ntd.tableblock>.content{margin-bottom:1.25em;word-wrap:anywhere}\ntd.tableblock>.content>:last-child{margin-bottom:-1.25em}\ntable.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}\ntable.grid-all>*>tr>*{border-width:1px}\ntable.grid-cols>*>tr>*{border-width:0 1px}\ntable.grid-rows>*>tr>*{border-width:1px 0}\ntable.frame-all{border-width:1px}\ntable.frame-ends{border-width:1px 0}\ntable.frame-sides{border-width:0 1px}\ntable.frame-none>colgroup+*>:first-child>*,table.frame-sides>colgroup+*>:first-child>*{border-top-width:0}\ntable.frame-none>:last-child>:last-child>*,table.frame-sides>:last-child>:last-child>*{border-bottom-width:0}\ntable.frame-none>*>tr>:first-child,table.frame-ends>*>tr>:first-child{border-left-width:0}\ntable.frame-none>*>tr>:last-child,table.frame-ends>*>tr>:last-child{border-right-width:0}\ntable.stripes-all>*>tr,table.stripes-odd>*>tr:nth-of-type(odd),table.stripes-even>*>tr:nth-of-type(even),table.stripes-hover>*>tr:hover{background:#f8f8f7}\nth.halign-left,td.halign-left{text-align:left}\nth.halign-right,td.halign-right{text-align:right}\nth.halign-center,td.halign-center{text-align:center}\nth.valign-top,td.valign-top{vertical-align:top}\nth.valign-bottom,td.valign-bottom{vertical-align:bottom}\nth.valign-middle,td.valign-middle{vertical-align:middle}\ntable thead th,table tfoot th{font-weight:bold}\ntbody tr th{background:#f7f8f7}\ntbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}\np.tableblock>code:only-child{background:none;padding:0}\np.tableblock{font-size:1em}\nol{margin-left:1.75em}\nul li ol{margin-left:1.5em}\ndl dd{margin-left:1.125em}\ndl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}\nli p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}\nul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}\nul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}\nul.unstyled,ol.unstyled{margin-left:0}\nli>p:empty:only-child::before{content:\"\";display:inline-block}\nul.checklist>li>p:first-child{margin-left:-1em}\nul.checklist>li>p:first-child>.fa-square-o:first-child,ul.checklist>li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}\nul.checklist>li>p:first-child>input[type=checkbox]:first-child{margin-right:.25em}\nul.inline{display:flex;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}\nul.inline>li{margin-left:1.25em}\n.unstyled dl dt{font-weight:400;font-style:normal}\nol.arabic{list-style-type:decimal}\nol.decimal{list-style-type:decimal-leading-zero}\nol.loweralpha{list-style-type:lower-alpha}\nol.upperalpha{list-style-type:upper-alpha}\nol.lowerroman{list-style-type:lower-roman}\nol.upperroman{list-style-type:upper-roman}\nol.lowergreek{list-style-type:lower-greek}\n.hdlist>table,.colist>table{border:0;background:none}\n.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}\ntd.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}\ntd.hdlist1{font-weight:bold;padding-bottom:1.25em}\ntd.hdlist2{word-wrap:anywhere}\n.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}\n.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}\n.colist td:not([class]):first-child img{max-width:none}\n.colist td:not([class]):last-child{padding:.25em 0}\n.thumb,.th{line-height:0;display:inline-block;border:4px solid #fff;box-shadow:0 0 0 1px #ddd}\n.imageblock.left{margin:.25em .625em 1.25em 0}\n.imageblock.right{margin:.25em 0 1.25em .625em}\n.imageblock>.title{margin-bottom:0}\n.imageblock.thumb,.imageblock.th{border-width:6px}\n.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}\n.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}\n.image.left{margin-right:.625em}\n.image.right{margin-left:.625em}\na.image{text-decoration:none;display:inline-block}\na.image object{pointer-events:none}\nsup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}\nsup.footnote a,sup.footnoteref a{text-decoration:none}\nsup.footnote a:active,sup.footnoteref a:active,#footnotes .footnote a:first-of-type:active{text-decoration:underline}\n#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}\n#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}\n#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}\n#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}\n#footnotes .footnote:last-of-type{margin-bottom:0}\n#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}\ndiv.unbreakable{page-break-inside:avoid}\n.big{font-size:larger}\n.small{font-size:smaller}\n.underline{text-decoration:underline}\n.overline{text-decoration:overline}\n.line-through{text-decoration:line-through}\n.aqua{color:#00bfbf}\n.aqua-background{background:#00fafa}\n.black{color:#000}\n.black-background{background:#000}\n.blue{color:#0000bf}\n.blue-background{background:#0000fa}\n.fuchsia{color:#bf00bf}\n.fuchsia-background{background:#fa00fa}\n.gray{color:#606060}\n.gray-background{background:#7d7d7d}\n.green{color:#006000}\n.green-background{background:#007d00}\n.lime{color:#00bf00}\n.lime-background{background:#00fa00}\n.maroon{color:#600000}\n.maroon-background{background:#7d0000}\n.navy{color:#000060}\n.navy-background{background:#00007d}\n.olive{color:#606000}\n.olive-background{background:#7d7d00}\n.purple{color:#600060}\n.purple-background{background:#7d007d}\n.red{color:#bf0000}\n.red-background{background:#fa0000}\n.silver{color:#909090}\n.silver-background{background:#bcbcbc}\n.teal{color:#006060}\n.teal-background{background:#007d7d}\n.white{color:#bfbfbf}\n.white-background{background:#fafafa}\n.yellow{color:#bfbf00}\n.yellow-background{background:#fafa00}\nspan.icon>.fa{cursor:default}\na span.icon>.fa{cursor:inherit}\n.admonitionblock td.icon [class^=\"fa icon-\"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}\n.admonitionblock td.icon .icon-note::before{content:\"\\f05a\";color:#19407c}\n.admonitionblock td.icon .icon-tip::before{content:\"\\f0eb\";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}\n.admonitionblock td.icon .icon-warning::before{content:\"\\f071\";color:#bf6900}\n.admonitionblock td.icon .icon-caution::before{content:\"\\f06d\";color:#bf3400}\n.admonitionblock td.icon .icon-important::before{content:\"\\f06a\";color:#bf0000}\n.conum[data-value]{display:inline-block;color:#fff!important;background:rgba(0,0,0,.8);border-radius:50%;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:\"Open Sans\",\"DejaVu Sans\",sans-serif;font-style:normal;font-weight:bold}\n.conum[data-value] *{color:#fff!important}\n.conum[data-value]+b{display:none}\n.conum[data-value]::after{content:attr(data-value)}\npre .conum[data-value]{position:relative;top:-.125em}\nb.conum *{color:inherit!important}\n.conum:not([data-value]):empty{display:none}\ndt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}\nh1,h2,p,td.content,span.alt,summary{letter-spacing:-.01em}\np strong,td.content strong,div.footnote strong{letter-spacing:-.005em}\np,blockquote,dt,td.content,td.hdlist1,span.alt,summary{font-size:1.0625rem}\np{margin-bottom:1.25rem}\n.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}\n.exampleblock>.content{background:#fffef7;border-color:#e0e0dc;box-shadow:0 1px 4px #e0e0dc}\n.print-only{display:none!important}\n@page{margin:1.25cm .75cm}\n@media print{*{box-shadow:none!important;text-shadow:none!important}\nhtml{font-size:80%}\na{color:inherit!important;text-decoration:underline!important}\na.bare,a[href^=\"#\"],a[href^=\"mailto:\"]{text-decoration:none!important}\na[href^=\"http:\"]:not(.bare)::after,a[href^=\"https:\"]:not(.bare)::after{content:\"(\" attr(href) \")\";display:inline-block;font-size:.875em;padding-left:.25em}\nabbr[title]{border-bottom:1px dotted}\nabbr[title]::after{content:\" (\" attr(title) \")\"}\npre,blockquote,tr,img,object,svg{page-break-inside:avoid}\nthead{display:table-header-group}\nsvg{max-width:100%}\np,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}\nh2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}\n#header,#content,#footnotes,#footer{max-width:none}\n#toc,.sidebarblock,.exampleblock>.content{background:none!important}\n#toc{border-bottom:1px solid #dddddf!important;padding-bottom:0!important}\nbody.book #header{text-align:center}\nbody.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}\nbody.book #header .details{border:0!important;display:block;padding:0!important}\nbody.book #header .details span:first-child{margin-left:0!important}\nbody.book #header .details br{display:block}\nbody.book #header .details br+span::before{content:none!important}\nbody.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}\nbody.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}\n.listingblock code[data-lang]::before{display:block}\n#footer{padding:0 .9375em}\n.hide-on-print{display:none!important}\n.print-only{display:block!important}\n.hide-for-print{display:none!important}\n.show-for-print{display:inherit!important}}\n@media amzn-kf8,print{#header>h1:first-child{margin-top:1.25rem}\n.sect1{padding:0!important}\n.sect1+.sect1{border:0}\n#footer{background:none}\n#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}\n@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}\n</style>\n</head>\n<body id=\"urls\" class=\"article toc2 toc-left\">\n<div id=\"header\">\n<h1>Cockpit URLs</h1>\n<div id=\"toc\" class=\"toc2\">\n<div id=\"toctitle\">Table of Contents</div>\n<ul class=\"sectlevel1\">\n<li><a href=\"#urls-components\">Component URLs</a></li>\n<li><a href=\"#urls-visible\">Visible URLs</a></li>\n</ul>\n</div>\n</div>\n<div id=\"content\">\n<div id=\"preamble\">\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit URLs follow a specific structure, related to the components they\nare loading. Various components are loaded in <code>&lt;iframe&gt;</code> tags. The\nURLs for these components are described first. Further down below you\ncan find information about the top level bookmarkable Cockpit address\nURLs.</p>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"urls-components\">Component URLs</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>Cockpit components are HTML documents. They are organized into\n<a href=\"#packages\">packages</a>. Each package contains information about which\nHTML components are available in that package. Components should always\nuse relative URLs to access resources, such as images, scripts or CSS\nfiles, even if they refer to a resource in another package.</p>\n</div>\n<div class=\"paragraph\">\n<p>The following are valid component URLs, each bit will be discussed\nbelow:</p>\n</div>\n<div class=\"literalblock\">\n<div class=\"content\">\n<pre>/cockpit/@localhost/package/component.html#/hash\n/cockpit/$checksum/package/component.html#/hash\n/cockpit/@server.example.com/package/component.html#/hash\n/cockpit+embedder/@localhost/package/component.html#/hash</pre>\n</div>\n</div>\n<div class=\"paragraph\">\n<p>All resource URLs are under the <code>/cockpit</code> namespace. In cases where a\nCockpit component is being <a href=\"#embedding\">embedded</a> the <code>/cockpit</code>\nmay be followed by a plus sign and another <code>embedder</code> specific\nidentifier.</p>\n</div>\n<div class=\"paragraph\">\n<p>What follows is either a <code>@host</code> or <code>$checksum</code> which tells cockpit\nwhere to <a href=\"#packages\">find the package</a>. Checksums are used when more\nthan one host has identical packages and the resources can be cached.</p>\n</div>\n<div class=\"paragraph\">\n<p>The <code>package</code> name is next, followed by the <code>component</code> HTML path\ninside that package. And lastly a hash allows for navigation within a\nsingle component. The hash should follow a URL path and/or query string\nform.</p>\n</div>\n<div class=\"admonitionblock warning\">\n<table>\n<tr>\n<td class=\"icon\">\n<div class=\"title\">Warning</div>\n</td>\n<td class=\"content\">\n<div class=\"paragraph\">\n<p>Never assume that the <code>@host</code> or <code>$checksum</code> portion is predictable.\nOnly refer to resources in packages on the same host.</p>\n</div>\n</td>\n</tr>\n</table>\n</div>\n</div>\n</div>\n<div class=\"sect1\">\n<h2 id=\"urls-visible\">Visible URLs</h2>\n<div class=\"sectionbody\">\n<div class=\"paragraph\">\n<p>The above Component URLs are usually not visible to the user. Instead\nthe Cockpit Web Service wraps the components in a shell which allows\nnavigation, and provides bookmarkable clean URLs to the component. These\nURLs do not affect <a href=\"#embedding\">embedders</a> or\n<a href=\"#packages\">components</a> directly.</p>\n</div>\n<div class=\"paragraph\">\n<p>If no path is present then the Cockpit will redirect to the default page\nfor the server.</p>\n</div>\n<div class=\"paragraph\">\n<p>If the first segment of the path begins with an <code>@</code> sign, then the\ncomponent is being shown from a non-local host.</p>\n</div>\n<div class=\"paragraph\">\n<p>The next segment of the path, (or first if the component is being shown\non the local host) is the <a href=\"#packages\">package name</a>. The remainder of\nthe path is a component file in the package. If no further path segments\nare present, a default <code>index.html</code> component in the package is\nloaded. An extension of <code>.html</code> is automatically appended.</p>\n</div>\n<div class=\"paragraph\">\n<p>The hash portion of the path is automatically transferred to the\ncomponent as the hash of its <a href=\"#urls-components\">resource URL</a>.</p>\n</div>\n</div>\n</div>\n</div>\n<div id=\"footer\">\n<div id=\"footer-text\">\nLast updated 2026-05-20 12:27:57 UTC\n</div>\n</div>\n</body>\n</html>"
  },
  {
    "path": "ideals.md",
    "content": "---\ntitle: Cockpit's Ideals\n---\n\n[Cockpit]({{ site.baseurl }}/) is an interactive server admin interface. For those helping contribute to Cockpit, these ideals help us remember what we’re trying to accomplish. For others, this page should answer the question: “Why Cockpit?”\n\nThese ideals are not a commentary about what is “right” and “wrong” in software in general. Other projects may have different guiding principles. These are ours.\n\nThese ideals also help define the scope of Cockpit. That scope is limited, and not meant to subsume all other configuration and/or management software.\n\n### Cockpit is discoverable\n\nIt should be possible to discover how to perform tasks through Cockpit without reading a help file.\n\n### Cockpit directly interacts with and reacts to the system\n\nCockpit does not store its own opinion of the state of the server anywhere. The UI always reflects the actual current state of the server. Cockpit reacts to system changes immediately, using the same system APIs that are used by command line tools.\n\nAlso, Cockpit does not make any security decisions. Once the user is authenticated they have exactly the same permissions as the user would have if they logged into the server via the console or SSH. Existing mechanisms are used to escalate privileges (e.g.: polkit or sudo).\n\nThus, Cockpit does not take over the server. It is always possible to move away from Cockpit to the command line and come back at will.\n\n### Cockpit requires no configuration or infrastructure\n\nThe goal is that Cockpit comes with the default server install of a Linux server, except for really minimal installs. Cockpit comes “out of the box” ready for the admin to interact with the system immediately.\n\nIn cases where there is other infrastructure available we should allow the admin to configure the server to take advantage of it (e.g.: use single-sign-on against a domain controller). But such infrastructure is not a prerequisite.\n\n### Cockpit is not configuration management\n\nCockpit itself does not have a predefined template or state for the server that it then imposes on the server. It is imperative configuration rather than declarative configuration.\n\nCockpit may expose UI elements that interact with configuration management style software installed on the server. Such software may have a declarative configuration, as one would expect. But Cockpit itself has no concept of configuration management, or a desired state for the server.\n\n### Cockpit is only the project name\n\nPeople using Cockpit should feel they are interacting with the underlying Server OS. Cockpit can look different on different operating systems, because it’s the UI for the OS, and not an external tool.\n\nThus the UI should never actually show the 'Cockpit' name, but call the server by its name or operating system.\n\n### Cockpit has zero footprint\n\nThe tools to configure the server itself should not waste resources needed for that. As such, Cockpit has (as near as makes no difference) zero memory and process footprint on the server when not in use. Disk space usage of Cockpit is minimal and the required set of dependencies is scrutinized.\n\n### Cockpit is designed first\n\nWhen developing Cockpit we want to design first, with real-world use cases driving which features we work on.\n\n### Cockpit helps the server evolve coherently\n\nWhen developing Cockpit we run into situations where we notice the underlying server behavior is not coherent. We try to resolve that by contributing in the usual open source fashion, before implementing a hack or work around.\n\n### Cockpit is tested\n\nEvery feature and change in Cockpit is covered by an automatic test. A proposed change only lands in the code base after it passes all tests. Tests run on all [Operating System](running.html) releases on which Cockpit is supported.\n\nIn addition, the design of new features and changes in existing features are tested in usability studies.\n\n### Cockpit is backwards-compatible\n\nCockpit can connect to other instances of itself. These might be much older, because we support many operating systems with different release cadences. To achieve that, Cockpit's Javascript API may not change in an incompatible way. External Cockpit components that use this API should continue to function despite newer versions of Cockpit being released.\n\nThere is no foreseen major incompatible version change for this Javascript API in Cockpit's future.\n"
  },
  {
    "path": "index.md",
    "content": "---\ntitle: Cockpit Project\nlayout: essential\nclass: front-page\n---\n{% capture newline %}\n{% endcapture %}\n\n{% capture screenshots %}\nlogin-opt.webp: Cockpit's log in prompt (on Fedora 42)\ndebian-in-windows-edge.webp: Cockpit works where you are (Pictured: Connecting to Debian 10 server from Microsoft Edge on Windows 10)\njournal.webp: View, filter, and search system logs\naccounts.webp: Edit accounts\nfirewall-remote.webp: Edit the firewall with ease (Pictured: Cockpit Web Console on Ubuntu 24.04, connected from Bazzite 42)\nnetwork-overview.webp: Manage your network\noverview.webp: Have a high-level overview of a server\nsoftware-updates-cve-auto.webp: Examine and apply software updates (with changelogs and links to CVEs)\nstorage-overview.webp: Look at and manage your storage\nsystem-services-ssh.webp: See system services\nsystem-service-details.webp: Manage an individual system service\nvm-create.webp: Create and manage virtual machines\n{% endcapture %}\n{% assign screenshots = screenshots | split: newline %}\n\n{% capture screenshots_html %}\n<div class=\"screenshots\">{%\nfor screenshot in screenshots\n  %}{%\n  assign filename = screenshot | split: \":\" | first | strip\n    | prepend: \"/images/screenshot/\"\n    | prepend: site.baseurl\n  %}{%\n  assign text = screenshot | replace_first: \":\", \"©\"\n    | split: \"©\" | last | strip\n  %}{%\n  unless text == \"\"\n    %}<a class=\"screenshot zoom\"\n    href=\"{{ filename }}\"><img src=\"{{ filename }}\" \n    title=\"{{ text }}\" alt=\"{{ text }}\"></a>{% \n  endunless\n  %}{%\nendfor\n%}</div>\n{% endcapture %}\n\n\n{% comment %}\n##### Content #####\nFirst we set up & capture the content, then we render it in the scaffolding below.\n{% endcomment %}\n\n{% capture intro-lede %}\nThe easy-to-use, integrated, glanceable, and open web-based interface for your servers\n{% endcapture %}\n\n{% capture intro-text %}\n## Introducing Cockpit\n\nCockpit is a web-based graphical interface for servers, intended for everyone, especially those who are:\n\n{:.audience-list}\n- **new to Linux** (including Windows admins)\n- **familiar with Linux** and want an easy, graphical way to administer servers\n- **expert admins** who mainly use other tools but want an overview on individual systems\n\nThanks to Cockpit intentionally using system APIs and commands, a whole team of admins can manage a system in the way they prefer, including the command line and utilities right alongside Cockpit.\n\n### Take a look\n\nA picture is worth a thousand words. Click a thumbnail to see screenshots of Cockpit in action.\n\n{{ screenshots_html }}\n\n\n### Simple to use\n\nCockpit makes Linux discoverable. You don't *have to* remember commands at a command-line.\n\nSee your server in a web browser and perform system tasks with a mouse. It's easy to start containers, administer storage, configure networks, and inspect logs.  Basically, you can think of Cockpit like a graphical \"desktop interface\", but for individual servers.\n\n### Compatible with your existing workflows\n\nHave a favorite app or command line tool that you use on your servers? \nKeep using the command line, Ansible, and your other favorite tools and add Cockpit to the mix with no issues.\n\nCockpit uses the same system tooling you would use from the command line. You can switch back and forth between Cockpit and whatever else you like. Cockpit even has a built-in terminal, which is useful when you connect from a non-Linux device.\n\n### Integrated\n\nCockpit uses APIs that already exist on the system. It doesn't reinvent subsystems or add a layer of its own tooling.\n\nBy default, Cockpit uses [your system's normal user logins and privileges]({{ site.baseurl }}/guide/latest/privileges). Network-wide logins are also supported through [single-sign-on]({{ site.baseurl }}/guide/latest/sso) and other [authentication]({{ site.baseurl }}/guide/latest/authentication) techniques.\n\nCockpit itself doesn't eat resources or even run in the background when you're not using it. It runs on demand, thanks to systemd socket activation.\n\n### Extendable\n\nCockpit also supports [a large list of optional and third-party applications](applications.html).\n\n## Using Cockpit\n\nHere's a subset of tasks you can perform on each host running Cockpit:\n\n{:.using-cockpit}\n- Inspect and change network settings\n- Configure a firewall\n- Manage storage (including RAID and LUKS partitions)\n- Create and manage virtual machines\n- Download and run containers\n- Browse and search system logs\n- Inspect a system's hardware\n- Upgrade software\n- Keep tabs on performance\n- Manage user accounts\n- Inspect and interact with systemd-based services\n- Use a terminal on a remote server in your local web browser\n- Switch between [multiple Cockpit servers]({{ site.baseurl }}/guide/latest/feature-machines.html)\n- Extend Cockpit's functionality by installing [a growing list of apps and add-ons](applications.html)\n- [Write your own custom modules]({{ site.baseurl }}/blog/cockpit-starter-kit.html) to make Cockpit do anything you want\n\n*[RAID]: Redundant Array of Inexpensive Disks\n*[LUKS]: Linux Unified Key Setup (encryption)\n\nAlso troubleshoot and fix pesky problems with ease:\n\n{:.using-cockpit}\n- Diagnose network issues\n- Spot and react to misbehaving virtual machines\n- Examine SELinux logs and fix common violations in a click\n- Inspect detailed metrics that correlate CPU load, memory usage, network activity, and storage performance with the system's journal\n\nMore features appear in Cockpit every release.\n\n### Designed & tested\n\nCockpit's design keeps your goals in mind.  We test Cockpit with usability studies to make it work the way you'd expect and adjust accordingly. As a result, Cockpit gets easier to use all the time.\n\nAll code changes have tests which must pass before merging, to ensure stability.\n\n### Free & free\n\nCockpit is free to use and [available under the GNU LGPL](https://github.com/cockpit-project/cockpit/blob/master/COPYING).\n\n### Cockpit works (nearly) everywhere\n\nYou can install Cockpit on the major distributions, including:\n\n{:.distro-logos}\n{%\n  for distro in site.data.distros\n%}- [![{{ distro.name }}](/images/site/os-{{ distro.first}}.svg)]({{ site.baseurl }}/running.html#{{ distro.first }})\n{% endfor %}\n\nOnce Cockpit is up and running, you can access systems from all major web browsers on any operating system (including Windows, MacOS, and Android).\n\n## Release schedule\n\nCockpit has a time-based release cadence, with new versions appearing every two weeks.\n\n## Get started\n\n{:style=\"text-decoration-skip-ink:none\"}\nAfter [installing and enabling Cockpit]({{ site.baseurl }}/running.html), visit port 9090 on your server (for example: <https://localhost:9090/> in a browser on the same machine as Cockpit).\n{% endcapture %}\n\n{% capture footer_links %}\nAbout Cockpit\n: [Frequently Asked Questions (FAQ)](faq.html)\n: [Project ideals and goals](ideals.html)\n: [Blog](blog) &amp; [Blog feeds](blog/feeds/)\n: [Release notes](blog/category/release.html)\n: [Search this site](search.html)\n{:.col.footer-links-1}\n\nRunning Cockpit\n: [Installation](running.html)\n: [Documentation](documentation.html)\n: [Deployment guide](guide/latest/guide.html)\n: [Feature internals](guide/latest/features.html)\n: [File a bug in the issue tracker](https://github.com/cockpit-project/cockpit/issues/new?assignees=&labels=bug&template=bug_report.yml)\n{:.col.footer-links-2}\n\nContributing\n: [Contribution overview](https://github.com/cockpit-project/cockpit/wiki/Contributing)\n: [Get the source](https://github.com/cockpit-project/cockpit)\n: [Join the mailing list](https://lists.fedorahosted.org/archives/list/cockpit-devel@lists.fedorahosted.org/)\n: [Matrix #cockpit:fedoraproject.org](https://matrix.to/#/#cockpit:fedoraproject.org)\n: [Developer tutorials](blog/category/tutorial.html)\n: [Developer API reference](guide/latest/development.html)\n{:.col.footer-links-3}\n\n*[Feeds]: Atom (similar to RSS), for use in feed readers\n{% endcapture %}\n\n\n{% capture badge %}\n{% assign release = site.posts | where: \"category\", \"release\" | first %}\n{% assign version = release.title | split: \"and\" | first | split: \" \" | last %}\n{% assign summary = release.summary | replace: '\"', \"'\" %}\n<a href=\"{{ site.baseurl }}{{ release.url }}\" title=\"{{ summary }}\">\n  <span class=\"badge-new\">\n    Released\n    <span class=\"badge-date\">{{ release.date | date: \"%-d %b %Y\" }}</span>:\n  </span>\n  <span class=\"badge-version\">Version {{ version }}</span>\n</a>\n{% endcapture %}\n\n{% capture screenshots %}\n[![Storage screenshot]({{ site.baseurl }}/images/site/screenshot-storage.webp)]({{ site.baseurl}}/images/site/screenshot-storage.webp)\n{:.screenshot.zoom}\n\n[![Network screenshot]({{ site.baseurl }}/images/site/screenshot-network.webp)]({{ site.baseurl }}/images/site/screenshot-network.webp)\n{:.screenshot.zoom}\n\n[![Dashboard screenshot]({{ site.baseurl }}/images/site/screenshot-dashboard.webp)]({{ site.baseurl }}/images/site/screenshot-dashboard.webp)\n{:.screenshot.zoom}\n{% endcapture %}\n\n{% comment %}\n##### Scaffolding #####\n{% endcomment %}\n\n{% capture output %}\n\n<div class=\"frontpage-background\">\n  {% include page_header.html %}\n  <section class=\"intro intro-background\">\n    <div class=\"intro-lede\">\n      {{ intro-lede | markdownify }}\n    </div>\n    <div class=\"planes\"></div>\n    <div class=\"badge\">\n      {{ badge }}\n    </div>\n  </section>\n</div>\n\n\n<div id=\"page-wrap\" class=\"page-content\" role=\"main\">\n  <section class=\"intro-text wrapper\">{{ intro-text | markdownify }}</section>\n</div>\n\n<footer class=\"footerlinks\">\n  {{ footer_links | markdownify }}\n</footer>\n{% include page_footer.html %}\n\n<a rel=\"me\" href=\"https://fosstodon.org/@Cockpit\" class=\"hidden\">Mastodon</a>\n\n<script src=\"{{ site.baseurl }}/assets/lib/screenshot-gallery.js\"></script>\n{% endcapture %}{{ output }}\n"
  },
  {
    "path": "manifest.json",
    "content": "---\nlayout:\n---\n{\n  \"name\": {{ site.title | jsonify }},\n  \"short_name\": {{ site.title | jsonify }},\n  \"lang\": {{ site.lang | default: 'en' | jsonify }},\n  \"start_url\": \".\",\n  \"scope\": {{ site.baseurl | default: '/' | jsonify }},\n  \"background_color\": \"#fff\",\n  {% if site.color %}\"theme_color\": {{ site.color | jsonify }},{% endif %}\n  \"description\": {{ site.description | strip | jsonify }},\n\n  {% assign _favicon_small = site.static_files | where_exp: \"item\", \"item.path contains '/images/favicon-small.'\" %}\n  {% assign _favicon = site.static_files | where_exp: \"item\", \"item.path contains '/images/favicon.'\" %}\n\n  {% if _favicon[0] or _favicon_small[0] %}\n  \"icons\": [\n\n  {% if _favicon_small[0] %}\n  {\n    \"src\": {{ _favicon_small[0].path | prepend: site.baseurl | jsonify }},\n    \"sizes\": \"16x16\",\n    \"type\": \"image/{{ _favicon_small[0].extname | replace: '.', '' }}\"\n  }{% if _favicon[0] %},{% endif %}\n  {% endif %}\n\n  {% if _favicon[0] %}\n  {\n    \"src\": {{ _favicon[0].path | prepend: site.baseurl | jsonify }},\n    \"sizes\": \"512x512\",\n    \"type\": \"image/{{ _favicon[0].extname | replace: '.', '' }}\"\n  }\n  {% endif %}\n\n  ],{% endif %}\n\n  \"display\": \"{{ site.display | default: 'browser' }}\"\n}\n"
  },
  {
    "path": "privacy.md",
    "content": "---\ntitle: Privacy Policy\n---\n\n## Preamble: Hosting Details\n\nThe Cockpit Project website is a static site that does not track, collect, store any information, or set any cookies. There is no account on the website itself.\n\nThere are some third party places where the Cockpit Project stores data:\n\n- [GitHub Pages](https://help.github.com/articles/what-is-github-pages/) is the website host. Please [refer to GitHub's privacy practices document for details](https://docs.github.com/en/site-policy/privacy-policies/github-general-privacy-statement).\n- [YouTube](https://youtube.com/) videos are embedded in some pages on the website. YouTube embeds are rewritten as to not use cookies. [Refer to YouTube's privacy policy for details](https://support.google.com/youtube/answer/7671399?hl=en).\n- The Cockpit Project has [a mailing list for development](https://lists.fedorahosted.org/archives/list/cockpit-devel@lists.fedorahosted.org/), and a [Matrix channel](https://matrix.to/#/#cockpit:fedoraproject.org) hosted by [the Fedora Project](https://fedoraproject.org/). [Refer to Fedora's privacy policy for more details](https://fedoraproject.org/wiki/Legal:PrivacyPolicy).\n- The Cockpit software is stored in git, on [GitHub](https://github.com/). The git software does collect names and email addresses in repositories. GitHub has account information. [Refer to GitHub's privacy practices document for details](https://help.github.com/articles/global-privacy-practices/).\n\n## Privacy Statement for the Cockpit Project\n\n### Scope of This Notice\n\nThis Privacy Statement is intended to describe the Cockpit Project's privacy practices and provide information about the choices you have regarding the ways in which information collected by the Cockpit Project is used and disclosed.\n\n### Our Commitment to Privacy\n\nAt the Cockpit Project, your privacy is important to us. To better protect your privacy, we have provided this Statement explaining our information practices and the choices you can make about the way your personal information is collected, used and disclosed. To make this Statement easy to find, we have made it available on our homepage and at every location where personally-identifiable information may be requested.\n\n### The Information We Collect\n\nThis Privacy Statement applies to all information collected by or submitted to the Cockpit Project, including personal data. \"Personal data\" is data that can be used to identify an individual.\n\nThe Cockpit Project collects personal data when:\n\n* you participate in surveys and evaluations;\n* you participate in promotions, contests or giveaways;\n* you submit questions or comments to us.\n\nThe Cockpit Project may also collect personal data from individuals (with their consent) at conventions, trade shows and expositions.\n\nThe types of personal data collected may include (but are not limited to):\n\n* your first and last name;\n* your title and your company's name;\n* your home, billing, or other physical address (including street name, name of a city or town, state/province);\n* your country code;\n* your e-mail address;\n* your Matrix identity,\n* your telephone number;\n* any other identifier that permits the Cockpit Project to make physical or online contact with you;\n* any information that the Cockpit Project collects online from you and maintains in association with your account, such as:\n* your GPG key ID,\n* your SSH public key,\n* your language preference,\n* your timezone,\n* your geographic coordinates (longitude/latitude),\n* your affiliation(s).\n\n### Using (Processing) Your Personal Data\n\nThe Cockpit Project uses the personal data you provide to:\n\n* attribute data and content you produce directly and indirectly in our public-facing services;\n* answer your questions;\n* send you information;\n* for research activities, including the production of statistical reports (such aggregated information is not used to contact the subjects of the report);\n* send you surveys.\n\n### Sharing Your Personal Data\n\nUnless you consent, the Cockpit Project will never process or share the personal data you provide to us except as described below.\n\nThe Cockpit Project may disclose your personal data to third parties under any of the following circumstances:\n\n* As required to provide service, and for e-mail housing (as a consequence of uses already described in this Privacy Statement). It is in the Cockpit Project’s legitimate interest to provide all users an accurate record of data and content provided by The Cockpit Project’s services, and to maintain the integrity of that data and content for historical, scientific, and research purposes. This data and content may include but is not limited to email, code changes, comments, and artifacts.\n* As required by law (such as responding to a valid subpoena, warrant, audit, or agency action, or to prevent fraud).\n* For research activities, including the production of statistical reports (such aggregated information is used to describe our services and is not used to contact the subjects of the report).\n\n### Receiving E-Mail\n\nThe Cockpit Project may send you e-mail to inform you of important upcoming events or to respond to your questions. For your protection, The Cockpit Project may contact you in the event that we find an issue that requires your immediate attention. The Cockpit Project processes your personal data in these cases to fulfill and comply with its contractual obligations to you, to provide the services you have requested, and to ensure the security of your account.\n\n### Our Commitment to Data Security\n\nOur website uses Secure Socket Layer (SSL) technology, which encrypts data to and from our website.\n\n### Public Forums Reminder\n\nThe Cockpit Project often makes chat rooms, mailing lists, and discussions on GitHub available to its users. Please remember that any information that is disclosed in these areas becomes public information. Exercise caution when deciding to disclose your personal data. Although we value individual ideas and encourage free expression, the Cockpit Project reserves the right to take necessary action to preserve the integrity of these areas, such as removing any posting that is vulgar or inappropriate. It is in The Cockpit Project’s legitimate interests to provide all users an accurate record of data and content provided in the public forums it maintains and uses; to maintain the integrity of that data and content for historical, scientific, and research purposes; and to provide an environment for the free exchange of ideas relevant and constructive to the development and propagation of open source software.\n\n### Our Commitment to Children's Online Privacy\n\nOut of special concern for children's privacy, the Cockpit Project does not knowingly accept online personal information from children under the age of 13. The Cockpit Project does not knowingly allow children under the age of 13 to become registered members of our sites. The Cockpit Project does not knowingly collect or solicit personal information about children under 13.\n\nIn the event that the Cockpit Project ever decides to expand its intended site audience to include children under the age of 13, those specific web pages will, in accordance with the requirements of the Children's Online Privacy Protection Act (COPPA), be clearly identified and provide an explicit privacy notice addressed to children under 13. In addition, The Cockpit Project will provide an appropriate mechanism to obtain parental approval, allow parents to subsequently make changes to or request removal of their children's personal information, and provide access to any other information as required by law.\n\n### About Links to Other Sites\n\nThis site contains links to other sites. The Cockpit Project does not control the information collection of sites that can be reached through links from [cockpit-project.org](/). If you have questions about the data collection procedures of linked sites, please contact these sites directly.\n\n### Your Rights and Choices in the EEA\n\nWhere the EU General Data Protection Regulation 2016/679 (“GDPR”) applies to the processing of your personal data, especially when you access the website from a country in the European Economic Area (“EEA”), you have the following rights, subject to some limitations, against the Cockpit Project:\n\n* The right to access your personal data;\n* The right to rectify the personal data we hold about you;\n* The right to erase your personal data;\n* The right to restrict our use of your personal data;\n* The right to object to our use of your personal data;\n* The right to receive your personal data in a usable electronic format and transmit it to a third party (also known as the right of data portability); and\n* The right to lodge a complaint with your local data protection authority.\n\nIf you would like to exercise any of these rights, you may do so by [contacting the Cockpit Project on Matrix](https://matrix.to/#/#cockpit:fedoraproject.org). Please understand, however, the rights enumerated above are not absolute in all cases.\n\nWhere the GDPR applies, you also have the right to withdraw any consent you have given to uses of your personal data. If you wish to withdraw consent that you have previously provided to the Cockpit Project, [please contact us via Matrix](https://matrix.to/#/#cockpit:fedoraproject.org) (`#cockpit:fedoraproject.org`). However, the withdrawal of consent will not affect the lawfulness of processing based on consent before its withdrawal.\n\n### How to Access, Modify or Update Your Information\n\nIf you wish to remove your personal data from the Cockpit Project website, you may contact us on Matrix and request that we remove this information from the Cockpit Project website. Other locations where you may have used your personal data as an identifier (e.g. GitHub comments, list postings in the archives, git history, chat rooms, and changelogs) will not be altered.\n\n### How to Contact Us\n\nIf you have any questions about any of these practices or the Cockpit Project's use of your personal information, please feel free to [contact us on Matrix](https://matrix.to/#/#cockpit:fedoraproject.org) (`#cockpit:fedoraproject.org`).\n\nThe Cockpit Project will work with you to resolve any concerns you may have about this Statement.\n\n### Changes to this Privacy Statement\n\nThe Cockpit Project reserves the right to change this Privacy Statement from time to time. If we do make changes, the revised Privacy Statement will be posted on the main project’s website.\n\nThis Privacy Statement was last amended on May 24, 2018.\n"
  },
  {
    "path": "running/safari.md",
    "content": "---\ntitle: Use Cockpit with Safari on an iPhone or iPad\n---\n\nSafari's default WebSocket framework on [iOS, iPadOS,](#ios-and-ipados) and [ARM-based Macs](#macos-on-arm-m1) does not support the WebSocket Secure sessions which Cockpit needs to function when using a self-signed or otherwise invalid certificate, even when they are manually marked as trusted. [Installing a valid certificate]({{ site.baseurl }}/guide/latest/https.html) should resolve this issue.\n\nAs an alternative workaround, you can enable Apple's future/experimental WebSocket framework which does work as expected.\n\n## iOS and iPadOS\n\n1. Open the Settings app\n   \n   ![iPhone settings]({{ site.baseurl }}/images/safari/1.png)\n\n2. Scroll down and tap on \"**Safari**\"\n   \n   ![iPhone settings, scrolled mid-way down]({{ site.baseurl }}/images/safari/2.png)\n   ![Safari settings highlighted]({{ site.baseurl }}/images/safari/2-2.png)\n\n3. Scroll down to the bottom and tap on \"**Advanced**\"\n   \n   ![Safari settings]({{ site.baseurl }}/images/safari/3.png)\n   ![Advanced highlighted]({{ site.baseurl }}/images/safari/3-2.png)\n\n4. Tap on \"**Experimental Features**\" at the bottom\n   \n   ![\"Experimental Features\" highlighted]({{ site.baseurl }}/images/safari/4.png)\n\n5. Scroll down until you see \"**NSURLSession WebSocket**\"\n   \n   ![Experimental Features]({{ site.baseurl }}/images/safari/5.png)\n   ![\"NSURLSession Websocket\" highlighted]({{ site.baseurl }}/images/safari/5-2.png)\n\n6. Enable \"**NSURLSession WebSocket**\"\n\n   ![\"NSURLSession Websocket\" off by default]({{ site.baseurl }}/images/safari/6.png)\n   ![\"NSURLSession Websocket\" turned on manually]({{ site.baseurl }}/images/safari/6-2.png)\n\n7. You're done! Navigate to Cockpit with Safari and sign in normally.\n\n   ![Safari icon]({{ site.baseurl }}/images/site/browser-safari.svg){:.safari-icon}\n\n\n## macOS on ARM (M1)\n\n1. Open Safari's settings, select \"**Advanced**\", and enable \"**Show Develop menu in menu bar**\"\n\n   ![Safari's settings]({{ site.baseurl }}/images/safari/macos-safari-advanced.png){:.full-width}\n\n2. Go to Safari's \"**Develop**\" menu, select \"**Experimental Features**\", and enable \"**NSURLSession WebSocket**\"\n\n   ![Safari's settings]({{ site.baseurl }}/images/safari/macos-safari-experimental.png){:.full-width}\n\n3. You're done! Navigate to Cockpit with Safari and sign in normally.\n\n   ![Safari icon]({{ site.baseurl }}/images/site/browser-safari.svg){:.safari-icon}\n"
  },
  {
    "path": "running.md",
    "content": "---\ntitle: Running Cockpit\nclass: running-cockpit body-cockpit\n---\n\n{% capture newline %}\n{% endcapture %}\n\nIf you already have Cockpit on your server, point your web browser to:\n**https://**_ip-address-of-machine_**:9090**\n\nUse your system user account and password to log in. See [the guide](guide/latest/guide.html) for more info.\n\nAfter installing Cockpit itself, consider [installing additional applications in Cockpit](applications.html).\n\n## Recommended client browsers\n\n{% capture icon %}{:.browser-0}![](/images/site/browser-0.svg){% endcapture %}\n{% capture label %}<span class=\"browser-name\">0</span>{% endcapture %}\n\nCockpit is developed with and has automated tests for:\n\n{:.browser-support}\n- {{icon | replace: \"0\", \"firefox\"}}{{label | replace: \"0\", \"Mozilla Firefox\"}}\n- {{icon | replace: \"0\", \"chrome\"}}{{label | replace: \"0\", \"Google Chrome\"}}\n\nCockpit is also periodically checked with:\n\n{:.browser-support}\n- {{icon | replace: \"0\", \"edge\"}}{{label | replace: \"0\", \"Microsoft Edge\"}}\n- {{icon | replace: \"0\", \"safari\"}}{{label | replace: \"0\", \"Apple Safari\"}}\n  _[iPhones, iPads, and macOS on ARM/M1 may require a workaround]({{ site.baseurl }}/running/safari.html)_{:.note-safari}\n- {{icon | replace: \"0\", \"epiphany\"}}{{label | replace: \"0\", \"GNOME Web (Epiphany)\"}}\n\n<div id=\"browser-support\">\n  <div class=\"is-supported\">\n    <img src=\"/images/site/icon-ok.svg\">\n    Your current browser should work with Cockpit.\n  </div>\n\n  <div class=\"is-not-supported\">\n    <img src=\"/images/site/icon-warning.svg\">\n    Sorry! Your current browser appears to lack necessary features.\n  </div>\n</div>\n\n### Minimum client browser versions\n\nThe following browsers (and up) _may_ also work with Cockpit:\n\n{% comment %}\n## Data for the browser table comes from `_data/browsers.yml`\n## Browser versions come from `_data/browser_support.yml` (generated)\n## Browser features are defined in `_scripts/update-browser-data.rb`\n{% endcomment %}\n\n{:.browser-support}\n{% for browser in site.data.browsers %}{%\n  assign slug = browser.name | downcase\n%}\n- {{\n  browser.vendor\n  }} {{\n  browser.name\n  }} {%\n  assign ver_caniuse = site.data.browser_support[\"browsers\"][slug] | plus: 0\n  %}{%\n  assign ver_caniuse_float = ver_caniuse | plus: 0\n  %}{%\n    if browser.version > ver_caniuse_float\n  %}{{\n    browser.version\n  }}{% else %}{{\n    ver_caniuse\n  }}{%\n    endif\n  %}{% endfor %}\n\nHowever, we __strongly__ encourage you to use the latest version of your browser for security reasons.\n\n## Installation & Setup\n\n{% comment %}\n## Data for the distros table comes from `_data/distros.yml` ##\n{% endcomment %}\n{% assign check = '<span aria-label=\"check\">✓</span>' %}\n\n| |Tested|Available||\n|-|-|-|-|-|-|{%\n  for distro in site.data.distros\n%}\n|[![{{ distro.name }}](/images/site/os-{{ distro.first}}.svg)](#{{ distro.first }})|{%\n  if distro.tested %}{{ check | replace: \"#\", \"tested\" }}{% endif\n  %}|{%\n  if distro.included %}{{ check | replace: \"#\", \"included\" }}{% endif\n  %}|[View instructions](#{{ distro.first }})|{% endfor %}\n{:.support-table}\n\n{:.note}\n\"Tested\" in this table means actively tested by the Cockpit team using automated integration testing with a specific virtual machine image. Distributions listed on this page likely do their own downstream testing in addition.\n\n### Fedora\n\nCockpit comes **installed by default in Fedora Server**.\n\nTo install Cockpit on other variants of Fedora use the following commands. For the latest versions [use COPR](https://copr.fedoraproject.org/coprs/g/cockpit/cockpit-preview/).\n\n1. Install cockpit:\n```\nsudo dnf install cockpit\n```\n2. Enable cockpit:\n```\nsudo systemctl enable --now cockpit.socket\n```\n3. Open the firewall if necessary:\n```\nsudo firewall-cmd --add-service=cockpit\nsudo firewall-cmd --add-service=cockpit --permanent\n```\n\n\n### Red Hat Enterprise Linux\n{:#rhel}\n\nCockpit is available in Red Hat Enterprise Linux 7 and later.\n\n1. On RHEL 7, enable the _Extras_ repository.\n```\nsudo subscription-manager repos --enable rhel-7-server-extras-rpms\n```\nRHEL 8 does not need any non-default repositories.\n\n2. Install cockpit:\n```\nsudo yum install cockpit\n```\n3. Enable cockpit:\n```\nsudo systemctl enable --now cockpit.socket\n```\n4. On RHEL 7, or if you use non-default zones on RHEL 8, open the firewall:\n```\nsudo firewall-cmd --add-service=cockpit\nsudo firewall-cmd --add-service=cockpit --permanent\n```\n\n### Fedora CoreOS\n{:#coreos}\n\nThe standard Fedora CoreOS image does not contain Cockpit packages.\n\n1. Install Cockpit packages as overlay RPMs:\n   ```\n   rpm-ostree install cockpit-system cockpit-ostree cockpit-podman\n   ```\n\n   Depending on your configuration, you may want to use other [`cockpit-*` extensions](https://cockpit-project.org/applications.html) as well, such as `cockpit-kdump` or `cockpit-networkmanager`.\n\n   If you have a custom-built OSTree, simply include the same packages in your build.\n\n2. Reboot\n\nSteps 1 and 2 are enough when the CoreOS machine is only connected to through another host running Cockpit.\n\nIf you want to also run a web server to log in directly on the CoreOS host:\n\n3. Enable password based SSH logins, unless you only use [SSO logins](https://cockpit-project.org/guide/latest/sso.html):\n   ```\n   echo 'PasswordAuthentication yes' | sudo tee /etc/ssh/sshd_config.d/02-enable-passwords.conf\n   sudo systemctl try-restart sshd\n   ```\n\n4. Run the Cockpit web service with a privileged container (as root):\n   ```\n   podman container runlabel --name cockpit-ws RUN quay.io/cockpit/ws\n   ```\n\n5. Make Cockpit start on boot:\n   ```\n   podman container runlabel INSTALL quay.io/cockpit/ws\n   systemctl enable cockpit.service\n   ```\n\nAfterward, use a web browser to log into port `9090` on your host IP address as usual.\n\n\n### CentOS\n\nCockpit is available in CentOS 7 and later:\n\n1. Install cockpit:\n```\nsudo yum install cockpit\n```\n2. Enable cockpit:\n```\nsudo systemctl enable --now cockpit.socket\n```\n3. Open the firewall if necessary:\n```\nsudo firewall-cmd --permanent --zone=public --add-service=cockpit\nsudo firewall-cmd --reload\n```\n\n\n### Debian\n\n{:.note}\nThese commands require a POSIX compatible shell like `bash`. For other shells like `fish`, temporarily run `bash -i`.\n\nCockpit is available in Debian since version 10 (Buster).\n\n1. To get the latest version, we recommend to enable the [backports repository](https://backports.debian.org):\n   ```\n   . /etc/os-release\n   echo \"deb http://deb.debian.org/debian ${VERSION_CODENAME}-backports main\" | \\\n       sudo tee /etc/apt/sources.list.d/backports.list\n   sudo apt update\n   ```\n2. Install or update the package:\n```\nsudo apt install -t ${VERSION_CODENAME}-backports cockpit\n```\n\n{:.note}\nWhen updating Cockpit-related packages and any dependencies, make sure to use `-t ...-backports` as above, so backports are included.\n\n### Ubuntu\n\n{:.note}\nThese commands require a POSIX compatible shell like `bash`. For other shells like `fish`, temporarily run `bash -i`.\n\nCockpit is available in Ubuntu, with [updated versions in official backports for LTS releases](https://help.ubuntu.com/community/UbuntuBackports).\n\nWe recommend installing or updating the latest version from backports. This repository is enabled by default, but if you customized apt sources you might need to [enable them manually](https://help.ubuntu.com/community/UbuntuBackports#Enabling_Backports).\n\n```\n. /etc/os-release\nsudo apt install -t ${VERSION_CODENAME}-backports cockpit\n```\n\n{:.note}\nWhen updating Cockpit-related packages and any dependencies, make sure to use `-t ...-backports` as above, so backports are included.\n\n\n### Arch Linux\n{:#archlinux}\n\n[Cockpit](https://archlinux.org/packages/extra/x86_64/cockpit/) is available in [Arch Linux](https://www.archlinux.org/packages/):\n```\nsudo pacman -S cockpit\nsudo systemctl enable --now cockpit.socket\n```\n\nIf the first command fails with \"database file for ... does not exist\", refresh/update your system with `sudo pacman -Syu` first.\n\n\n### openSUSE Tumbleweed and Leap\n{:#tumbleweed}\n\n[Cockpit](https://software.opensuse.org/package/cockpit) is available in both [openSUSE Tumbleweed](https://get.opensuse.org/tumbleweed) and [openSUSE Leap](https://get.opensuse.org/leap) starting by 15.6:\n\n\n1. Install cockpit:\n```\nzypper in cockpit\n```\n2. Enable cockpit:\n```\nsystemctl enable --now cockpit.socket\n```\n3. Open the firewall if necessary:\n```\nfirewall-cmd --permanent --zone=public --add-service=cockpit\nfirewall-cmd --reload\n```\n4. Optionally allow root access (disabled by default)\n```\n$EDITOR /etc/cockpit/disallowed-users\n```\n\n### SUSE Linux Enterprise Micro\n{:#slemicro}\n\nCockpit is included in SUSE Linux Enterprise (SLE) Micro 5.x.\n\n1. Install cockpit (already present in the pre-built images):\n```\ntransactional-update pkg install -t pattern microos_cockpit\n```\n2. Enable the socket:\n```\nsystemctl enable --now cockpit.socket\n```\n3. In case you have enabled the firewall, you also must open the port:\n```\nfirewall-cmd --permanent --zone=public --add-service=cockpit\nfirewall-cmd --reload\n```\n4. Access through the web interface:\n```\nhttps://IP_ADDRESS_OF_MACHINE:9090\n```\n"
  },
  {
    "path": "search.json",
    "content": "---\nlayout:\n---\n{% include search_json.html %}\n"
  },
  {
    "path": "search.md",
    "content": "---\nindex: false\nlayout: default\n---\n\n## Search\n\n{% include search.html %}\n"
  }
]