diff --git a/404.html b/404.html index c2984b318..57f9899fb 100644 --- a/404.html +++ b/404.html @@ -13,15 +13,15 @@ - - + +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- - + + \ No newline at end of file diff --git a/assets/js/1c14429f.4b597116.js b/assets/js/1c14429f.c57b3392.js similarity index 99% rename from assets/js/1c14429f.4b597116.js rename to assets/js/1c14429f.c57b3392.js index 7b174ab0f..6d8461ba6 100644 --- a/assets/js/1c14429f.4b597116.js +++ b/assets/js/1c14429f.c57b3392.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[2702],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var o=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=o.createContext({}),d=function(e){var t=o.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=d(e.components);return o.createElement(s.Provider,{value:t},e.children)},u="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},h=o.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),u=d(n),h=a,m=u["".concat(s,".").concat(h)]||u[h]||p[h]||r;return n?o.createElement(m,i(i({ref:t},c),{},{components:n})):o.createElement(m,i({ref:t},c))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,i=new Array(r);i[0]=h;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[u]="string"==typeof e?e:a,i[1]=l;for(var d=2;d{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>m,frontMatter:()=>l,metadata:()=>d,toc:()=>u});var o=n(7462),a=(n(7294),n(3905)),r=n(3872),i=n(2915);const l={template:"post",draft:!1,hide_title:!0,title:"Getting Started",slug:"getting-started",date:new Date("2023-08-31T23:00:00.000Z"),canonical:"",description:"A first look at what Fleek Network is, why it's important, and a simple tutorial of running and interacting with a node on your local machine!",category:"Tutorial",tags:["Edge computing","Guide","Getting Started"]},s=void 0,d={unversionedId:"Node Operators/getting-started-guide",id:"Node Operators/getting-started-guide",title:"Getting Started",description:"A first look at what Fleek Network is, why it's important, and a simple tutorial of running and interacting with a node on your local machine!",source:"@site/guides/Node Operators/getting-started-guide.md",sourceDirName:"Node Operators",slug:"/Node Operators/getting-started",permalink:"/guides/Node Operators/getting-started",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/guides/Node Operators/getting-started-guide.md",tags:[{label:"Edge computing",permalink:"/guides/tags/edge-computing"},{label:"Guide",permalink:"/guides/tags/guide"},{label:"Getting Started",permalink:"/guides/tags/getting-started"}],version:"current",lastUpdatedAt:1694784773,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{template:"post",draft:!1,hide_title:!0,title:"Getting Started",slug:"getting-started",date:"2023-08-31T23:00:00.000Z",canonical:"",description:"A first look at what Fleek Network is, why it's important, and a simple tutorial of running and interacting with a node on your local machine!",category:"Tutorial",tags:["Edge computing","Guide","Getting Started"]},sidebar:"defaultSidebar",previous:{title:"About guides",permalink:"/guides/"},next:{title:"Managing the keystore",permalink:"/guides/Node Operators/managing-the-keystore"}},c={},u=[{value:"Introduction",id:"introduction",level:2},{value:"Pre-requisites",id:"pre-requisites",level:2},{value:"Need a quick Fleek Network TL;DR?",id:"need-a-quick-fleek-network-tldr",level:2},{value:"Why is Fleek Network needed?",id:"why-is-fleek-network-needed",level:2},{value:"How Does Fleek Network Work?",id:"how-does-fleek-network-work",level:2},{value:"Running a Node",id:"running-a-node",level:2},{value:"Clone the source code",id:"clone-the-source-code",level:3},{value:"Dependencies",id:"dependencies",level:3},{value:"Build",id:"build",level:3},{value:"Node Launch",id:"node-launch",level:3},{value:"Health check",id:"health-check",level:3},{value:"Next steps",id:"next-steps",level:2},{value:"Conclusion",id:"conclusion",level:2}],p={toc:u},h="wrapper";function m(e){let{components:t,...n}=e;return(0,a.kt)(h,(0,o.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"introduction"},"Introduction"),(0,a.kt)("p",null,"For this guide, we\u2019ll have a simple look into how Fleek Network works in its current development phase and briefly share some of the core concepts like spinning up a node and making a request to a service to put and retrieve a .car files from the network."),(0,a.kt)("p",null,"For those seeking advanced knowledge:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Read our ",(0,a.kt)("a",{parentName:"li",href:"/docs/whitepaper"},"whitepaper"),"."),(0,a.kt)("li",{parentName:"ul"},"Check out ",(0,a.kt)("a",{parentName:"li",href:"https://github.com/fleek-network/lightning"},"our open-source code"),".")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"If you find any typos in our documentation, feel free to ",(0,a.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"provide us feedback")," or contribute by opening a PR in our repository ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/fleek-network-docs/"},"here"),".")),(0,a.kt)("h2",{id:"pre-requisites"},"Pre-requisites"),(0,a.kt)("p",null,"To follow the guide, you will need the following:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Familiarity with the command-line interface"),(0,a.kt)("li",{parentName:"ul"},"Git")),(0,a.kt)("h2",{id:"need-a-quick-fleek-network-tldr"},"Need a quick Fleek Network TL;DR?"),(0,a.kt)("p",null,"Fleek Network is an open-source edge computing platform to accelerate the development and execution of the next generation of web services."),(0,a.kt)("p",null,"The system is built on a distributed network of nodes, where services run within a fair and incentivized ecosystem constituted by an open community of developers and operators. It relies on blockchain technology at its core, allowing governance and token rewards as incentives for participation in serving the network."),(0,a.kt)("p",null,"Made by an open community that's free to operate nodes or build services without the need for approvals, permissions, or intermediaries. Or simply, consume Fleek Network resources on demand, from anywhere, provided by services running on the edge."),(0,a.kt)("p",null,"Applications, platforms and protocols build and utilize decentralized services on the Fleek Network to optimize performance and reduce dependency on typical centralized cloud providers and corporate infrastructure."),(0,a.kt)("p",null,"Developers can build faster and launch better products by offloading parts of the development stack to the edge to focus on core features for the value proposition of the services being developed."),(0,a.kt)("p",null,"To get started, install a Network Node in a ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/requirements"},"supported")," Linux server, such as Debian or Ubuntu (latest) by utilizing our simple ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/install#assisted-installer"},"assisted installer")," to help onboard as quickly as possible."),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"Our network is open to everyone, so you're more than welcome to join us anytime without any restrictions, permission or formalities. We'd be happy to have you as part of our community!")),(0,a.kt)("p",null,"Once connected to the server, open a terminal window and execute the following command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"curl https://get.fleek.network | bash\n")),(0,a.kt)("p",null,"Follow the install assistant recommendations to have the node ready without hassle and as quickly as possible."),(0,a.kt)("h2",{id:"why-is-fleek-network-needed"},"Why is Fleek Network needed?"),(0,a.kt)("p",null,"Web3 products typically rely on centralized cloud infrastructure, which is vulnerable to attacks as computation and data can be easily manipulated to suit business goals. However, blockchain technology has paved the way for a new era of decentralized cloud computing and data storage. The Fleek Network offers a sustainable alternative to traditional centralized architectures, providing a secure, transparent, and accessible decentralized edge computing future for everyone."),(0,a.kt)("h2",{id:"how-does-fleek-network-work"},"How Does Fleek Network Work?"),(0,a.kt)("p",null,"When a client requests a service, the protocol determines the best route to the nodes where the service replicas and workload are allocated."),(0,a.kt)("p",null,"Once the computation is successful, the data streaming routes to the client. On-client request fulfillment, a proof of delivery is generated containing cryptographically secured metadata about the original request, any parts involved and the resources consumed."),(0,a.kt)("p",null,"The Delivery Acknowledgements are stored locally in the participating node memory pools, rolled up to the protocol consensus consistently throughout the Epoch. This agreement is formed by a random committee of any healthy Nodes that use the information provided to reward the Nodes fairly."),(0,a.kt)("h2",{id:"running-a-node"},"Running a Node"),(0,a.kt)("p",null,"A Fleek Network node can be built and run on your machine. It\u2019s an ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/lightning"},"open-source project")," and is open for contributions."),(0,a.kt)("p",null,"The project is written with Rust, a general-purpose programming language that you need to have installed in advance to be able to follow the current guide."),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"To set up Rust, packages and library dependencies can be tricky. The quickest is to visit the ",(0,a.kt)("a",{parentName:"p",href:"https://rustup.rs/"},"rustup.rs"),". Alternatively, if you haven't already, the build section has a ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/install#manual-installation"},"manual installation")," document to help.")),(0,a.kt)("h3",{id:"clone-the-source-code"},"Clone the source code"),(0,a.kt)("p",null,"We\u2019ll clone the repository locally, build it and interact with the node through the binary or the HTTP JSON-RPC API with a client like cURL, but you can use a GUI (Postman, Insomnia, amongst others) if you prefer."),(0,a.kt)("admonition",{type:"note"},(0,a.kt)("p",{parentName:"admonition"},"The ~/fleek-network/lightning or $HOME/fleek-network/lightning directory is the default or recommended location to store the repository. If you like to follow conventions, then is best to stick with the recommendation, to avoid confusion and make it easier to follow our documentation.")),(0,a.kt)("p",null,"Start by cloning the repository located at ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/lightning"},"https://github.com/fleek-network/lightning")),(0,a.kt)(i.ZP,{mdxType:"GitCloneOptions"}),(0,a.kt)("p",null,"Once the git clone completes, you\u2019ll have the latest version at the time of cloning. You should use git to fetch or pull the latest versions consequently."),(0,a.kt)("h3",{id:"dependencies"},"Dependencies"),(0,a.kt)("p",null,"Install the required dependencies necessary for compiling general software and for our use-case Lightning CLI."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"sudo apt-get install \\\n build-essential \\\n clang \\\n pkg-config \\\n libssl-dev \\\n gcc-multilib \\\n protobuf-compiler\n")),(0,a.kt)("h3",{id:"build"},"Build"),(0,a.kt)("p",null,"Start by changing the directory to the project directory where the source code is stored. If you have followed the recommended location that'll be ",(0,a.kt)("inlineCode",{parentName:"p"},"~/fleek-network/lightning"),", as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"cd ~/fleek-network/lightning\n")),(0,a.kt)("p",null,"Run the Rust package manager clean and update commands."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"cargo clean\ncargo update\n")),(0,a.kt)("p",null,"Execute the install command to build and install the Fleek Network CLI."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"cargo build\n")),(0,a.kt)("p",null,"The install command uses the Rust compiler to build; It might take a while depending on how speedy is your machine."),(0,a.kt)("p",null,"Once the Rust compiler completes, the generated binary will be available in the source code project directory. If you stick with the default, that'll look like ",(0,a.kt)("inlineCode",{parentName:"p"},"~/fleek-network/lightning/target/debug/lightning-node"),"."),(0,a.kt)("p",null,"To avoid having to specify the pathname everytime, create a symbolic link to keep it short. Here we'll name the process as the global ",(0,a.kt)("inlineCode",{parentName:"p"},"lgtn"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'sudo ln -s "~/fleek-network/lightning/target/debug/lightning-node" /usr/local/bin/lgtn\n')),(0,a.kt)("p",null,"Run the CLI with the flag ",(0,a.kt)("inlineCode",{parentName:"p"},"version")," to confirm it's available globally."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn --version\n")),(0,a.kt)("p",null,"The output should look like:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"Usage: lgtn [OPTIONS] \n\nCommands:\n run Start the node\n keys Handle keys\n print-config Print the loaded configuration\n dev-init-only Initialize the node without starting it\n dev-dump-graph Dump the infusion graph of the node instance\n help Print this message or the help of the given subcommand(s)\n\nOptions:\n -c, --config Path to the toml configuration file [default: ~/.lightning/config.toml]\n --with-mock-consensus Determines that we should be using the mock consensus backend\n -v... Increases the level of verbosity (the max level is -vvv)\n --log-location Print code location on console logs\n -h, --help Print help\n -V, --version Print version\n")),(0,a.kt)("h3",{id:"node-launch"},"Node Launch"),(0,a.kt)("p",null,"After ",(0,a.kt)("a",{parentName:"p",href:"#build"},"building"),", the node can be launched by running the subcommand ",(0,a.kt)("inlineCode",{parentName:"p"},"run"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn run\n")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"It's highly recommend to use systemd to manage the Fleek Network service for node operators. Systemd is a system and service manager for Linux operating systems that provides a consistent way to manage system services across various distributions.")),(0,a.kt)("p",null,"Learn how to create a new Systemd service in the ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/install#manual-installation"},"manual installation")," document."),(0,a.kt)("h3",{id:"health-check"},"Health check"),(0,a.kt)("p",null,"It's important for Node operators to regularly check on the health of their resources to make sure everything is running smoothly. By doing this, they can get helpful feedback and know for sure if their Node is up and running. Some experienced node operators even automate this process using cronjobs and get reports sent to them via email or other custom methods."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'curl -w "\\n" localhost:4069/health\n')),(0,a.kt)("p",null,"If everything goes well, the response should be:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"OK\n")),(0,a.kt)("p",null,"Alternatively, use the JSON-RPC method ",(0,a.kt)("inlineCode",{parentName:"p"},"flk_ping"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'curl -s \\\n -X POST \\\n -H "Content-Type: application/json" \\\n -d \'{\n "jsonrpc": "2.0",\n "method": "flk_ping",\n "params": [],\n "id": 1\n }\' \\\n localhost:4069/rpc/v0\n')),(0,a.kt)("p",null,"Which response should return the key ",(0,a.kt)("inlineCode",{parentName:"p"},"result")," with value ",(0,a.kt)("inlineCode",{parentName:"p"},"pong"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'{\n "jsonrpc": "2.0",\n "result": "pong",\n "id": 1\n}\n')),(0,a.kt)("h2",{id:"next-steps"},"Next steps"),(0,a.kt)("p",null,"While you can run the Network Node as described here, it's required to set up the Network Node correctly and securely! It requires some degree of patience, knowledge and time to go through our guides but we'll provide some guides and references to help you manage your network node server!"),(0,a.kt)("p",null,"To avoid having to go through all the steps manually, we recommend reading our ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/install#assisted-installer"},"assisted installer")," document for quick onboarding."),(0,a.kt)("h2",{id:"conclusion"},"Conclusion"),(0,a.kt)("p",null,"We introduced Fleek Network as an open-source edge computing platform to help us accelerate the development and execution of the next generation of web services."),(0,a.kt)("p",null,"We have learned a bit about the importance of a decentralized edge computing network to reach and fulfill the future of computation and how the Fleek Network protocol works succinctly."),(0,a.kt)("p",null,"We guide you through a step-by-step installation of the network node process, where we pull the source code, build the binary and launch the service."),(0,a.kt)("p",null,"Finally, we do a quick health check to confirm the status of our node."),(0,a.kt)("p",null,"Discover more about the project by ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/lightning"},"watching/contributing on GitHub"),", following us on ",(0,a.kt)("a",{parentName:"p",href:"https://twitter.com/fleek_net"},"Twitter"),", and joining ",(0,a.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"our community Discord")," for any updates."),(0,a.kt)(r.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}m.isMDXComponent=!0},2915:(e,t,n)=>{n.d(t,{ZP:()=>l});var o=n(7462),a=(n(7294),n(3905));const r={toc:[]},i="wrapper";function l(e){let{components:t,...n}=e;return(0,a.kt)(i,(0,o.Z)({},r,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"You have several ways of doing this:"),(0,a.kt)("ul",{parentName:"admonition"},(0,a.kt)("li",{parentName:"ul"},"Clone via HTTPS"),(0,a.kt)("li",{parentName:"ul"},"Clone via SSH"),(0,a.kt)("li",{parentName:"ul"},"Download via Github CLI"),(0,a.kt)("li",{parentName:"ul"},"Download the ",(0,a.kt)("a",{parentName:"li",href:"https://github.com/fleek-network/lightning/archive/refs/heads/main.zip"},"zip package")," from the repository")),(0,a.kt)("p",{parentName:"admonition"},"We recommend HTTPS because it is the easiest to set up in the wild, and by users who are new to all this.\nAlthough, we strongly recommend using an SSH connection when interacting with GitHub. If you are to this and are interested read more about it ",(0,a.kt)("a",{parentName:"p",href:"https://docs.github.com/en/authentication/connecting-to-github-with-ssh"},"here"),"."),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"git clone -b testnet-alpha-0 https://github.com/fleek-network/lightning.git \n")),(0,a.kt)("p",{parentName:"admonition"},"Here's an example of what it'd look like when sticking to the recommended path location:"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"git clone -b testnet-alpha-0 https://github.com/fleek-network/lightning.git ~/fleek-network/lightning\n"))))}l.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>a});var o=n(7294);const a=e=>{let{image:t,name:n,title:a,url:r,communityMember:i=!1}=e;return o.createElement("section",{className:"author_card"},o.createElement("div",null,o.createElement("span",{className:"avatar"},o.createElement("a",{href:r,target:"_blank",alt:n},o.createElement("img",{src:t,alt:n}))),o.createElement("div",null,o.createElement("span",{className:"name"},o.createElement("a",{href:r,target:"_blank",alt:n},n)),o.createElement("span",{className:"title"},a),o.createElement("span",{className:"discord"},i?"Join our community on":"Got questions? Find us on"," ",o.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[2702],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var o=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=o.createContext({}),d=function(e){var t=o.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=d(e.components);return o.createElement(s.Provider,{value:t},e.children)},u="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},h=o.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),u=d(n),h=a,m=u["".concat(s,".").concat(h)]||u[h]||p[h]||r;return n?o.createElement(m,i(i({ref:t},c),{},{components:n})):o.createElement(m,i({ref:t},c))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,i=new Array(r);i[0]=h;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[u]="string"==typeof e?e:a,i[1]=l;for(var d=2;d{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>s,default:()=>m,frontMatter:()=>l,metadata:()=>d,toc:()=>u});var o=n(7462),a=(n(7294),n(3905)),r=n(3872),i=n(2915);const l={template:"post",draft:!1,hide_title:!0,title:"Getting Started",slug:"getting-started",date:new Date("2023-08-31T23:00:00.000Z"),canonical:"",description:"A first look at what Fleek Network is, why it's important, and a simple tutorial of running and interacting with a node on your local machine!",category:"Tutorial",tags:["Edge computing","Guide","Getting Started"]},s=void 0,d={unversionedId:"Node Operators/getting-started-guide",id:"Node Operators/getting-started-guide",title:"Getting Started",description:"A first look at what Fleek Network is, why it's important, and a simple tutorial of running and interacting with a node on your local machine!",source:"@site/guides/Node Operators/getting-started-guide.md",sourceDirName:"Node Operators",slug:"/Node Operators/getting-started",permalink:"/guides/Node Operators/getting-started",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/guides/Node Operators/getting-started-guide.md",tags:[{label:"Edge computing",permalink:"/guides/tags/edge-computing"},{label:"Guide",permalink:"/guides/tags/guide"},{label:"Getting Started",permalink:"/guides/tags/getting-started"}],version:"current",lastUpdatedAt:1694785242,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{template:"post",draft:!1,hide_title:!0,title:"Getting Started",slug:"getting-started",date:"2023-08-31T23:00:00.000Z",canonical:"",description:"A first look at what Fleek Network is, why it's important, and a simple tutorial of running and interacting with a node on your local machine!",category:"Tutorial",tags:["Edge computing","Guide","Getting Started"]},sidebar:"defaultSidebar",previous:{title:"About guides",permalink:"/guides/"},next:{title:"Managing the keystore",permalink:"/guides/Node Operators/managing-the-keystore"}},c={},u=[{value:"Introduction",id:"introduction",level:2},{value:"Pre-requisites",id:"pre-requisites",level:2},{value:"Need a quick Fleek Network TL;DR?",id:"need-a-quick-fleek-network-tldr",level:2},{value:"Why is Fleek Network needed?",id:"why-is-fleek-network-needed",level:2},{value:"How Does Fleek Network Work?",id:"how-does-fleek-network-work",level:2},{value:"Running a Node",id:"running-a-node",level:2},{value:"Clone the source code",id:"clone-the-source-code",level:3},{value:"Dependencies",id:"dependencies",level:3},{value:"Build",id:"build",level:3},{value:"Node Launch",id:"node-launch",level:3},{value:"Health check",id:"health-check",level:3},{value:"Next steps",id:"next-steps",level:2},{value:"Conclusion",id:"conclusion",level:2}],p={toc:u},h="wrapper";function m(e){let{components:t,...n}=e;return(0,a.kt)(h,(0,o.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"introduction"},"Introduction"),(0,a.kt)("p",null,"For this guide, we\u2019ll have a simple look into how Fleek Network works in its current development phase and briefly share some of the core concepts like spinning up a node and making a request to a service to put and retrieve a .car files from the network."),(0,a.kt)("p",null,"For those seeking advanced knowledge:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Read our ",(0,a.kt)("a",{parentName:"li",href:"/docs/whitepaper"},"whitepaper"),"."),(0,a.kt)("li",{parentName:"ul"},"Check out ",(0,a.kt)("a",{parentName:"li",href:"https://github.com/fleek-network/lightning"},"our open-source code"),".")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"If you find any typos in our documentation, feel free to ",(0,a.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"provide us feedback")," or contribute by opening a PR in our repository ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/fleek-network-docs/"},"here"),".")),(0,a.kt)("h2",{id:"pre-requisites"},"Pre-requisites"),(0,a.kt)("p",null,"To follow the guide, you will need the following:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Familiarity with the command-line interface"),(0,a.kt)("li",{parentName:"ul"},"Git")),(0,a.kt)("h2",{id:"need-a-quick-fleek-network-tldr"},"Need a quick Fleek Network TL;DR?"),(0,a.kt)("p",null,"Fleek Network is an open-source edge computing platform to accelerate the development and execution of the next generation of web services."),(0,a.kt)("p",null,"The system is built on a distributed network of nodes, where services run within a fair and incentivized ecosystem constituted by an open community of developers and operators. It relies on blockchain technology at its core, allowing governance and token rewards as incentives for participation in serving the network."),(0,a.kt)("p",null,"Made by an open community that's free to operate nodes or build services without the need for approvals, permissions, or intermediaries. Or simply, consume Fleek Network resources on demand, from anywhere, provided by services running on the edge."),(0,a.kt)("p",null,"Applications, platforms and protocols build and utilize decentralized services on the Fleek Network to optimize performance and reduce dependency on typical centralized cloud providers and corporate infrastructure."),(0,a.kt)("p",null,"Developers can build faster and launch better products by offloading parts of the development stack to the edge to focus on core features for the value proposition of the services being developed."),(0,a.kt)("p",null,"To get started, install a Network Node in a ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/requirements"},"supported")," Linux server, such as Debian or Ubuntu (latest) by utilizing our simple ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/install#assisted-installer"},"assisted installer")," to help onboard as quickly as possible."),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"Our network is open to everyone, so you're more than welcome to join us anytime without any restrictions, permission or formalities. We'd be happy to have you as part of our community!")),(0,a.kt)("p",null,"Once connected to the server, open a terminal window and execute the following command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"curl https://get.fleek.network | bash\n")),(0,a.kt)("p",null,"Follow the install assistant recommendations to have the node ready without hassle and as quickly as possible."),(0,a.kt)("h2",{id:"why-is-fleek-network-needed"},"Why is Fleek Network needed?"),(0,a.kt)("p",null,"Web3 products typically rely on centralized cloud infrastructure, which is vulnerable to attacks as computation and data can be easily manipulated to suit business goals. However, blockchain technology has paved the way for a new era of decentralized cloud computing and data storage. The Fleek Network offers a sustainable alternative to traditional centralized architectures, providing a secure, transparent, and accessible decentralized edge computing future for everyone."),(0,a.kt)("h2",{id:"how-does-fleek-network-work"},"How Does Fleek Network Work?"),(0,a.kt)("p",null,"When a client requests a service, the protocol determines the best route to the nodes where the service replicas and workload are allocated."),(0,a.kt)("p",null,"Once the computation is successful, the data streaming routes to the client. On-client request fulfillment, a proof of delivery is generated containing cryptographically secured metadata about the original request, any parts involved and the resources consumed."),(0,a.kt)("p",null,"The Delivery Acknowledgements are stored locally in the participating node memory pools, rolled up to the protocol consensus consistently throughout the Epoch. This agreement is formed by a random committee of any healthy Nodes that use the information provided to reward the Nodes fairly."),(0,a.kt)("h2",{id:"running-a-node"},"Running a Node"),(0,a.kt)("p",null,"A Fleek Network node can be built and run on your machine. It\u2019s an ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/lightning"},"open-source project")," and is open for contributions."),(0,a.kt)("p",null,"The project is written with Rust, a general-purpose programming language that you need to have installed in advance to be able to follow the current guide."),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"To set up Rust, packages and library dependencies can be tricky. The quickest is to visit the ",(0,a.kt)("a",{parentName:"p",href:"https://rustup.rs/"},"rustup.rs"),". Alternatively, if you haven't already, the build section has a ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/install#manual-installation"},"manual installation")," document to help.")),(0,a.kt)("h3",{id:"clone-the-source-code"},"Clone the source code"),(0,a.kt)("p",null,"We\u2019ll clone the repository locally, build it and interact with the node through the binary or the HTTP JSON-RPC API with a client like cURL, but you can use a GUI (Postman, Insomnia, amongst others) if you prefer."),(0,a.kt)("admonition",{type:"note"},(0,a.kt)("p",{parentName:"admonition"},"The ~/fleek-network/lightning or $HOME/fleek-network/lightning directory is the default or recommended location to store the repository. If you like to follow conventions, then is best to stick with the recommendation, to avoid confusion and make it easier to follow our documentation.")),(0,a.kt)("p",null,"Start by cloning the repository located at ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/lightning"},"https://github.com/fleek-network/lightning")),(0,a.kt)(i.ZP,{mdxType:"GitCloneOptions"}),(0,a.kt)("p",null,"Once the git clone completes, you\u2019ll have the latest version at the time of cloning. You should use git to fetch or pull the latest versions consequently."),(0,a.kt)("h3",{id:"dependencies"},"Dependencies"),(0,a.kt)("p",null,"Install the required dependencies necessary for compiling general software and for our use-case Lightning CLI."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"sudo apt-get install \\\n build-essential \\\n clang \\\n pkg-config \\\n libssl-dev \\\n gcc-multilib \\\n protobuf-compiler\n")),(0,a.kt)("h3",{id:"build"},"Build"),(0,a.kt)("p",null,"Start by changing the directory to the project directory where the source code is stored. If you have followed the recommended location that'll be ",(0,a.kt)("inlineCode",{parentName:"p"},"~/fleek-network/lightning"),", as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"cd ~/fleek-network/lightning\n")),(0,a.kt)("p",null,"Run the Rust package manager clean and update commands."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"cargo clean\ncargo update\n")),(0,a.kt)("p",null,"Execute the install command to build and install the Fleek Network CLI."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"cargo build\n")),(0,a.kt)("p",null,"The install command uses the Rust compiler to build; It might take a while depending on how speedy is your machine."),(0,a.kt)("p",null,"Once the Rust compiler completes, the generated binary will be available in the source code project directory. If you stick with the default, that'll look like ",(0,a.kt)("inlineCode",{parentName:"p"},"~/fleek-network/lightning/target/debug/lightning-node"),"."),(0,a.kt)("p",null,"To avoid having to specify the pathname everytime, create a symbolic link to keep it short. Here we'll name the process as the global ",(0,a.kt)("inlineCode",{parentName:"p"},"lgtn"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'sudo ln -s "~/fleek-network/lightning/target/debug/lightning-node" /usr/local/bin/lgtn\n')),(0,a.kt)("p",null,"Run the CLI with the flag ",(0,a.kt)("inlineCode",{parentName:"p"},"version")," to confirm it's available globally."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn --version\n")),(0,a.kt)("p",null,"The output should look like:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"Usage: lgtn [OPTIONS] \n\nCommands:\n run Start the node\n keys Handle keys\n print-config Print the loaded configuration\n dev-init-only Initialize the node without starting it\n dev-dump-graph Dump the infusion graph of the node instance\n help Print this message or the help of the given subcommand(s)\n\nOptions:\n -c, --config Path to the toml configuration file [default: ~/.lightning/config.toml]\n --with-mock-consensus Determines that we should be using the mock consensus backend\n -v... Increases the level of verbosity (the max level is -vvv)\n --log-location Print code location on console logs\n -h, --help Print help\n -V, --version Print version\n")),(0,a.kt)("h3",{id:"node-launch"},"Node Launch"),(0,a.kt)("p",null,"After ",(0,a.kt)("a",{parentName:"p",href:"#build"},"building"),", the node can be launched by running the subcommand ",(0,a.kt)("inlineCode",{parentName:"p"},"run"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn run\n")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"It's highly recommend to use systemd to manage the Fleek Network service for node operators. Systemd is a system and service manager for Linux operating systems that provides a consistent way to manage system services across various distributions.")),(0,a.kt)("p",null,"Learn how to create a new Systemd service in the ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/install#manual-installation"},"manual installation")," document."),(0,a.kt)("h3",{id:"health-check"},"Health check"),(0,a.kt)("p",null,"It's important for Node operators to regularly check on the health of their resources to make sure everything is running smoothly. By doing this, they can get helpful feedback and know for sure if their Node is up and running. Some experienced node operators even automate this process using cronjobs and get reports sent to them via email or other custom methods."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'curl -w "\\n" localhost:4069/health\n')),(0,a.kt)("p",null,"If everything goes well, the response should be:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"OK\n")),(0,a.kt)("p",null,"Alternatively, use the JSON-RPC method ",(0,a.kt)("inlineCode",{parentName:"p"},"flk_ping"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'curl -s \\\n -X POST \\\n -H "Content-Type: application/json" \\\n -d \'{\n "jsonrpc": "2.0",\n "method": "flk_ping",\n "params": [],\n "id": 1\n }\' \\\n localhost:4069/rpc/v0\n')),(0,a.kt)("p",null,"Which response should return the key ",(0,a.kt)("inlineCode",{parentName:"p"},"result")," with value ",(0,a.kt)("inlineCode",{parentName:"p"},"pong"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'{\n "jsonrpc": "2.0",\n "result": "pong",\n "id": 1\n}\n')),(0,a.kt)("h2",{id:"next-steps"},"Next steps"),(0,a.kt)("p",null,"While you can run the Network Node as described here, it's required to set up the Network Node correctly and securely! It requires some degree of patience, knowledge and time to go through our guides but we'll provide some guides and references to help you manage your network node server!"),(0,a.kt)("p",null,"To avoid having to go through all the steps manually, we recommend reading our ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/install#assisted-installer"},"assisted installer")," document for quick onboarding."),(0,a.kt)("h2",{id:"conclusion"},"Conclusion"),(0,a.kt)("p",null,"We introduced Fleek Network as an open-source edge computing platform to help us accelerate the development and execution of the next generation of web services."),(0,a.kt)("p",null,"We have learned a bit about the importance of a decentralized edge computing network to reach and fulfill the future of computation and how the Fleek Network protocol works succinctly."),(0,a.kt)("p",null,"We guide you through a step-by-step installation of the network node process, where we pull the source code, build the binary and launch the service."),(0,a.kt)("p",null,"Finally, we do a quick health check to confirm the status of our node."),(0,a.kt)("p",null,"Discover more about the project by ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/lightning"},"watching/contributing on GitHub"),", following us on ",(0,a.kt)("a",{parentName:"p",href:"https://twitter.com/fleek_net"},"Twitter"),", and joining ",(0,a.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"our community Discord")," for any updates."),(0,a.kt)(r.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}m.isMDXComponent=!0},2915:(e,t,n)=>{n.d(t,{ZP:()=>l});var o=n(7462),a=(n(7294),n(3905));const r={toc:[]},i="wrapper";function l(e){let{components:t,...n}=e;return(0,a.kt)(i,(0,o.Z)({},r,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"You have several ways of doing this:"),(0,a.kt)("ul",{parentName:"admonition"},(0,a.kt)("li",{parentName:"ul"},"Clone via HTTPS"),(0,a.kt)("li",{parentName:"ul"},"Clone via SSH"),(0,a.kt)("li",{parentName:"ul"},"Download via Github CLI"),(0,a.kt)("li",{parentName:"ul"},"Download the ",(0,a.kt)("a",{parentName:"li",href:"https://github.com/fleek-network/lightning/archive/refs/heads/main.zip"},"zip package")," from the repository")),(0,a.kt)("p",{parentName:"admonition"},"We recommend HTTPS because it is the easiest to set up in the wild, and by users who are new to all this.\nAlthough, we strongly recommend using an SSH connection when interacting with GitHub. If you are to this and are interested read more about it ",(0,a.kt)("a",{parentName:"p",href:"https://docs.github.com/en/authentication/connecting-to-github-with-ssh"},"here"),"."),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"git clone -b testnet-alpha-0 https://github.com/fleek-network/lightning.git \n")),(0,a.kt)("p",{parentName:"admonition"},"Here's an example of what it'd look like when sticking to the recommended path location:"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"git clone -b testnet-alpha-0 https://github.com/fleek-network/lightning.git ~/fleek-network/lightning\n"))))}l.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>a});var o=n(7294);const a=e=>{let{image:t,name:n,title:a,url:r,communityMember:i=!1}=e;return o.createElement("section",{className:"author_card"},o.createElement("div",null,o.createElement("span",{className:"avatar"},o.createElement("a",{href:r,target:"_blank",alt:n},o.createElement("img",{src:t,alt:n}))),o.createElement("div",null,o.createElement("span",{className:"name"},o.createElement("a",{href:r,target:"_blank",alt:n},n)),o.createElement("span",{className:"title"},a),o.createElement("span",{className:"discord"},i?"Join our community on":"Got questions? Find us on"," ",o.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file diff --git a/assets/js/1d8a5d15.76804856.js b/assets/js/1d8a5d15.4040af92.js similarity index 99% rename from assets/js/1d8a5d15.76804856.js rename to assets/js/1d8a5d15.4040af92.js index 0516eef04..610f02104 100644 --- a/assets/js/1d8a5d15.76804856.js +++ b/assets/js/1d8a5d15.4040af92.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[9854],{3905:(e,t,n)=>{n.d(t,{Zo:()=>h,kt:()=>c});var o=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=o.createContext({}),p=function(e){var t=o.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},h=function(e){var t=p(e.components);return o.createElement(l.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},m=o.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,l=e.parentName,h=s(e,["components","mdxType","originalType","parentName"]),d=p(n),m=r,c=d["".concat(l,".").concat(m)]||d[m]||u[m]||a;return n?o.createElement(c,i(i({ref:t},h),{},{components:n})):o.createElement(c,i({ref:t},h))}));function c(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,i=new Array(a);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:r,i[1]=s;for(var p=2;p{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>p,default:()=>g,frontMatter:()=>l,metadata:()=>h,toc:()=>u});var o=n(7462),r=(n(7294),n(3905)),a=n(3872),i=(n(2915),n(6733)),s=n(3242);const l={template:"post",draft:!1,hide_title:!0,title:"Transfering setup ownership",slug:"transfering-setup-ownership",date:new Date("2023-09-12T23:00:00.000Z"),description:"A step-by-step guide to transfer the ownership of the Fleek Network Lightning CLI and service setup",category:"Tutorial",tags:["transfer","ownership","guide","setup","configuration"]},p=void 0,h={unversionedId:"Node Operators/transfering-setup-ownership",id:"Node Operators/transfering-setup-ownership",title:"Transfering setup ownership",description:"A step-by-step guide to transfer the ownership of the Fleek Network Lightning CLI and service setup",source:"@site/guides/Node Operators/transfering-setup-ownership.md",sourceDirName:"Node Operators",slug:"/Node Operators/transfering-setup-ownership",permalink:"/guides/Node Operators/transfering-setup-ownership",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/guides/Node Operators/transfering-setup-ownership.md",tags:[{label:"transfer",permalink:"/guides/tags/transfer"},{label:"ownership",permalink:"/guides/tags/ownership"},{label:"guide",permalink:"/guides/tags/guide"},{label:"setup",permalink:"/guides/tags/setup"},{label:"configuration",permalink:"/guides/tags/configuration"}],version:"current",lastUpdatedAt:1694784773,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{template:"post",draft:!1,hide_title:!0,title:"Transfering setup ownership",slug:"transfering-setup-ownership",date:"2023-09-12T23:00:00.000Z",description:"A step-by-step guide to transfer the ownership of the Fleek Network Lightning CLI and service setup",category:"Tutorial",tags:["transfer","ownership","guide","setup","configuration"]},sidebar:"defaultSidebar",previous:{title:"Managing the keystore",permalink:"/guides/Node Operators/managing-the-keystore"}},d={},u=[{value:"TL;DR",id:"tldr",level:2},{value:"Introduction",id:"introduction",level:2},{value:"Pre-requisites",id:"pre-requisites",level:2},{value:"Ownership of Lightning CLI files",id:"ownership-of-lightning-cli-files",level:2},{value:"Systemd Service",id:"systemd-service",level:2},{value:"Stop the service",id:"stop-the-service",level:2},{value:"Clear the .lightning data",id:"clear-the-lightning-data",level:2},{value:"Create a user",id:"create-a-user",level:2},{value:"Move lightning system and source code directory to user's home",id:"move-lightning-system-and-source-code-directory-to-users-home",level:2},{value:"1) Move the /root/.lightning directory from one user to the other",id:"1-move-the-rootlightning-directory-from-one-user-to-the-other",level:3},{value:"2) Move the /root/fleek-network directory from one user to the other",id:"2-move-the-rootfleek-network-directory-from-one-user-to-the-other",level:3},{value:"3) Confirm move by finding both directories",id:"3-confirm-move-by-finding-both-directories",level:3},{value:"Change ownership of files",id:"change-ownership-of-files",level:2},{value:"The lgtn symbolic link (symlink)",id:"the-lgtn-symbolic-link-symlink",level:2},{value:"Update the Systemd service unit",id:"update-the-systemd-service-unit",level:2},{value:"Update the config.toml with user-preferred file locations",id:"update-the-configtoml-with-user-preferred-file-locations",level:2},{value:"Start the service",id:"start-the-service",level:2},{value:"Conclusion",id:"conclusion",level:2}],m={toc:u},c="wrapper";function g(e){let{components:t,...n}=e;return(0,r.kt)(c,(0,o.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"tldr"},"TL;DR"),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"The step-by-step instructions provided in the guide should be simple to follow, but the process is also available as an automated script from our familiar ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/get.fleek.network"},"get.fleek.network")," tool."),(0,r.kt)("p",{parentName:"admonition"},"To use the automated script execute the following command in your server terminal and follow the instructions:"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"curl -sS https://get.fleek.network/transfer_system_user_setup_ownership | bash\n")),(0,r.kt)("p",{parentName:"admonition"},"We try to make the auomated scripts as useful as possible, but it's impossible to fit every single use-case. So, if you find any isses or have feedback to help us improve ",(0,r.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"message us through our Discord"),".")),(0,r.kt)("h2",{id:"introduction"},"Introduction"),(0,r.kt)("p",null,"Our Lightning CLI and Node process is run by a user, that has some sort of permissions\u2013some users run it as a super user (root) which is questionable as root privileges are not a necessary good. We'll look into how to create a user to manage and control the Fleek Network Lightning CLI and Systemd unit service. Also, presents the concept of file permissions and ownership which is crucial in preventing private or sensitive data from being exposed to dodgy actors."),(0,r.kt)("p",null,"Let's discuss the topic and open up a few ideas to help us improve the security of our server."),(0,r.kt)("h2",{id:"pre-requisites"},"Pre-requisites"),(0,r.kt)("p",null,"To follow the guide, you will need the following:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Familiarity with the command-line interface"),(0,r.kt)("li",{parentName:"ul"},"Have installed and set up the Lightning CLI and service")),(0,r.kt)("h2",{id:"ownership-of-lightning-cli-files"},"Ownership of Lightning CLI files"),(0,r.kt)("p",null,"The user who installs the Lightning CLI and sets the Service takes an important role that determines the location of the configuration files, the setup, and how the Systemd service is managed or controlled."),(0,r.kt)("p",null,"Our ",(0,r.kt)("a",{parentName:"p",href:"/docs/node/install"},"install")," document recommends creating a user and switching to the user to set up the service. You shouldn't want installed applications to run with elevated privileges. Applications are meant to be run with non-administrative privileges. If an application requires higher privileges, the administrator, such as a ",(0,r.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Sudo"},"sudoer")," should be able to elevate it. An application that has full access and control of a system can modify it in harmful ways, e.g. compromise the private keys."),(0,r.kt)("p",null,"For our guide, we'll illustrate the process of migration from a super user (root) to another user (sudo). The knowledge should be easily appliable for any other user-to-user migration. We stick with root user for simplicity and because that's the most common use case."),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"A reference document about ",(0,r.kt)("a",{parentName:"p",href:"/references/Lightning%20CLI/file-permissions-and-ownership"},"File permissions and ownership")," is available that explains how it works practically, by showcasing how the process can be started, how the node process locates the Keystore, etc.")),(0,r.kt)("h2",{id:"systemd-service"},"Systemd Service"),(0,r.kt)("p",null,"In systemd, a unit refers to any resource that the system knows how to operate on and manage. This is the primary object that the systemd tools know how to deal with. These resources are defined using configuration files called unit files."),(0,r.kt)("p",null,"The recommended installation process features a ",(0,r.kt)("a",{parentName:"p",href:"https://www.freedesktop.org/software/systemd/man/systemd.service.html"},"systemd.service")," which is a resource that the system knows how to operate and manage by an administrator user."),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"When using a Systemd service to run a process, it operates comparably to running it directly. The key difference is that Systemd keeps track of all the processes and threads that are spawned. This means that when a service is stopped using systemctl, such as the Fleek Network Lightning Node service, all the child processes that were started by the service are also terminated. Additionally, by utilizing Systemd, a user can run the process in the background and configure it to start automatically on system startup.")),(0,r.kt)("p",null,"If you have followed the installation recommendations, find the systemd service unit in the location ",(0,r.kt)("inlineCode",{parentName:"p"},"/etc/systemd/system/lightning.service")," (we are using Ubuntu Linux as an example to keep it short)."),(0,r.kt)("p",null,"Make sure that you have set up a ",(0,r.kt)("a",{parentName:"p",href:"/docs/node/install#systemd-service-setup"},"Systemd unit service"),", as recommended during the installation as this guide assumes you have one setup."),(0,r.kt)("h2",{id:"stop-the-service"},"Stop the service"),(0,r.kt)("p",null,"Before we proceed with any changes required for the migration, you'll have to stop the ",(0,r.kt)("inlineCode",{parentName:"p"},"lightning.service"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl stop lightning\n")),(0,r.kt)("admonition",{type:"note"},(0,r.kt)("p",{parentName:"admonition"},"For this guide, we are assuming that you are migrating ownership from ",(0,r.kt)("strong",{parentName:"p"},"root")," to a ",(0,r.kt)("strong",{parentName:"p"},"sudoer")," user. If not, you might be required to elevate privileges as ",(0,r.kt)("strong",{parentName:"p"},"sudo**")," where required. For example, ",(0,r.kt)("inlineCode",{parentName:"p"},"sudo systemctl stop lightning"),".")),(0,r.kt)("h2",{id:"clear-the-lightning-data"},"Clear the .lightning data"),(0,r.kt)("p",null,"Run the following command to clear the ",(0,r.kt)("inlineCode",{parentName:"p"},"/root/.lightning/data"),", as it can be quite large and we don't need to move it."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo rm -rf /root/.lightning/data\n")),(0,r.kt)("h2",{id:"create-a-user"},"Create a user"),(0,r.kt)(i.ZP,{mdxType:"CreateAUser"}),(0,r.kt)("h2",{id:"move-lightning-system-and-source-code-directory-to-users-home"},"Move lightning system and source code directory to user's home"),(0,r.kt)("p",null,"A user should've been created, added the user to the sudo group, switched to the user, and changed the directory to the user's home."),(0,r.kt)("p",null,"Run the command ",(0,r.kt)("inlineCode",{parentName:"p"},"pwd"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"pwd\n")),(0,r.kt)("p",null,"The output would look like:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"/home/\n")),(0,r.kt)("p",null,"Given the username ",(0,r.kt)("strong",{parentName:"p"},"lgtn"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"/home/lgtn\n")),(0,r.kt)("p",null,"You'll then move two directories:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"The ",(0,r.kt)("inlineCode",{parentName:"li"},"/root/.lightning")),(0,r.kt)("li",{parentName:"ul"},"The source code under the parent ",(0,r.kt)("inlineCode",{parentName:"li"},"/root/fleek-network"))),(0,r.kt)("h3",{id:"1-move-the-rootlightning-directory-from-one-user-to-the-other"},"1) Move the ",(0,r.kt)("inlineCode",{parentName:"h3"},"/root/.lightning")," directory from one user to the other"),(0,r.kt)("p",null,"For our demo, we have assumed ",(0,r.kt)("strong",{parentName:"p"},"root")," user to ",(0,r.kt)("strong",{parentName:"p"},"sudoer")," user named ",(0,r.kt)("strong",{parentName:"p"},"lgtn"),", thus that'll look like this:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo mv /root/.lightning /home/lgtn/\n")),(0,r.kt)("h3",{id:"2-move-the-rootfleek-network-directory-from-one-user-to-the-other"},"2) Move the ",(0,r.kt)("inlineCode",{parentName:"h3"},"/root/fleek-network")," directory from one user to the other"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo mv /root/fleek-network /home/lgtn/\n")),(0,r.kt)("h3",{id:"3-confirm-move-by-finding-both-directories"},"3) Confirm move by finding both directories"),(0,r.kt)("p",null,"In the user $HOME directory, you should be able to list the content of the directory and find the ",(0,r.kt)("inlineCode",{parentName:"p"},".lightning")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"fleek-network")," directory."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"ls -la\n")),(0,r.kt)("p",null,"The output should be similar to the following."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"drwxr-x--- 6 lgtn lgtn 4096 Sep 12 13:51 .\ndrwxr-xr-x 3 root root 4096 Sep 11 12:28 ..\ndrwxrwxr-x 5 root root 4096 Sep 11 15:25 .lightning\ndrwxrwxr-x 3 root root 4096 Sep 11 12:28 fleek-network\n")),(0,r.kt)("h2",{id:"change-ownership-of-files"},"Change ownership of files"),(0,r.kt)("p",null,"Once the directories and files are moved, they should have have the wrong ownership, which should be set to ",(0,r.kt)("strong",{parentName:"p"},"root:root"),". We'll now have to change the ownership of the directories and files recursively."),(0,r.kt)("p",null,"Change the ownership of ",(0,r.kt)("inlineCode",{parentName:"p"},"/home/lgtn/.lightning")," to the user ",(0,r.kt)("strong",{parentName:"p"},"lgtn")," as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo chown -R lgtn:lgtn .lightning\n")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Make sure that you use the ",(0,r.kt)("inlineCode",{parentName:"p"},"-R")," flag to have the ownership changes applied to the parent, the child directories and all the files.")),(0,r.kt)("p",null,"Change the ownership of ",(0,r.kt)("inlineCode",{parentName:"p"},"/home/lgtn/fleek-network")," to the user ",(0,r.kt)("strong",{parentName:"p"},"lgtn")," as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo chown -R lgtn:lgtn fleek-network\n")),(0,r.kt)("p",null,"Once completed, if you list the content of the directory the ownership should have changed from ",(0,r.kt)("inlineCode",{parentName:"p"},"root:root")," to ",(0,r.kt)("inlineCode",{parentName:"p"},"lgtn:lgtn"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"ls -la\n")),(0,r.kt)("p",null,"The output should be similar to the following."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"drwxr-x--- 6 lgtn lgtn 4096 Sep 12 13:51 .\ndrwxr-xr-x 3 root root 4096 Sep 11 12:28 ..\ndrwxrwxr-x 5 lgtn lgtn 4096 Sep 11 15:25 .lightning\ndrwxrwxr-x 3 lgtn lgtn 4096 Sep 11 12:28 fleek-network\n")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Remember that we are using ",(0,r.kt)("strong",{parentName:"p"},"lgtn")," for our demo. If you have opted for a different username, make sure you use the correct username. To find the username you are logged in with run the command:"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"whoami\n")),(0,r.kt)("p",{parentName:"admonition"},"For our demo, we'll assume that you understand that ",(0,r.kt)("strong",{parentName:"p"},"lgtn")," is the user we opted in for our demo.")),(0,r.kt)("h2",{id:"the-lgtn-symbolic-link-symlink"},"The lgtn symbolic link (symlink)"),(0,r.kt)("p",null,"We have the symbolic link that links the binary built from the source code, to the alias ",(0,r.kt)("strong",{parentName:"p"},"lgtn")," that's set under the ",(0,r.kt)("inlineCode",{parentName:"p"},"/usr/local/bin/lgtn")," pathname."),(0,r.kt)("p",null,"For example, you can find where that is linked to by running:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"ls -la $(which lgtn)\n")),(0,r.kt)("p",null,"On the output below, we can see that the ",(0,r.kt)("inlineCode",{parentName:"p"},"/usr/local/bin/lgtn")," points to ",(0,r.kt)("inlineCode",{parentName:"p"},"/root/fleek-network/lightning/target/release/lightning-node"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"lrwxrwxrwx 1 root root 64 Sep 11 15:48 /usr/local/bin/lgtn -> /root/fleek-network/lightning/target/release/lightning-node\n")),(0,r.kt)("p",null,"The target base path is ",(0,r.kt)("inlineCode",{parentName:"p"},"/root")," and we know that we've moved the source code directory to the user home ",(0,r.kt)("inlineCode",{parentName:"p"},"/home/lgtn"),". For this reason, we need to create a new symlink with the updated location of the binary file."),(0,r.kt)("p",null,"Unlink the symlink:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo unlink /usr/local/bin/lgtn\n")),(0,r.kt)("p",null,"Create the symlink:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},'sudo ln -s "/home/lgtn/fleek-network/lightning/target/release/lightning-node" /usr/local/bin/lgtn\n')),(0,r.kt)("p",null,"If successful, you should be able to execute the command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn help\n")),(0,r.kt)("p",null,"The output should look similar to:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"Usage: lgtn [OPTIONS] \n\nCommands:\n run Start the node\n keys Handle keys\n print-config Print the loaded configuration\n help Print this message or the help of the given subcommand(s)\n\nOptions:\n -c, --config Path to the toml configuration file [default: ~/.lightning/config.toml]\n --with-mock-consensus Determines that we should be using the mock consensus backend\n -v... Increases the level of verbosity (the max level is -vvv)\n --log-location Print code location on console logs\n -h, --help Print help\n -V, --version Print version\n")),(0,r.kt)("h2",{id:"update-the-systemd-service-unit"},"Update the Systemd service unit"),(0,r.kt)("p",null,"Open the file, its settings should be similar to the following:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"[Unit]\nDescription=Fleek Network Node lightning service\n\n[Service]\nType=simple\nMemoryHigh=32G\nRestartSec=15s\nRestart=always\nExecStart=lgtn -c /home//.lightning/config.toml run\nStandardOutput=append:/var/log/lightning/output.log\nStandardError=append:/var/log/lightning/diagnostic.log\nEnvironment=TMPDIR=/var/tmp\n\n[Install]\nWantedBy=multi-user.target\n")),(0,r.kt)("p",null,"Since we opted in for the username ",(0,r.kt)("strong",{parentName:"p"},"lgtn")," for our demo, replaced ",(0,r.kt)("inlineCode",{parentName:"p"},"")," with ",(0,r.kt)("inlineCode",{parentName:"p"},"lgtn")," and it would look like:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"[Unit]\nDescription=Fleek Network Node lightning service\n\n[Service]\nType=simple\nMemoryHigh=32G\nRestartSec=15s\nRestart=always\nExecStart=lgtn -c /home/lgtn/.lightning/config.toml run\nStandardOutput=append:/var/log/lightning/output.log\nStandardError=append:/var/log/lightning/diagnostic.log\nEnvironment=TMPDIR=/var/tmp\n\n[Install]\nWantedBy=multi-user.target\n")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Notice the ",(0,r.kt)("inlineCode",{parentName:"p"},"ExecStart=")," which includes the flag ",(0,r.kt)("inlineCode",{parentName:"p"},"-c")," where the location of the user files is declared. Learn how to ",(0,r.kt)("a",{parentName:"p",href:"#update-the-configtoml-with-user-preferred-file-locations"},"update the config.toml")," to include the user-preferred file paths, e.g. declare the keystore pathname.")),(0,r.kt)("p",null,"Complete the step by reloading the daemon, to apply the newly created changes. You can do this by executing:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl daemon-reload\n")),(0,r.kt)("h2",{id:"update-the-configtoml-with-user-preferred-file-locations"},"Update the config.toml with user-preferred file locations"),(0,r.kt)("p",null,"Open the ",(0,r.kt)("inlineCode",{parentName:"p"},"/home/lgtn/.lightning/config.toml")," file in your favorite text editor."),(0,r.kt)("p",null,"Replace every instance of ",(0,r.kt)("inlineCode",{parentName:"p"},"~")," (tilde) with the user's home path. We do this to ensure that every time we control the service via systemctl, the configuration file that tells which keystore to use is declared upfront regardless of running it as user or delegating to root with ",(0,r.kt)("strong",{parentName:"p"},"sudo"),". Learn more about ",(0,r.kt)("a",{parentName:"p",href:"/references/Lightning%20CLI/file-permissions-and-ownership"},"file permissions and ownership")," by reading the reference document."),(0,r.kt)(s.ZP,{mdxType:"FindAndReplaceConfigWithUserPaths"}),(0,r.kt)("h2",{id:"start-the-service"},"Start the service"),(0,r.kt)("p",null,"At this stage, you should have migrated the essential files to the user home."),(0,r.kt)("p",null,"Ideally, you would now manage the service as the ",(0,r.kt)("inlineCode",{parentName:"p"},"user")," (as described in the ",(0,r.kt)("a",{parentName:"p",href:"/references/Systemd/user-service/"},"user service reference"),"). To keep our guide wider to all users, we'll prefix the commands with ",(0,r.kt)("strong",{parentName:"p"},"sudo"),", which elevates the permissions to ",(0,r.kt)("strong",{parentName:"p"},"root"),". But since we have provided the configuration file the ",(0,r.kt)("inlineCode",{parentName:"p"},"-c")," in our ",(0,r.kt)("a",{parentName:"p",href:"#systemd-service"},"systemd service"),", we'll have the user-preferred configuration options ruling. "),(0,r.kt)("p",null,"Start the service by running the command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl start lightning.service\n")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Find the timeline of events for the Lightning service by checking the log files. Learn about it in the section ",(0,r.kt)("a",{parentName:"p",href:"/docs/node/install#analyzing-log-messages"},"Log Messages"),".")),(0,r.kt)("p",null,"To learn more, visit the section ",(0,r.kt)("a",{parentName:"p",href:"/docs/node/install#use-systemctl-to-manage-systemd-service"},"Use Systemctl to manage the Lightning Service")),(0,r.kt)("h2",{id:"conclusion"},"Conclusion"),(0,r.kt)("p",null,"We started by giving a brief introduction to ownership of the Lightning CLI files."),(0,r.kt)("p",null,"Jumped through topics of Systemd service that helps the user manage the service in the Linux environment, which helps keep keeps track of all the processes and threads that are spawned."),(0,r.kt)("p",null,"We've gone through the step-by-step process to migrate the Fleek Network CLI and Systemd service setup from one user to the other. To keep it short, we decided to go with the use-case of where the migration happens between a ",(0,r.kt)("strong",{parentName:"p"},"root")," user and a ",(0,r.kt)("strong",{parentName:"p"},"sudoer"),"."),(0,r.kt)("p",null,"Discover more about the project by ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/lightning"},"watching/contributing on GitHub"),", following us on ",(0,r.kt)("a",{parentName:"p",href:"https://twitter.com/fleek_net"},"Twitter"),", and joining ",(0,r.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"our community Discord")," for any updates."),(0,r.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}g.isMDXComponent=!0},6733:(e,t,n)=>{n.d(t,{ZP:()=>s});var o=n(7462),r=(n(7294),n(3905));const a={toc:[]},i="wrapper";function s(e){let{components:t,...n}=e;return(0,r.kt)(i,(0,o.Z)({},a,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"We recommend creating a ",(0,r.kt)("inlineCode",{parentName:"p"},"non-root")," user with administrative privileges. It'll allow us to install any system requirements."),(0,r.kt)("p",null,"You can create a new user and add to the ",(0,r.kt)("strong",{parentName:"p"},"sudo")," group by running:"),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"For our example, we'll be using the name ",(0,r.kt)("inlineCode",{parentName:"p"},"lgtn")," but you can pick whichever you'd like. If you already have a ",(0,r.kt)("strong",{parentName:"p"},"sudoer")," account, you can skip this step.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"adduser lgtn\n")),(0,r.kt)("p",null,"After completing the ",(0,r.kt)("inlineCode",{parentName:"p"},"adduser")," steps, execute the ",(0,r.kt)("inlineCode",{parentName:"p"},"usermod")," to add the ",(0,r.kt)("inlineCode",{parentName:"p"},"user")," to the ",(0,r.kt)("strong",{parentName:"p"},"sudo")," group, as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"usermod -aG sudo lgtn\n")),(0,r.kt)("p",null,"Switch to the new ",(0,r.kt)("strong",{parentName:"p"},"user")," by using the command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"su lgtn\n")),(0,r.kt)("p",null,"Change the directory to the new user's home, as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"cd /home/lgtn\n")))}s.isMDXComponent=!0},3242:(e,t,n)=>{n.d(t,{ZP:()=>s});var o=n(7462),r=(n(7294),n(3905));const a={toc:[]},i="wrapper";function s(e){let{components:t,...n}=e;return(0,r.kt)(i,(0,o.Z)({},a,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"In the ",(0,r.kt)("inlineCode",{parentName:"p"},"/home//.lightning/config.toml")," you'll find some and more of the following:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n')),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"The configuration properties and values presented above are a shorter version of what you'll find on your ",(0,r.kt)("strong",{parentName:"p"},"configuration.toml"),". We keep it short to make it easier to follow, do not copy and paste.")),(0,r.kt)("p",null,"Find and replace all instances of ~ in the config file ",(0,r.kt)("inlineCode",{parentName:"p"},"/home//.lightning/config.toml"),". "),(0,r.kt)("p",null,"Here's an example of how to do it using ",(0,r.kt)("strong",{parentName:"p"},"sed"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},'sed -i "s|~/.lightning|/home//.lightning|g" "/home//.lightning/config.toml"\n')),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Replace the ",(0,r.kt)("inlineCode",{parentName:"p"},"")," with your username. For example, if you have followed the recommendation to ",(0,r.kt)("a",{parentName:"p",href:"/docs/node/install#create-a-user"},"create a user")," it would look like ",(0,r.kt)("inlineCode",{parentName:"p"},"/home/lgtn/.lightning/config.toml")," for the username ",(0,r.kt)("strong",{parentName:"p"},"lgtn"),".")),(0,r.kt)("p",null,"For example, if your username is ",(0,r.kt)("inlineCode",{parentName:"p"},"lgtn")," that'd look like this:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},'sed -i "s|~/.lightning|/home/lgtn/.lightning|g" "/home/lgtn/.lightning/config.toml"\n')),(0,r.kt)("p",null,"Once modified, you can run a ",(0,r.kt)("inlineCode",{parentName:"p"},"cat")," to see the content of the files to confirm it has been updated."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"cat /home/lgtn/.lightning/config.toml\n")),(0,r.kt)("p",null,"For our example where we opted in for the username ",(0,r.kt)("inlineCode",{parentName:"p"},"lgtn")," that would look like:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n')),(0,r.kt)("admonition",{title:"Warning",type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"Bear in mind that we are keeping the content of the file short to make it easier to read and follow. The content of your configuration file should look slightly different, amongst these it should contain other properties and values. You should not copy and replace the content of your files with the ones presented here.")))}s.isMDXComponent=!0},2915:(e,t,n)=>{n.d(t,{ZP:()=>s});var o=n(7462),r=(n(7294),n(3905));const a={toc:[]},i="wrapper";function s(e){let{components:t,...n}=e;return(0,r.kt)(i,(0,o.Z)({},a,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"You have several ways of doing this:"),(0,r.kt)("ul",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ul"},"Clone via HTTPS"),(0,r.kt)("li",{parentName:"ul"},"Clone via SSH"),(0,r.kt)("li",{parentName:"ul"},"Download via Github CLI"),(0,r.kt)("li",{parentName:"ul"},"Download the ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/fleek-network/lightning/archive/refs/heads/main.zip"},"zip package")," from the repository")),(0,r.kt)("p",{parentName:"admonition"},"We recommend HTTPS because it is the easiest to set up in the wild, and by users who are new to all this.\nAlthough, we strongly recommend using an SSH connection when interacting with GitHub. If you are to this and are interested read more about it ",(0,r.kt)("a",{parentName:"p",href:"https://docs.github.com/en/authentication/connecting-to-github-with-ssh"},"here"),"."),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"git clone -b testnet-alpha-0 https://github.com/fleek-network/lightning.git \n")),(0,r.kt)("p",{parentName:"admonition"},"Here's an example of what it'd look like when sticking to the recommended path location:"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"git clone -b testnet-alpha-0 https://github.com/fleek-network/lightning.git ~/fleek-network/lightning\n"))))}s.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>r});var o=n(7294);const r=e=>{let{image:t,name:n,title:r,url:a,communityMember:i=!1}=e;return o.createElement("section",{className:"author_card"},o.createElement("div",null,o.createElement("span",{className:"avatar"},o.createElement("a",{href:a,target:"_blank",alt:n},o.createElement("img",{src:t,alt:n}))),o.createElement("div",null,o.createElement("span",{className:"name"},o.createElement("a",{href:a,target:"_blank",alt:n},n)),o.createElement("span",{className:"title"},r),o.createElement("span",{className:"discord"},i?"Join our community on":"Got questions? Find us on"," ",o.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[9854],{3905:(e,t,n)=>{n.d(t,{Zo:()=>h,kt:()=>c});var o=n(7294);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,o)}return n}function i(e){for(var t=1;t=0||(r[n]=e[n]);return r}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(r[n]=e[n])}return r}var l=o.createContext({}),p=function(e){var t=o.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},h=function(e){var t=p(e.components);return o.createElement(l.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},m=o.forwardRef((function(e,t){var n=e.components,r=e.mdxType,a=e.originalType,l=e.parentName,h=s(e,["components","mdxType","originalType","parentName"]),d=p(n),m=r,c=d["".concat(l,".").concat(m)]||d[m]||u[m]||a;return n?o.createElement(c,i(i({ref:t},h),{},{components:n})):o.createElement(c,i({ref:t},h))}));function c(e,t){var n=arguments,r=t&&t.mdxType;if("string"==typeof e||r){var a=n.length,i=new Array(a);i[0]=m;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:r,i[1]=s;for(var p=2;p{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>p,default:()=>g,frontMatter:()=>l,metadata:()=>h,toc:()=>u});var o=n(7462),r=(n(7294),n(3905)),a=n(3872),i=(n(2915),n(6733)),s=n(3242);const l={template:"post",draft:!1,hide_title:!0,title:"Transfering setup ownership",slug:"transfering-setup-ownership",date:new Date("2023-09-12T23:00:00.000Z"),description:"A step-by-step guide to transfer the ownership of the Fleek Network Lightning CLI and service setup",category:"Tutorial",tags:["transfer","ownership","guide","setup","configuration"]},p=void 0,h={unversionedId:"Node Operators/transfering-setup-ownership",id:"Node Operators/transfering-setup-ownership",title:"Transfering setup ownership",description:"A step-by-step guide to transfer the ownership of the Fleek Network Lightning CLI and service setup",source:"@site/guides/Node Operators/transfering-setup-ownership.md",sourceDirName:"Node Operators",slug:"/Node Operators/transfering-setup-ownership",permalink:"/guides/Node Operators/transfering-setup-ownership",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/guides/Node Operators/transfering-setup-ownership.md",tags:[{label:"transfer",permalink:"/guides/tags/transfer"},{label:"ownership",permalink:"/guides/tags/ownership"},{label:"guide",permalink:"/guides/tags/guide"},{label:"setup",permalink:"/guides/tags/setup"},{label:"configuration",permalink:"/guides/tags/configuration"}],version:"current",lastUpdatedAt:1694785242,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{template:"post",draft:!1,hide_title:!0,title:"Transfering setup ownership",slug:"transfering-setup-ownership",date:"2023-09-12T23:00:00.000Z",description:"A step-by-step guide to transfer the ownership of the Fleek Network Lightning CLI and service setup",category:"Tutorial",tags:["transfer","ownership","guide","setup","configuration"]},sidebar:"defaultSidebar",previous:{title:"Managing the keystore",permalink:"/guides/Node Operators/managing-the-keystore"}},d={},u=[{value:"TL;DR",id:"tldr",level:2},{value:"Introduction",id:"introduction",level:2},{value:"Pre-requisites",id:"pre-requisites",level:2},{value:"Ownership of Lightning CLI files",id:"ownership-of-lightning-cli-files",level:2},{value:"Systemd Service",id:"systemd-service",level:2},{value:"Stop the service",id:"stop-the-service",level:2},{value:"Clear the .lightning data",id:"clear-the-lightning-data",level:2},{value:"Create a user",id:"create-a-user",level:2},{value:"Move lightning system and source code directory to user's home",id:"move-lightning-system-and-source-code-directory-to-users-home",level:2},{value:"1) Move the /root/.lightning directory from one user to the other",id:"1-move-the-rootlightning-directory-from-one-user-to-the-other",level:3},{value:"2) Move the /root/fleek-network directory from one user to the other",id:"2-move-the-rootfleek-network-directory-from-one-user-to-the-other",level:3},{value:"3) Confirm move by finding both directories",id:"3-confirm-move-by-finding-both-directories",level:3},{value:"Change ownership of files",id:"change-ownership-of-files",level:2},{value:"The lgtn symbolic link (symlink)",id:"the-lgtn-symbolic-link-symlink",level:2},{value:"Update the Systemd service unit",id:"update-the-systemd-service-unit",level:2},{value:"Update the config.toml with user-preferred file locations",id:"update-the-configtoml-with-user-preferred-file-locations",level:2},{value:"Start the service",id:"start-the-service",level:2},{value:"Conclusion",id:"conclusion",level:2}],m={toc:u},c="wrapper";function g(e){let{components:t,...n}=e;return(0,r.kt)(c,(0,o.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("h2",{id:"tldr"},"TL;DR"),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"The step-by-step instructions provided in the guide should be simple to follow, but the process is also available as an automated script from our familiar ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/get.fleek.network"},"get.fleek.network")," tool."),(0,r.kt)("p",{parentName:"admonition"},"To use the automated script execute the following command in your server terminal and follow the instructions:"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"curl -sS https://get.fleek.network/transfer_system_user_setup_ownership | bash\n")),(0,r.kt)("p",{parentName:"admonition"},"We try to make the auomated scripts as useful as possible, but it's impossible to fit every single use-case. So, if you find any isses or have feedback to help us improve ",(0,r.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"message us through our Discord"),".")),(0,r.kt)("h2",{id:"introduction"},"Introduction"),(0,r.kt)("p",null,"Our Lightning CLI and Node process is run by a user, that has some sort of permissions\u2013some users run it as a super user (root) which is questionable as root privileges are not a necessary good. We'll look into how to create a user to manage and control the Fleek Network Lightning CLI and Systemd unit service. Also, presents the concept of file permissions and ownership which is crucial in preventing private or sensitive data from being exposed to dodgy actors."),(0,r.kt)("p",null,"Let's discuss the topic and open up a few ideas to help us improve the security of our server."),(0,r.kt)("h2",{id:"pre-requisites"},"Pre-requisites"),(0,r.kt)("p",null,"To follow the guide, you will need the following:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"Familiarity with the command-line interface"),(0,r.kt)("li",{parentName:"ul"},"Have installed and set up the Lightning CLI and service")),(0,r.kt)("h2",{id:"ownership-of-lightning-cli-files"},"Ownership of Lightning CLI files"),(0,r.kt)("p",null,"The user who installs the Lightning CLI and sets the Service takes an important role that determines the location of the configuration files, the setup, and how the Systemd service is managed or controlled."),(0,r.kt)("p",null,"Our ",(0,r.kt)("a",{parentName:"p",href:"/docs/node/install"},"install")," document recommends creating a user and switching to the user to set up the service. You shouldn't want installed applications to run with elevated privileges. Applications are meant to be run with non-administrative privileges. If an application requires higher privileges, the administrator, such as a ",(0,r.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Sudo"},"sudoer")," should be able to elevate it. An application that has full access and control of a system can modify it in harmful ways, e.g. compromise the private keys."),(0,r.kt)("p",null,"For our guide, we'll illustrate the process of migration from a super user (root) to another user (sudo). The knowledge should be easily appliable for any other user-to-user migration. We stick with root user for simplicity and because that's the most common use case."),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"A reference document about ",(0,r.kt)("a",{parentName:"p",href:"/references/Lightning%20CLI/file-permissions-and-ownership"},"File permissions and ownership")," is available that explains how it works practically, by showcasing how the process can be started, how the node process locates the Keystore, etc.")),(0,r.kt)("h2",{id:"systemd-service"},"Systemd Service"),(0,r.kt)("p",null,"In systemd, a unit refers to any resource that the system knows how to operate on and manage. This is the primary object that the systemd tools know how to deal with. These resources are defined using configuration files called unit files."),(0,r.kt)("p",null,"The recommended installation process features a ",(0,r.kt)("a",{parentName:"p",href:"https://www.freedesktop.org/software/systemd/man/systemd.service.html"},"systemd.service")," which is a resource that the system knows how to operate and manage by an administrator user."),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"When using a Systemd service to run a process, it operates comparably to running it directly. The key difference is that Systemd keeps track of all the processes and threads that are spawned. This means that when a service is stopped using systemctl, such as the Fleek Network Lightning Node service, all the child processes that were started by the service are also terminated. Additionally, by utilizing Systemd, a user can run the process in the background and configure it to start automatically on system startup.")),(0,r.kt)("p",null,"If you have followed the installation recommendations, find the systemd service unit in the location ",(0,r.kt)("inlineCode",{parentName:"p"},"/etc/systemd/system/lightning.service")," (we are using Ubuntu Linux as an example to keep it short)."),(0,r.kt)("p",null,"Make sure that you have set up a ",(0,r.kt)("a",{parentName:"p",href:"/docs/node/install#systemd-service-setup"},"Systemd unit service"),", as recommended during the installation as this guide assumes you have one setup."),(0,r.kt)("h2",{id:"stop-the-service"},"Stop the service"),(0,r.kt)("p",null,"Before we proceed with any changes required for the migration, you'll have to stop the ",(0,r.kt)("inlineCode",{parentName:"p"},"lightning.service"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl stop lightning\n")),(0,r.kt)("admonition",{type:"note"},(0,r.kt)("p",{parentName:"admonition"},"For this guide, we are assuming that you are migrating ownership from ",(0,r.kt)("strong",{parentName:"p"},"root")," to a ",(0,r.kt)("strong",{parentName:"p"},"sudoer")," user. If not, you might be required to elevate privileges as ",(0,r.kt)("strong",{parentName:"p"},"sudo**")," where required. For example, ",(0,r.kt)("inlineCode",{parentName:"p"},"sudo systemctl stop lightning"),".")),(0,r.kt)("h2",{id:"clear-the-lightning-data"},"Clear the .lightning data"),(0,r.kt)("p",null,"Run the following command to clear the ",(0,r.kt)("inlineCode",{parentName:"p"},"/root/.lightning/data"),", as it can be quite large and we don't need to move it."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo rm -rf /root/.lightning/data\n")),(0,r.kt)("h2",{id:"create-a-user"},"Create a user"),(0,r.kt)(i.ZP,{mdxType:"CreateAUser"}),(0,r.kt)("h2",{id:"move-lightning-system-and-source-code-directory-to-users-home"},"Move lightning system and source code directory to user's home"),(0,r.kt)("p",null,"A user should've been created, added the user to the sudo group, switched to the user, and changed the directory to the user's home."),(0,r.kt)("p",null,"Run the command ",(0,r.kt)("inlineCode",{parentName:"p"},"pwd"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"pwd\n")),(0,r.kt)("p",null,"The output would look like:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"/home/\n")),(0,r.kt)("p",null,"Given the username ",(0,r.kt)("strong",{parentName:"p"},"lgtn"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"/home/lgtn\n")),(0,r.kt)("p",null,"You'll then move two directories:"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"The ",(0,r.kt)("inlineCode",{parentName:"li"},"/root/.lightning")),(0,r.kt)("li",{parentName:"ul"},"The source code under the parent ",(0,r.kt)("inlineCode",{parentName:"li"},"/root/fleek-network"))),(0,r.kt)("h3",{id:"1-move-the-rootlightning-directory-from-one-user-to-the-other"},"1) Move the ",(0,r.kt)("inlineCode",{parentName:"h3"},"/root/.lightning")," directory from one user to the other"),(0,r.kt)("p",null,"For our demo, we have assumed ",(0,r.kt)("strong",{parentName:"p"},"root")," user to ",(0,r.kt)("strong",{parentName:"p"},"sudoer")," user named ",(0,r.kt)("strong",{parentName:"p"},"lgtn"),", thus that'll look like this:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo mv /root/.lightning /home/lgtn/\n")),(0,r.kt)("h3",{id:"2-move-the-rootfleek-network-directory-from-one-user-to-the-other"},"2) Move the ",(0,r.kt)("inlineCode",{parentName:"h3"},"/root/fleek-network")," directory from one user to the other"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo mv /root/fleek-network /home/lgtn/\n")),(0,r.kt)("h3",{id:"3-confirm-move-by-finding-both-directories"},"3) Confirm move by finding both directories"),(0,r.kt)("p",null,"In the user $HOME directory, you should be able to list the content of the directory and find the ",(0,r.kt)("inlineCode",{parentName:"p"},".lightning")," and ",(0,r.kt)("inlineCode",{parentName:"p"},"fleek-network")," directory."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"ls -la\n")),(0,r.kt)("p",null,"The output should be similar to the following."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"drwxr-x--- 6 lgtn lgtn 4096 Sep 12 13:51 .\ndrwxr-xr-x 3 root root 4096 Sep 11 12:28 ..\ndrwxrwxr-x 5 root root 4096 Sep 11 15:25 .lightning\ndrwxrwxr-x 3 root root 4096 Sep 11 12:28 fleek-network\n")),(0,r.kt)("h2",{id:"change-ownership-of-files"},"Change ownership of files"),(0,r.kt)("p",null,"Once the directories and files are moved, they should have have the wrong ownership, which should be set to ",(0,r.kt)("strong",{parentName:"p"},"root:root"),". We'll now have to change the ownership of the directories and files recursively."),(0,r.kt)("p",null,"Change the ownership of ",(0,r.kt)("inlineCode",{parentName:"p"},"/home/lgtn/.lightning")," to the user ",(0,r.kt)("strong",{parentName:"p"},"lgtn")," as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo chown -R lgtn:lgtn .lightning\n")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Make sure that you use the ",(0,r.kt)("inlineCode",{parentName:"p"},"-R")," flag to have the ownership changes applied to the parent, the child directories and all the files.")),(0,r.kt)("p",null,"Change the ownership of ",(0,r.kt)("inlineCode",{parentName:"p"},"/home/lgtn/fleek-network")," to the user ",(0,r.kt)("strong",{parentName:"p"},"lgtn")," as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo chown -R lgtn:lgtn fleek-network\n")),(0,r.kt)("p",null,"Once completed, if you list the content of the directory the ownership should have changed from ",(0,r.kt)("inlineCode",{parentName:"p"},"root:root")," to ",(0,r.kt)("inlineCode",{parentName:"p"},"lgtn:lgtn"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"ls -la\n")),(0,r.kt)("p",null,"The output should be similar to the following."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"drwxr-x--- 6 lgtn lgtn 4096 Sep 12 13:51 .\ndrwxr-xr-x 3 root root 4096 Sep 11 12:28 ..\ndrwxrwxr-x 5 lgtn lgtn 4096 Sep 11 15:25 .lightning\ndrwxrwxr-x 3 lgtn lgtn 4096 Sep 11 12:28 fleek-network\n")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Remember that we are using ",(0,r.kt)("strong",{parentName:"p"},"lgtn")," for our demo. If you have opted for a different username, make sure you use the correct username. To find the username you are logged in with run the command:"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"whoami\n")),(0,r.kt)("p",{parentName:"admonition"},"For our demo, we'll assume that you understand that ",(0,r.kt)("strong",{parentName:"p"},"lgtn")," is the user we opted in for our demo.")),(0,r.kt)("h2",{id:"the-lgtn-symbolic-link-symlink"},"The lgtn symbolic link (symlink)"),(0,r.kt)("p",null,"We have the symbolic link that links the binary built from the source code, to the alias ",(0,r.kt)("strong",{parentName:"p"},"lgtn")," that's set under the ",(0,r.kt)("inlineCode",{parentName:"p"},"/usr/local/bin/lgtn")," pathname."),(0,r.kt)("p",null,"For example, you can find where that is linked to by running:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"ls -la $(which lgtn)\n")),(0,r.kt)("p",null,"On the output below, we can see that the ",(0,r.kt)("inlineCode",{parentName:"p"},"/usr/local/bin/lgtn")," points to ",(0,r.kt)("inlineCode",{parentName:"p"},"/root/fleek-network/lightning/target/release/lightning-node"),"."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"lrwxrwxrwx 1 root root 64 Sep 11 15:48 /usr/local/bin/lgtn -> /root/fleek-network/lightning/target/release/lightning-node\n")),(0,r.kt)("p",null,"The target base path is ",(0,r.kt)("inlineCode",{parentName:"p"},"/root")," and we know that we've moved the source code directory to the user home ",(0,r.kt)("inlineCode",{parentName:"p"},"/home/lgtn"),". For this reason, we need to create a new symlink with the updated location of the binary file."),(0,r.kt)("p",null,"Unlink the symlink:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo unlink /usr/local/bin/lgtn\n")),(0,r.kt)("p",null,"Create the symlink:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},'sudo ln -s "/home/lgtn/fleek-network/lightning/target/release/lightning-node" /usr/local/bin/lgtn\n')),(0,r.kt)("p",null,"If successful, you should be able to execute the command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn help\n")),(0,r.kt)("p",null,"The output should look similar to:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"Usage: lgtn [OPTIONS] \n\nCommands:\n run Start the node\n keys Handle keys\n print-config Print the loaded configuration\n help Print this message or the help of the given subcommand(s)\n\nOptions:\n -c, --config Path to the toml configuration file [default: ~/.lightning/config.toml]\n --with-mock-consensus Determines that we should be using the mock consensus backend\n -v... Increases the level of verbosity (the max level is -vvv)\n --log-location Print code location on console logs\n -h, --help Print help\n -V, --version Print version\n")),(0,r.kt)("h2",{id:"update-the-systemd-service-unit"},"Update the Systemd service unit"),(0,r.kt)("p",null,"Open the file, its settings should be similar to the following:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"[Unit]\nDescription=Fleek Network Node lightning service\n\n[Service]\nType=simple\nMemoryHigh=32G\nRestartSec=15s\nRestart=always\nExecStart=lgtn -c /home//.lightning/config.toml run\nStandardOutput=append:/var/log/lightning/output.log\nStandardError=append:/var/log/lightning/diagnostic.log\nEnvironment=TMPDIR=/var/tmp\n\n[Install]\nWantedBy=multi-user.target\n")),(0,r.kt)("p",null,"Since we opted in for the username ",(0,r.kt)("strong",{parentName:"p"},"lgtn")," for our demo, replaced ",(0,r.kt)("inlineCode",{parentName:"p"},"")," with ",(0,r.kt)("inlineCode",{parentName:"p"},"lgtn")," and it would look like:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"[Unit]\nDescription=Fleek Network Node lightning service\n\n[Service]\nType=simple\nMemoryHigh=32G\nRestartSec=15s\nRestart=always\nExecStart=lgtn -c /home/lgtn/.lightning/config.toml run\nStandardOutput=append:/var/log/lightning/output.log\nStandardError=append:/var/log/lightning/diagnostic.log\nEnvironment=TMPDIR=/var/tmp\n\n[Install]\nWantedBy=multi-user.target\n")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Notice the ",(0,r.kt)("inlineCode",{parentName:"p"},"ExecStart=")," which includes the flag ",(0,r.kt)("inlineCode",{parentName:"p"},"-c")," where the location of the user files is declared. Learn how to ",(0,r.kt)("a",{parentName:"p",href:"#update-the-configtoml-with-user-preferred-file-locations"},"update the config.toml")," to include the user-preferred file paths, e.g. declare the keystore pathname.")),(0,r.kt)("p",null,"Complete the step by reloading the daemon, to apply the newly created changes. You can do this by executing:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl daemon-reload\n")),(0,r.kt)("h2",{id:"update-the-configtoml-with-user-preferred-file-locations"},"Update the config.toml with user-preferred file locations"),(0,r.kt)("p",null,"Open the ",(0,r.kt)("inlineCode",{parentName:"p"},"/home/lgtn/.lightning/config.toml")," file in your favorite text editor."),(0,r.kt)("p",null,"Replace every instance of ",(0,r.kt)("inlineCode",{parentName:"p"},"~")," (tilde) with the user's home path. We do this to ensure that every time we control the service via systemctl, the configuration file that tells which keystore to use is declared upfront regardless of running it as user or delegating to root with ",(0,r.kt)("strong",{parentName:"p"},"sudo"),". Learn more about ",(0,r.kt)("a",{parentName:"p",href:"/references/Lightning%20CLI/file-permissions-and-ownership"},"file permissions and ownership")," by reading the reference document."),(0,r.kt)(s.ZP,{mdxType:"FindAndReplaceConfigWithUserPaths"}),(0,r.kt)("h2",{id:"start-the-service"},"Start the service"),(0,r.kt)("p",null,"At this stage, you should have migrated the essential files to the user home."),(0,r.kt)("p",null,"Ideally, you would now manage the service as the ",(0,r.kt)("inlineCode",{parentName:"p"},"user")," (as described in the ",(0,r.kt)("a",{parentName:"p",href:"/references/Systemd/user-service/"},"user service reference"),"). To keep our guide wider to all users, we'll prefix the commands with ",(0,r.kt)("strong",{parentName:"p"},"sudo"),", which elevates the permissions to ",(0,r.kt)("strong",{parentName:"p"},"root"),". But since we have provided the configuration file the ",(0,r.kt)("inlineCode",{parentName:"p"},"-c")," in our ",(0,r.kt)("a",{parentName:"p",href:"#systemd-service"},"systemd service"),", we'll have the user-preferred configuration options ruling. "),(0,r.kt)("p",null,"Start the service by running the command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl start lightning.service\n")),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Find the timeline of events for the Lightning service by checking the log files. Learn about it in the section ",(0,r.kt)("a",{parentName:"p",href:"/docs/node/install#analyzing-log-messages"},"Log Messages"),".")),(0,r.kt)("p",null,"To learn more, visit the section ",(0,r.kt)("a",{parentName:"p",href:"/docs/node/install#use-systemctl-to-manage-systemd-service"},"Use Systemctl to manage the Lightning Service")),(0,r.kt)("h2",{id:"conclusion"},"Conclusion"),(0,r.kt)("p",null,"We started by giving a brief introduction to ownership of the Lightning CLI files."),(0,r.kt)("p",null,"Jumped through topics of Systemd service that helps the user manage the service in the Linux environment, which helps keep keeps track of all the processes and threads that are spawned."),(0,r.kt)("p",null,"We've gone through the step-by-step process to migrate the Fleek Network CLI and Systemd service setup from one user to the other. To keep it short, we decided to go with the use-case of where the migration happens between a ",(0,r.kt)("strong",{parentName:"p"},"root")," user and a ",(0,r.kt)("strong",{parentName:"p"},"sudoer"),"."),(0,r.kt)("p",null,"Discover more about the project by ",(0,r.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/lightning"},"watching/contributing on GitHub"),", following us on ",(0,r.kt)("a",{parentName:"p",href:"https://twitter.com/fleek_net"},"Twitter"),", and joining ",(0,r.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"our community Discord")," for any updates."),(0,r.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}g.isMDXComponent=!0},6733:(e,t,n)=>{n.d(t,{ZP:()=>s});var o=n(7462),r=(n(7294),n(3905));const a={toc:[]},i="wrapper";function s(e){let{components:t,...n}=e;return(0,r.kt)(i,(0,o.Z)({},a,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"We recommend creating a ",(0,r.kt)("inlineCode",{parentName:"p"},"non-root")," user with administrative privileges. It'll allow us to install any system requirements."),(0,r.kt)("p",null,"You can create a new user and add to the ",(0,r.kt)("strong",{parentName:"p"},"sudo")," group by running:"),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"For our example, we'll be using the name ",(0,r.kt)("inlineCode",{parentName:"p"},"lgtn")," but you can pick whichever you'd like. If you already have a ",(0,r.kt)("strong",{parentName:"p"},"sudoer")," account, you can skip this step.")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"adduser lgtn\n")),(0,r.kt)("p",null,"After completing the ",(0,r.kt)("inlineCode",{parentName:"p"},"adduser")," steps, execute the ",(0,r.kt)("inlineCode",{parentName:"p"},"usermod")," to add the ",(0,r.kt)("inlineCode",{parentName:"p"},"user")," to the ",(0,r.kt)("strong",{parentName:"p"},"sudo")," group, as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"usermod -aG sudo lgtn\n")),(0,r.kt)("p",null,"Switch to the new ",(0,r.kt)("strong",{parentName:"p"},"user")," by using the command:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"su lgtn\n")),(0,r.kt)("p",null,"Change the directory to the new user's home, as follows:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"cd /home/lgtn\n")))}s.isMDXComponent=!0},3242:(e,t,n)=>{n.d(t,{ZP:()=>s});var o=n(7462),r=(n(7294),n(3905));const a={toc:[]},i="wrapper";function s(e){let{components:t,...n}=e;return(0,r.kt)(i,(0,o.Z)({},a,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"In the ",(0,r.kt)("inlineCode",{parentName:"p"},"/home//.lightning/config.toml")," you'll find some and more of the following:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n')),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"The configuration properties and values presented above are a shorter version of what you'll find on your ",(0,r.kt)("strong",{parentName:"p"},"configuration.toml"),". We keep it short to make it easier to follow, do not copy and paste.")),(0,r.kt)("p",null,"Find and replace all instances of ~ in the config file ",(0,r.kt)("inlineCode",{parentName:"p"},"/home//.lightning/config.toml"),". "),(0,r.kt)("p",null,"Here's an example of how to do it using ",(0,r.kt)("strong",{parentName:"p"},"sed"),":"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},'sed -i "s|~/.lightning|/home//.lightning|g" "/home//.lightning/config.toml"\n')),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"Replace the ",(0,r.kt)("inlineCode",{parentName:"p"},"")," with your username. For example, if you have followed the recommendation to ",(0,r.kt)("a",{parentName:"p",href:"/docs/node/install#create-a-user"},"create a user")," it would look like ",(0,r.kt)("inlineCode",{parentName:"p"},"/home/lgtn/.lightning/config.toml")," for the username ",(0,r.kt)("strong",{parentName:"p"},"lgtn"),".")),(0,r.kt)("p",null,"For example, if your username is ",(0,r.kt)("inlineCode",{parentName:"p"},"lgtn")," that'd look like this:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},'sed -i "s|~/.lightning|/home/lgtn/.lightning|g" "/home/lgtn/.lightning/config.toml"\n')),(0,r.kt)("p",null,"Once modified, you can run a ",(0,r.kt)("inlineCode",{parentName:"p"},"cat")," to see the content of the files to confirm it has been updated."),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"cat /home/lgtn/.lightning/config.toml\n")),(0,r.kt)("p",null,"For our example where we opted in for the username ",(0,r.kt)("inlineCode",{parentName:"p"},"lgtn")," that would look like:"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n')),(0,r.kt)("admonition",{title:"Warning",type:"caution"},(0,r.kt)("p",{parentName:"admonition"},"Bear in mind that we are keeping the content of the file short to make it easier to read and follow. The content of your configuration file should look slightly different, amongst these it should contain other properties and values. You should not copy and replace the content of your files with the ones presented here.")))}s.isMDXComponent=!0},2915:(e,t,n)=>{n.d(t,{ZP:()=>s});var o=n(7462),r=(n(7294),n(3905));const a={toc:[]},i="wrapper";function s(e){let{components:t,...n}=e;return(0,r.kt)(i,(0,o.Z)({},a,n,{components:t,mdxType:"MDXLayout"}),(0,r.kt)("admonition",{type:"tip"},(0,r.kt)("p",{parentName:"admonition"},"You have several ways of doing this:"),(0,r.kt)("ul",{parentName:"admonition"},(0,r.kt)("li",{parentName:"ul"},"Clone via HTTPS"),(0,r.kt)("li",{parentName:"ul"},"Clone via SSH"),(0,r.kt)("li",{parentName:"ul"},"Download via Github CLI"),(0,r.kt)("li",{parentName:"ul"},"Download the ",(0,r.kt)("a",{parentName:"li",href:"https://github.com/fleek-network/lightning/archive/refs/heads/main.zip"},"zip package")," from the repository")),(0,r.kt)("p",{parentName:"admonition"},"We recommend HTTPS because it is the easiest to set up in the wild, and by users who are new to all this.\nAlthough, we strongly recommend using an SSH connection when interacting with GitHub. If you are to this and are interested read more about it ",(0,r.kt)("a",{parentName:"p",href:"https://docs.github.com/en/authentication/connecting-to-github-with-ssh"},"here"),"."),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"git clone -b testnet-alpha-0 https://github.com/fleek-network/lightning.git \n")),(0,r.kt)("p",{parentName:"admonition"},"Here's an example of what it'd look like when sticking to the recommended path location:"),(0,r.kt)("pre",{parentName:"admonition"},(0,r.kt)("code",{parentName:"pre",className:"language-sh"},"git clone -b testnet-alpha-0 https://github.com/fleek-network/lightning.git ~/fleek-network/lightning\n"))))}s.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>r});var o=n(7294);const r=e=>{let{image:t,name:n,title:r,url:a,communityMember:i=!1}=e;return o.createElement("section",{className:"author_card"},o.createElement("div",null,o.createElement("span",{className:"avatar"},o.createElement("a",{href:a,target:"_blank",alt:n},o.createElement("img",{src:t,alt:n}))),o.createElement("div",null,o.createElement("span",{className:"name"},o.createElement("a",{href:a,target:"_blank",alt:n},n)),o.createElement("span",{className:"title"},r),o.createElement("span",{className:"discord"},i?"Join our community on":"Got questions? Find us on"," ",o.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file diff --git a/assets/js/2730e145.06d16aee.js b/assets/js/2730e145.a51c8e0a.js similarity index 99% rename from assets/js/2730e145.06d16aee.js rename to assets/js/2730e145.a51c8e0a.js index 597abf7ca..35f9c6747 100644 --- a/assets/js/2730e145.06d16aee.js +++ b/assets/js/2730e145.a51c8e0a.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[7147],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>h});var r=t(7294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function o(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=r.createContext({}),d=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},p=function(e){var n=d(e.components);return r.createElement(l.Provider,{value:n},e.children)},c="mdxType",m={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},u=r.forwardRef((function(e,n){var t=e.components,i=e.mdxType,a=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),c=d(t),u=i,h=c["".concat(l,".").concat(u)]||c[u]||m[u]||a;return t?r.createElement(h,o(o({ref:n},p),{},{components:t})):r.createElement(h,o({ref:n},p))}));function h(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var a=t.length,o=new Array(a);o[0]=u;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s[c]="string"==typeof e?e:i,o[1]=s;for(var d=2;d{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>s,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>p});var r=t(7462),i=(t(7294),t(3905)),a=t(3872);const o={title:"Permission denied (os error 13)",slug:"permission-denied-os-error-13",hide_title:!0,tags:["permissions"]},s=void 0,l={unversionedId:"Lightning CLI/permission-denied-os-error-13",id:"Lightning CLI/permission-denied-os-error-13",title:"Permission denied (os error 13)",description:"Ownership and file permissions",source:"@site/references/Lightning CLI/permission-denied-os-error-13.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/permission-denied-os-error-13",permalink:"/references/Lightning CLI/permission-denied-os-error-13",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/permission-denied-os-error-13.md",tags:[{label:"permissions",permalink:"/references/tags/permissions"}],version:"current",lastUpdatedAt:1694784773,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Permission denied (os error 13)",slug:"permission-denied-os-error-13",hide_title:!0,tags:["permissions"]},sidebar:"defaultSidebar",previous:{title:"Backing up the keystore",permalink:"/references/Lightning CLI/backing-up-the-keystore"},next:{title:"Uninstall Lightning CLI",permalink:"/references/Lightning CLI/uninstall-lightning-cli"}},d={},p=[{value:"Ownership and file permissions",id:"ownership-and-file-permissions",level:2},{value:"Override the TMPDIR",id:"override-the-tmpdir",level:2}],c={toc:p},m="wrapper";function u(e){let{components:n,...t}=e;return(0,i.kt)(m,(0,r.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"ownership-and-file-permissions"},"Ownership and file permissions"),(0,i.kt)("p",null,"When running the Lightning CLI, the user who's in control can delegate to ",(0,i.kt)("strong",{parentName:"p"},"root")," via ",(0,i.kt)("strong",{parentName:"p"},"sudo"),". Depending on how the Fleek Networking Lightning CLI was installed, this might cause some confusion, which is better explained by reading the reference ",(0,i.kt)("a",{parentName:"p",href:"/references/Lightning%20CLI/keys-not-found"},"Keys not found"),", which illustrates a situation where a user gets an error message about the wrong location of a system path (keystore)."),(0,i.kt)("p",null,"Some of the reasons why the ",(0,i.kt)("inlineCode",{parentName:"p"},"Permission denied (os error 13)")," might occur are related to:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"The Fleek Network Lightning CLI process trying to write to a ",(0,i.kt)("inlineCode",{parentName:"li"},".lightning")," stored in a non permited location"),(0,i.kt)("li",{parentName:"ul"},"The Fleek Network Lightning CLI process trying to write to ",(0,i.kt)("inlineCode",{parentName:"li"},"/tmp"))),(0,i.kt)("p",null,"The most common issue can be fixed by reading the section ",(0,i.kt)("a",{parentName:"p",href:"#override-the-tmpdir"},"Override the TMPDIR"),"."),(0,i.kt)("h2",{id:"override-the-tmpdir"},"Override the TMPDIR"),(0,i.kt)("p",null,"The Fleek Network Lightning process requires writing to a temporary directory. As the process requires permissions, this might fail as demonstrated by some of the output logs we have below."),(0,i.kt)("p",null,"a) A permission denied error message"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"Permission denied (os error 13)\n")),(0,i.kt)("p",null,"b) Rust panic error message which includes a permission denied"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"thread 'main' panicked at 'called Result::unwrap() on an Err value: Os { code: 13, kind: PermissionDenied, message: \"Permission denied\" }', core/node/src/cli.rs:181:18\nnote: run with RUST_BACKTRACE=1 environment variable to display a backtrace\nthread 'main' panicked at 'called Result::unwrap() on an Err value: Os { code: 13, kind: PermissionDenied, message: \"Permission denied\" }', core/node/src/cli.rs:181:18\nnote: run with RUST_BACKTRACE=1 environment variable to display a backtrace\nthread 'main' panicked at 'called Result::unwrap() on an Err value: Os { code: 13, kind: PermissionDenied, message: \"Permission denied\" }', core/node/src/cli.rs:181:18\nnote: run with RUST_BACKTRACE=1 environment variable to display a backtrace\nthread 'main' panicked at 'called Result::unwrap() on an Err value: Os { code: 13, kind: PermissionDenied, message: \"Permission denied\" }', core/node/src/cli.rs:181:18\nnote: run with RUST_BACKTRACE=1 environment variable to display a backtrace\nthread 'main' panicked at 'called Result::unwrap() on an Err value: Os { code: 13, kind: PermissionDenied, message: \"Permission denied\" }', core/node/src/cli.rs:181:18\nnote: run with RUST_BACKTRACE=1 environment variable to display a backtrace\n")),(0,i.kt)("p",null,"c) A trace showing the path where this has failed"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},'[00007fcbe168e764] openat(AT_FDCWD, "/tmp/lightning.log", O_WRONLY|O_CREAT|O_APPEND|O_CLOEXEC, 0666) = -1 EACCES (Permission denied)\n[00007fcbe168ea6f] write(2, "thread \'", 8thread \') = 8\n[00007fcbe168ea6f] write(2, "main", 4main) = 4\n[00007fcbe168ea6f] write(2, "\' panicked at \'", 15\' panicked at \') = 15\n[00007fcbe168ea6f] write(2, "called `Result::unwrap()` on an "..., 114called `Result::unwrap()` on an `Err` value: Os { code: 13, kind: PermissionDenied, message: "Permission denied" }) = 114\n[00007fcbe168ea6f] write(2, "\', ", 3\', ) = 3\n')),(0,i.kt)("admonition",{type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"The ",(0,i.kt)("inlineCode",{parentName:"p"},"/tmp")," directory should have wide permissions for all applications, but to mitigate any permission issues the user can override the system environment ",(0,i.kt)("inlineCode",{parentName:"p"},"TMPDIR"),". For example, the ",(0,i.kt)("inlineCode",{parentName:"p"},"installer")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"update")," scripts override ",(0,i.kt)("inlineCode",{parentName:"p"},"TMPDIR")," environment variable to ",(0,i.kt)("inlineCode",{parentName:"p"},"/var/tmp")," setting it in the service unit ",(0,i.kt)("inlineCode",{parentName:"p"},"Environment="),".")),(0,i.kt)("p",null,"The Lightning CLI process is aware of the environment variable TMPDIR, which the operators can override as discussed in the reference for ",(0,i.kt)("a",{parentName:"p",href:"/references/Lightning%20CLI/update-cli-from-source-code/#update-the-systemd-service-unit"},"Update the System service unit"),"."),(0,i.kt)("p",null,"In short, it requires you to include an ",(0,i.kt)("inlineCode",{parentName:"p"},"Environment=")," value of ",(0,i.kt)("inlineCode",{parentName:"p"},"TMPDIR=/var/tmp")," as follows:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"[Service]\n...\nStandardOutput=append:/var/log/lightning/output.log\nStandardError=append:/var/log/lightning/diagnostic.log\nEnvironment=TMPDIR=/var/tmp\n")),(0,i.kt)("admonition",{title:"attention",type:"caution"},(0,i.kt)("p",{parentName:"admonition"},"The ",(0,i.kt)("inlineCode",{parentName:"p"},"/etc/systemd/system/lightning.service")," service unit file presented here is a shorter version for simplicity. Do not replace your service unit file with the shorter content version presented here.")),(0,i.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}u.isMDXComponent=!0},3872:(e,n,t)=>{t.d(n,{Z:()=>i});var r=t(7294);const i=e=>{let{image:n,name:t,title:i,url:a,communityMember:o=!1}=e;return r.createElement("section",{className:"author_card"},r.createElement("div",null,r.createElement("span",{className:"avatar"},r.createElement("a",{href:a,target:"_blank",alt:t},r.createElement("img",{src:n,alt:t}))),r.createElement("div",null,r.createElement("span",{className:"name"},r.createElement("a",{href:a,target:"_blank",alt:t},t)),r.createElement("span",{className:"title"},i),r.createElement("span",{className:"discord"},o?"Join our community on":"Got questions? Find us on"," ",r.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[7147],{3905:(e,n,t)=>{t.d(n,{Zo:()=>p,kt:()=>h});var r=t(7294);function i(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function a(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);n&&(r=r.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,r)}return t}function o(e){for(var n=1;n=0||(i[t]=e[t]);return i}(e,n);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(i[t]=e[t])}return i}var l=r.createContext({}),d=function(e){var n=r.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):o(o({},n),e)),t},p=function(e){var n=d(e.components);return r.createElement(l.Provider,{value:n},e.children)},c="mdxType",m={inlineCode:"code",wrapper:function(e){var n=e.children;return r.createElement(r.Fragment,{},n)}},u=r.forwardRef((function(e,n){var t=e.components,i=e.mdxType,a=e.originalType,l=e.parentName,p=s(e,["components","mdxType","originalType","parentName"]),c=d(t),u=i,h=c["".concat(l,".").concat(u)]||c[u]||m[u]||a;return t?r.createElement(h,o(o({ref:n},p),{},{components:t})):r.createElement(h,o({ref:n},p))}));function h(e,n){var t=arguments,i=n&&n.mdxType;if("string"==typeof e||i){var a=t.length,o=new Array(a);o[0]=u;var s={};for(var l in n)hasOwnProperty.call(n,l)&&(s[l]=n[l]);s.originalType=e,s[c]="string"==typeof e?e:i,o[1]=s;for(var d=2;d{t.r(n),t.d(n,{assets:()=>d,contentTitle:()=>s,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>p});var r=t(7462),i=(t(7294),t(3905)),a=t(3872);const o={title:"Permission denied (os error 13)",slug:"permission-denied-os-error-13",hide_title:!0,tags:["permissions"]},s=void 0,l={unversionedId:"Lightning CLI/permission-denied-os-error-13",id:"Lightning CLI/permission-denied-os-error-13",title:"Permission denied (os error 13)",description:"Ownership and file permissions",source:"@site/references/Lightning CLI/permission-denied-os-error-13.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/permission-denied-os-error-13",permalink:"/references/Lightning CLI/permission-denied-os-error-13",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/permission-denied-os-error-13.md",tags:[{label:"permissions",permalink:"/references/tags/permissions"}],version:"current",lastUpdatedAt:1694785242,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Permission denied (os error 13)",slug:"permission-denied-os-error-13",hide_title:!0,tags:["permissions"]},sidebar:"defaultSidebar",previous:{title:"Backing up the keystore",permalink:"/references/Lightning CLI/backing-up-the-keystore"},next:{title:"Uninstall Lightning CLI",permalink:"/references/Lightning CLI/uninstall-lightning-cli"}},d={},p=[{value:"Ownership and file permissions",id:"ownership-and-file-permissions",level:2},{value:"Override the TMPDIR",id:"override-the-tmpdir",level:2}],c={toc:p},m="wrapper";function u(e){let{components:n,...t}=e;return(0,i.kt)(m,(0,r.Z)({},c,t,{components:n,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"ownership-and-file-permissions"},"Ownership and file permissions"),(0,i.kt)("p",null,"When running the Lightning CLI, the user who's in control can delegate to ",(0,i.kt)("strong",{parentName:"p"},"root")," via ",(0,i.kt)("strong",{parentName:"p"},"sudo"),". Depending on how the Fleek Networking Lightning CLI was installed, this might cause some confusion, which is better explained by reading the reference ",(0,i.kt)("a",{parentName:"p",href:"/references/Lightning%20CLI/keys-not-found"},"Keys not found"),", which illustrates a situation where a user gets an error message about the wrong location of a system path (keystore)."),(0,i.kt)("p",null,"Some of the reasons why the ",(0,i.kt)("inlineCode",{parentName:"p"},"Permission denied (os error 13)")," might occur are related to:"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"The Fleek Network Lightning CLI process trying to write to a ",(0,i.kt)("inlineCode",{parentName:"li"},".lightning")," stored in a non permited location"),(0,i.kt)("li",{parentName:"ul"},"The Fleek Network Lightning CLI process trying to write to ",(0,i.kt)("inlineCode",{parentName:"li"},"/tmp"))),(0,i.kt)("p",null,"The most common issue can be fixed by reading the section ",(0,i.kt)("a",{parentName:"p",href:"#override-the-tmpdir"},"Override the TMPDIR"),"."),(0,i.kt)("h2",{id:"override-the-tmpdir"},"Override the TMPDIR"),(0,i.kt)("p",null,"The Fleek Network Lightning process requires writing to a temporary directory. As the process requires permissions, this might fail as demonstrated by some of the output logs we have below."),(0,i.kt)("p",null,"a) A permission denied error message"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"Permission denied (os error 13)\n")),(0,i.kt)("p",null,"b) Rust panic error message which includes a permission denied"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"thread 'main' panicked at 'called Result::unwrap() on an Err value: Os { code: 13, kind: PermissionDenied, message: \"Permission denied\" }', core/node/src/cli.rs:181:18\nnote: run with RUST_BACKTRACE=1 environment variable to display a backtrace\nthread 'main' panicked at 'called Result::unwrap() on an Err value: Os { code: 13, kind: PermissionDenied, message: \"Permission denied\" }', core/node/src/cli.rs:181:18\nnote: run with RUST_BACKTRACE=1 environment variable to display a backtrace\nthread 'main' panicked at 'called Result::unwrap() on an Err value: Os { code: 13, kind: PermissionDenied, message: \"Permission denied\" }', core/node/src/cli.rs:181:18\nnote: run with RUST_BACKTRACE=1 environment variable to display a backtrace\nthread 'main' panicked at 'called Result::unwrap() on an Err value: Os { code: 13, kind: PermissionDenied, message: \"Permission denied\" }', core/node/src/cli.rs:181:18\nnote: run with RUST_BACKTRACE=1 environment variable to display a backtrace\nthread 'main' panicked at 'called Result::unwrap() on an Err value: Os { code: 13, kind: PermissionDenied, message: \"Permission denied\" }', core/node/src/cli.rs:181:18\nnote: run with RUST_BACKTRACE=1 environment variable to display a backtrace\n")),(0,i.kt)("p",null,"c) A trace showing the path where this has failed"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},'[00007fcbe168e764] openat(AT_FDCWD, "/tmp/lightning.log", O_WRONLY|O_CREAT|O_APPEND|O_CLOEXEC, 0666) = -1 EACCES (Permission denied)\n[00007fcbe168ea6f] write(2, "thread \'", 8thread \') = 8\n[00007fcbe168ea6f] write(2, "main", 4main) = 4\n[00007fcbe168ea6f] write(2, "\' panicked at \'", 15\' panicked at \') = 15\n[00007fcbe168ea6f] write(2, "called `Result::unwrap()` on an "..., 114called `Result::unwrap()` on an `Err` value: Os { code: 13, kind: PermissionDenied, message: "Permission denied" }) = 114\n[00007fcbe168ea6f] write(2, "\', ", 3\', ) = 3\n')),(0,i.kt)("admonition",{type:"tip"},(0,i.kt)("p",{parentName:"admonition"},"The ",(0,i.kt)("inlineCode",{parentName:"p"},"/tmp")," directory should have wide permissions for all applications, but to mitigate any permission issues the user can override the system environment ",(0,i.kt)("inlineCode",{parentName:"p"},"TMPDIR"),". For example, the ",(0,i.kt)("inlineCode",{parentName:"p"},"installer")," and ",(0,i.kt)("inlineCode",{parentName:"p"},"update")," scripts override ",(0,i.kt)("inlineCode",{parentName:"p"},"TMPDIR")," environment variable to ",(0,i.kt)("inlineCode",{parentName:"p"},"/var/tmp")," setting it in the service unit ",(0,i.kt)("inlineCode",{parentName:"p"},"Environment="),".")),(0,i.kt)("p",null,"The Lightning CLI process is aware of the environment variable TMPDIR, which the operators can override as discussed in the reference for ",(0,i.kt)("a",{parentName:"p",href:"/references/Lightning%20CLI/update-cli-from-source-code/#update-the-systemd-service-unit"},"Update the System service unit"),"."),(0,i.kt)("p",null,"In short, it requires you to include an ",(0,i.kt)("inlineCode",{parentName:"p"},"Environment=")," value of ",(0,i.kt)("inlineCode",{parentName:"p"},"TMPDIR=/var/tmp")," as follows:"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"[Service]\n...\nStandardOutput=append:/var/log/lightning/output.log\nStandardError=append:/var/log/lightning/diagnostic.log\nEnvironment=TMPDIR=/var/tmp\n")),(0,i.kt)("admonition",{title:"attention",type:"caution"},(0,i.kt)("p",{parentName:"admonition"},"The ",(0,i.kt)("inlineCode",{parentName:"p"},"/etc/systemd/system/lightning.service")," service unit file presented here is a shorter version for simplicity. Do not replace your service unit file with the shorter content version presented here.")),(0,i.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}u.isMDXComponent=!0},3872:(e,n,t)=>{t.d(n,{Z:()=>i});var r=t(7294);const i=e=>{let{image:n,name:t,title:i,url:a,communityMember:o=!1}=e;return r.createElement("section",{className:"author_card"},r.createElement("div",null,r.createElement("span",{className:"avatar"},r.createElement("a",{href:a,target:"_blank",alt:t},r.createElement("img",{src:n,alt:t}))),r.createElement("div",null,r.createElement("span",{className:"name"},r.createElement("a",{href:a,target:"_blank",alt:t},t)),r.createElement("span",{className:"title"},i),r.createElement("span",{className:"discord"},o?"Join our community on":"Got questions? Find us on"," ",r.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file diff --git a/assets/js/29b62a39.6a7ed6c6.js b/assets/js/29b62a39.f3ae4346.js similarity index 98% rename from assets/js/29b62a39.6a7ed6c6.js rename to assets/js/29b62a39.f3ae4346.js index 3cedcf5e3..dbc3a63f1 100644 --- a/assets/js/29b62a39.6a7ed6c6.js +++ b/assets/js/29b62a39.f3ae4346.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[1498],{3905:(e,t,r)=>{r.d(t,{Zo:()=>l,kt:()=>m});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),d=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},l=function(e){var t=d(e.components);return n.createElement(c.Provider,{value:t},e.children)},u="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,l=s(e,["components","mdxType","originalType","parentName"]),u=d(r),f=o,m=u["".concat(c,".").concat(f)]||u[f]||p[f]||a;return r?n.createElement(m,i(i({ref:t},l),{},{components:r})):n.createElement(m,i({ref:t},l))}));function m(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=f;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s[u]="string"==typeof e?e:o,i[1]=s;for(var d=2;d{r.r(t),r.d(t,{assets:()=>d,contentTitle:()=>s,default:()=>f,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const a=r.p+"assets/images/banner-guides-cd76f6e8aac3594bb5d072a564e0e277.png",i={title:"About guides",hide_title:!0,sidebar_position:1,tags:["Guides","Help","Fleek Network"]},s=void 0,c={unversionedId:"index",id:"index",title:"About guides",description:"The guides provide step-by-step instructions and descriptions to help understand how and why you'd have to do or execute certain commands or processes.",source:"@site/guides/index.md",sourceDirName:".",slug:"/",permalink:"/guides/",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/guides/index.md",tags:[{label:"Guides",permalink:"/guides/tags/guides"},{label:"Help",permalink:"/guides/tags/help"},{label:"Fleek Network",permalink:"/guides/tags/fleek-network"}],version:"current",lastUpdatedAt:1694784773,formattedLastUpdatedAt:"Sep 15, 2023",sidebarPosition:1,frontMatter:{title:"About guides",hide_title:!0,sidebar_position:1,tags:["Guides","Help","Fleek Network"]},sidebar:"defaultSidebar",next:{title:"Getting Started",permalink:"/guides/Node Operators/getting-started"}},d={},l=[],u={toc:l},p="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(p,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("img",{className:"banner",src:a}),(0,o.kt)("p",null,"The guides provide step-by-step instructions and descriptions to help understand how and why you'd have to do or execute certain commands or processes."),(0,o.kt)("p",null,"It differs from the ",(0,o.kt)("a",{parentName:"p",href:"/references"},"references")," documentation which serves as a quick direct breakdown of commands and processes without much explanation, as the name implies."),(0,o.kt)("p",null,"To start, find guides by consulting the available categories to locate the content on the sidebar. Our guides are also available as a result when using the search feature located at the very top of the documentation site."))}f.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[1498],{3905:(e,t,r)=>{r.d(t,{Zo:()=>l,kt:()=>m});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),d=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},l=function(e){var t=d(e.components);return n.createElement(c.Provider,{value:t},e.children)},u="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,l=s(e,["components","mdxType","originalType","parentName"]),u=d(r),f=o,m=u["".concat(c,".").concat(f)]||u[f]||p[f]||a;return r?n.createElement(m,i(i({ref:t},l),{},{components:r})):n.createElement(m,i({ref:t},l))}));function m(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=f;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s[u]="string"==typeof e?e:o,i[1]=s;for(var d=2;d{r.r(t),r.d(t,{assets:()=>d,contentTitle:()=>s,default:()=>f,frontMatter:()=>i,metadata:()=>c,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const a=r.p+"assets/images/banner-guides-cd76f6e8aac3594bb5d072a564e0e277.png",i={title:"About guides",hide_title:!0,sidebar_position:1,tags:["Guides","Help","Fleek Network"]},s=void 0,c={unversionedId:"index",id:"index",title:"About guides",description:"The guides provide step-by-step instructions and descriptions to help understand how and why you'd have to do or execute certain commands or processes.",source:"@site/guides/index.md",sourceDirName:".",slug:"/",permalink:"/guides/",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/guides/index.md",tags:[{label:"Guides",permalink:"/guides/tags/guides"},{label:"Help",permalink:"/guides/tags/help"},{label:"Fleek Network",permalink:"/guides/tags/fleek-network"}],version:"current",lastUpdatedAt:1694785242,formattedLastUpdatedAt:"Sep 15, 2023",sidebarPosition:1,frontMatter:{title:"About guides",hide_title:!0,sidebar_position:1,tags:["Guides","Help","Fleek Network"]},sidebar:"defaultSidebar",next:{title:"Getting Started",permalink:"/guides/Node Operators/getting-started"}},d={},l=[],u={toc:l},p="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(p,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("img",{className:"banner",src:a}),(0,o.kt)("p",null,"The guides provide step-by-step instructions and descriptions to help understand how and why you'd have to do or execute certain commands or processes."),(0,o.kt)("p",null,"It differs from the ",(0,o.kt)("a",{parentName:"p",href:"/references"},"references")," documentation which serves as a quick direct breakdown of commands and processes without much explanation, as the name implies."),(0,o.kt)("p",null,"To start, find guides by consulting the available categories to locate the content on the sidebar. Our guides are also available as a result when using the search feature located at the very top of the documentation site."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/29b83576.c0c3fad7.js b/assets/js/29b83576.6458996c.js similarity index 99% rename from assets/js/29b83576.c0c3fad7.js rename to assets/js/29b83576.6458996c.js index 67fe6b660..8918e314d 100644 --- a/assets/js/29b83576.c0c3fad7.js +++ b/assets/js/29b83576.6458996c.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[1510],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>g});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},u="mdxType",h={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),u=p(n),d=a,g=u["".concat(s,".").concat(d)]||u[d]||h[d]||o;return n?r.createElement(g,i(i({ref:t},c),{},{components:n})):r.createElement(g,i({ref:t},c))}));function g(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=d;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[u]="string"==typeof e?e:a,i[1]=l;for(var p=2;p{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>l,default:()=>d,frontMatter:()=>i,metadata:()=>s,toc:()=>c});var r=n(7462),a=(n(7294),n(3905)),o=n(3872);const i={title:"Backing up the keystore",slug:"backing-up-the-keystore",hide_title:!0,tags:["references","help","keystore","backup","restore"]},l=void 0,s={unversionedId:"Lightning CLI/keystore-backup",id:"Lightning CLI/keystore-backup",title:"Backing up the keystore",description:"The security of the private key is the responsibility of the user. Unfortunately, the Fleek Network team and any others are unable to help regain access to private key if lost or failed to secure them. The private keys are the user responsibility. The Fleek Network team doesn't endorse any methods of encryption and storage, the methods described here are for educational purposes only.",source:"@site/references/Lightning CLI/keystore-backup.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/backing-up-the-keystore",permalink:"/references/Lightning CLI/backing-up-the-keystore",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/keystore-backup.md",tags:[{label:"references",permalink:"/references/tags/references"},{label:"help",permalink:"/references/tags/help"},{label:"keystore",permalink:"/references/tags/keystore"},{label:"backup",permalink:"/references/tags/backup"},{label:"restore",permalink:"/references/tags/restore"}],version:"current",lastUpdatedAt:1694784773,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Backing up the keystore",slug:"backing-up-the-keystore",hide_title:!0,tags:["references","help","keystore","backup","restore"]},sidebar:"defaultSidebar",previous:{title:"Keys not found",permalink:"/references/Lightning CLI/keys-not-found"},next:{title:"Permission denied (os error 13)",permalink:"/references/Lightning CLI/permission-denied-os-error-13"}},p={},c=[{value:"Keystore pathname",id:"keystore-pathname",level:2},{value:"Configuration file settings",id:"configuration-file-settings",level:2},{value:"Loading the configuration file on runtime",id:"loading-the-configuration-file-on-runtime",level:2},{value:"Low security backup",id:"low-security-backup",level:2},{value:"Higher security",id:"higher-security",level:2}],u={toc:c},h="wrapper";function d(e){let{components:t,...n}=e;return(0,a.kt)(h,(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"The security of the private key is the responsibility of the user. Unfortunately, the Fleek Network team and any others are unable to help regain access to private key if lost or failed to secure them. The private keys are the user responsibility. The Fleek Network team doesn't endorse any methods of encryption and storage, the methods described here are for educational purposes only.")),(0,a.kt)("h2",{id:"keystore-pathname"},"Keystore pathname"),(0,a.kt)("p",null,"The default location for the keystore is in the user home. The $HOME or ",(0,a.kt)("inlineCode",{parentName:"p"},"~")," refers to the user home, as such consider the logged in username."),(0,a.kt)("p",null,"To Check the user you are logged in with:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"whoami\n")),(0,a.kt)("p",null,"The default location for the keystore is:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"$HOME/.lightning/keystore\n")),(0,a.kt)("h2",{id:"configuration-file-settings"},"Configuration file settings"),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"config.toml")," should have some and more of the following properties and values that are used to locate crucial files, such as the consensus and node keys of the keystore."),(0,a.kt)("p",null,"Here's an incomplete example of how the ",(0,a.kt)("inlineCode",{parentName:"p"},"config.toml")," looks like:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'[BLANK]\n...\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n...\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n...\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n...\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n...\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n...\n')),(0,a.kt)("p",null,"If you've followed the installation recommendations, it's very likely that you'll have the username path defined at the base of the pathnames declared in the properties, such as the following except instead of ",(0,a.kt)("inlineCode",{parentName:"p"},"")," you'll have your username:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'[signer]\nconsensus_key_path = "/home//.lightning/keystore/consensus.pem"\nnode_key_path = "/home//.lightning/keystore/node.pem"\n')),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"config.toml")," if loaded on Lightning node process runtime, will pick the desired paths declared in the file."),(0,a.kt)("h2",{id:"loading-the-configuration-file-on-runtime"},"Loading the configuration file on runtime"),(0,a.kt)("p",null,"Use the configuration flag ",(0,a.kt)("inlineCode",{parentName:"p"},"-c")," to pass the configuration ",(0,a.kt)("inlineCode",{parentName:"p"},"config.toml")," path:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn -c /home//.lightning/config.toml run\n")),(0,a.kt)("p",null,"Replace the ",(0,a.kt)("inlineCode",{parentName:"p"},"")," with the correct username, where the config is located."),(0,a.kt)("p",null,"Executing the subcommand ",(0,a.kt)("inlineCode",{parentName:"p"},"run")," without the configuration flag ",(0,a.kt)("inlineCode",{parentName:"p"},"-c"),", doesn't mean that it'll locate the desired ",(0,a.kt)("inlineCode",{parentName:"p"},"config.toml"),", as it'll default to ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/config.toml"),", e.g. if you were logged in with ",(0,a.kt)("strong",{parentName:"p"},"root"),", that'd be ",(0,a.kt)("inlineCode",{parentName:"p"},"/root/.lightning/config.toml"),"."),(0,a.kt)("h2",{id:"low-security-backup"},"Low security backup"),(0,a.kt)("p",null,"To zip and encrypto the ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/keystore")," directory run:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"# It'll prompt for password (remember)\nzip --encrypt -r keystore.zip.enc $HOME/.lightning/keystore\n")),(0,a.kt)("p",null,"To unzip and decrypt the ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore.zip.enc"),", you'd run:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"# It'll prompt for password (recall)\nunzip keystore.zip.enc -d $HOME/.lightning/keystore\n")),(0,a.kt)("h2",{id:"higher-security"},"Higher security"),(0,a.kt)("p",null,"Create a ",(0,a.kt)("inlineCode",{parentName:"p"},"tarbar")," by executing:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'tar -cf "keystore.tar" $HOME/.lightning/keystore\n')),(0,a.kt)("p",null,"The encryption command is:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"sudo gpg -a --symmetric --cipher-algo AES256 keystore.tar\n")),(0,a.kt)("p",null,"To decrypt the ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore.tar.asc")," file, enter:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"sudo gpg -a --output keystore.tar --decrypt keystore.tar.asc\n")),(0,a.kt)("p",null,"Create a temporary directory to extract the tar archive with the original full pathname."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"mkdir $HOME/tar_keystore_extract\n")),(0,a.kt)("p",null,"Now, run the command to extract to the target directory, as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"tar -xf keystore.tar -C $HOME/tar_keystore_extract\n")),(0,a.kt)("p",null,"Locate the extracted files in ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/tar_keystore_extract"),", which should look like ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/tar_keystore/home//.lightning/keystore")),(0,a.kt)("p",null,"For a more in depth or step-by-step instructions read the guide ",(0,a.kt)("a",{parentName:"p",href:"/guides/Node%20Operators/managing-the-keystore"},"managing the keystore"),"."),(0,a.kt)(o.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}d.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>a});var r=n(7294);const a=e=>{let{image:t,name:n,title:a,url:o,communityMember:i=!1}=e;return r.createElement("section",{className:"author_card"},r.createElement("div",null,r.createElement("span",{className:"avatar"},r.createElement("a",{href:o,target:"_blank",alt:n},r.createElement("img",{src:t,alt:n}))),r.createElement("div",null,r.createElement("span",{className:"name"},r.createElement("a",{href:o,target:"_blank",alt:n},n)),r.createElement("span",{className:"title"},a),r.createElement("span",{className:"discord"},i?"Join our community on":"Got questions? Find us on"," ",r.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[1510],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>g});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),p=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},c=function(e){var t=p(e.components);return r.createElement(s.Provider,{value:t},e.children)},u="mdxType",h={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,s=e.parentName,c=l(e,["components","mdxType","originalType","parentName"]),u=p(n),d=a,g=u["".concat(s,".").concat(d)]||u[d]||h[d]||o;return n?r.createElement(g,i(i({ref:t},c),{},{components:n})):r.createElement(g,i({ref:t},c))}));function g(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,i=new Array(o);i[0]=d;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[u]="string"==typeof e?e:a,i[1]=l;for(var p=2;p{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>l,default:()=>d,frontMatter:()=>i,metadata:()=>s,toc:()=>c});var r=n(7462),a=(n(7294),n(3905)),o=n(3872);const i={title:"Backing up the keystore",slug:"backing-up-the-keystore",hide_title:!0,tags:["references","help","keystore","backup","restore"]},l=void 0,s={unversionedId:"Lightning CLI/keystore-backup",id:"Lightning CLI/keystore-backup",title:"Backing up the keystore",description:"The security of the private key is the responsibility of the user. Unfortunately, the Fleek Network team and any others are unable to help regain access to private key if lost or failed to secure them. The private keys are the user responsibility. The Fleek Network team doesn't endorse any methods of encryption and storage, the methods described here are for educational purposes only.",source:"@site/references/Lightning CLI/keystore-backup.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/backing-up-the-keystore",permalink:"/references/Lightning CLI/backing-up-the-keystore",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/keystore-backup.md",tags:[{label:"references",permalink:"/references/tags/references"},{label:"help",permalink:"/references/tags/help"},{label:"keystore",permalink:"/references/tags/keystore"},{label:"backup",permalink:"/references/tags/backup"},{label:"restore",permalink:"/references/tags/restore"}],version:"current",lastUpdatedAt:1694785242,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Backing up the keystore",slug:"backing-up-the-keystore",hide_title:!0,tags:["references","help","keystore","backup","restore"]},sidebar:"defaultSidebar",previous:{title:"Keys not found",permalink:"/references/Lightning CLI/keys-not-found"},next:{title:"Permission denied (os error 13)",permalink:"/references/Lightning CLI/permission-denied-os-error-13"}},p={},c=[{value:"Keystore pathname",id:"keystore-pathname",level:2},{value:"Configuration file settings",id:"configuration-file-settings",level:2},{value:"Loading the configuration file on runtime",id:"loading-the-configuration-file-on-runtime",level:2},{value:"Low security backup",id:"low-security-backup",level:2},{value:"Higher security",id:"higher-security",level:2}],u={toc:c},h="wrapper";function d(e){let{components:t,...n}=e;return(0,a.kt)(h,(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"The security of the private key is the responsibility of the user. Unfortunately, the Fleek Network team and any others are unable to help regain access to private key if lost or failed to secure them. The private keys are the user responsibility. The Fleek Network team doesn't endorse any methods of encryption and storage, the methods described here are for educational purposes only.")),(0,a.kt)("h2",{id:"keystore-pathname"},"Keystore pathname"),(0,a.kt)("p",null,"The default location for the keystore is in the user home. The $HOME or ",(0,a.kt)("inlineCode",{parentName:"p"},"~")," refers to the user home, as such consider the logged in username."),(0,a.kt)("p",null,"To Check the user you are logged in with:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"whoami\n")),(0,a.kt)("p",null,"The default location for the keystore is:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"$HOME/.lightning/keystore\n")),(0,a.kt)("h2",{id:"configuration-file-settings"},"Configuration file settings"),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"config.toml")," should have some and more of the following properties and values that are used to locate crucial files, such as the consensus and node keys of the keystore."),(0,a.kt)("p",null,"Here's an incomplete example of how the ",(0,a.kt)("inlineCode",{parentName:"p"},"config.toml")," looks like:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'[BLANK]\n...\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n...\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n...\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n...\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n...\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n...\n')),(0,a.kt)("p",null,"If you've followed the installation recommendations, it's very likely that you'll have the username path defined at the base of the pathnames declared in the properties, such as the following except instead of ",(0,a.kt)("inlineCode",{parentName:"p"},"")," you'll have your username:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'[signer]\nconsensus_key_path = "/home//.lightning/keystore/consensus.pem"\nnode_key_path = "/home//.lightning/keystore/node.pem"\n')),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"config.toml")," if loaded on Lightning node process runtime, will pick the desired paths declared in the file."),(0,a.kt)("h2",{id:"loading-the-configuration-file-on-runtime"},"Loading the configuration file on runtime"),(0,a.kt)("p",null,"Use the configuration flag ",(0,a.kt)("inlineCode",{parentName:"p"},"-c")," to pass the configuration ",(0,a.kt)("inlineCode",{parentName:"p"},"config.toml")," path:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn -c /home//.lightning/config.toml run\n")),(0,a.kt)("p",null,"Replace the ",(0,a.kt)("inlineCode",{parentName:"p"},"")," with the correct username, where the config is located."),(0,a.kt)("p",null,"Executing the subcommand ",(0,a.kt)("inlineCode",{parentName:"p"},"run")," without the configuration flag ",(0,a.kt)("inlineCode",{parentName:"p"},"-c"),", doesn't mean that it'll locate the desired ",(0,a.kt)("inlineCode",{parentName:"p"},"config.toml"),", as it'll default to ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/config.toml"),", e.g. if you were logged in with ",(0,a.kt)("strong",{parentName:"p"},"root"),", that'd be ",(0,a.kt)("inlineCode",{parentName:"p"},"/root/.lightning/config.toml"),"."),(0,a.kt)("h2",{id:"low-security-backup"},"Low security backup"),(0,a.kt)("p",null,"To zip and encrypto the ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/keystore")," directory run:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"# It'll prompt for password (remember)\nzip --encrypt -r keystore.zip.enc $HOME/.lightning/keystore\n")),(0,a.kt)("p",null,"To unzip and decrypt the ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore.zip.enc"),", you'd run:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"# It'll prompt for password (recall)\nunzip keystore.zip.enc -d $HOME/.lightning/keystore\n")),(0,a.kt)("h2",{id:"higher-security"},"Higher security"),(0,a.kt)("p",null,"Create a ",(0,a.kt)("inlineCode",{parentName:"p"},"tarbar")," by executing:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'tar -cf "keystore.tar" $HOME/.lightning/keystore\n')),(0,a.kt)("p",null,"The encryption command is:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"sudo gpg -a --symmetric --cipher-algo AES256 keystore.tar\n")),(0,a.kt)("p",null,"To decrypt the ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore.tar.asc")," file, enter:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"sudo gpg -a --output keystore.tar --decrypt keystore.tar.asc\n")),(0,a.kt)("p",null,"Create a temporary directory to extract the tar archive with the original full pathname."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"mkdir $HOME/tar_keystore_extract\n")),(0,a.kt)("p",null,"Now, run the command to extract to the target directory, as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"tar -xf keystore.tar -C $HOME/tar_keystore_extract\n")),(0,a.kt)("p",null,"Locate the extracted files in ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/tar_keystore_extract"),", which should look like ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/tar_keystore/home//.lightning/keystore")),(0,a.kt)("p",null,"For a more in depth or step-by-step instructions read the guide ",(0,a.kt)("a",{parentName:"p",href:"/guides/Node%20Operators/managing-the-keystore"},"managing the keystore"),"."),(0,a.kt)(o.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}d.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>a});var r=n(7294);const a=e=>{let{image:t,name:n,title:a,url:o,communityMember:i=!1}=e;return r.createElement("section",{className:"author_card"},r.createElement("div",null,r.createElement("span",{className:"avatar"},r.createElement("a",{href:o,target:"_blank",alt:n},r.createElement("img",{src:t,alt:n}))),r.createElement("div",null,r.createElement("span",{className:"name"},r.createElement("a",{href:o,target:"_blank",alt:n},n)),r.createElement("span",{className:"title"},a),r.createElement("span",{className:"discord"},i?"Join our community on":"Got questions? Find us on"," ",r.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file diff --git a/assets/js/40aeb86f.41636888.js b/assets/js/40aeb86f.179226e6.js similarity index 99% rename from assets/js/40aeb86f.41636888.js rename to assets/js/40aeb86f.179226e6.js index bf4881301..853075598 100644 --- a/assets/js/40aeb86f.41636888.js +++ b/assets/js/40aeb86f.179226e6.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[4402],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=a.createContext({}),p=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},c=function(e){var t=p(e.components);return a.createElement(s.Provider,{value:t},e.children)},h="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,s=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),h=p(n),d=o,m=h["".concat(s,".").concat(d)]||h[d]||u[d]||r;return n?a.createElement(m,l(l({ref:t},c),{},{components:n})):a.createElement(m,l({ref:t},c))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,l=new Array(r);l[0]=d;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i[h]="string"==typeof e?e:o,l[1]=i;for(var p=2;p{n.d(t,{ZP:()=>i});var a=n(7462),o=(n(7294),n(3905));const r={toc:[]},l="wrapper";function i(e){let{components:t,...n}=e;return(0,o.kt)(l,(0,a.Z)({},r,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"In the ",(0,o.kt)("inlineCode",{parentName:"p"},"/home//.lightning/config.toml")," you'll find some and more of the following:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n')),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"The configuration properties and values presented above are a shorter version of what you'll find on your ",(0,o.kt)("strong",{parentName:"p"},"configuration.toml"),". We keep it short to make it easier to follow, do not copy and paste.")),(0,o.kt)("p",null,"Find and replace all instances of ~ in the config file ",(0,o.kt)("inlineCode",{parentName:"p"},"/home//.lightning/config.toml"),". "),(0,o.kt)("p",null,"Here's an example of how to do it using ",(0,o.kt)("strong",{parentName:"p"},"sed"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'sed -i "s|~/.lightning|/home//.lightning|g" "/home//.lightning/config.toml"\n')),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Replace the ",(0,o.kt)("inlineCode",{parentName:"p"},"")," with your username. For example, if you have followed the recommendation to ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/install#create-a-user"},"create a user")," it would look like ",(0,o.kt)("inlineCode",{parentName:"p"},"/home/lgtn/.lightning/config.toml")," for the username ",(0,o.kt)("strong",{parentName:"p"},"lgtn"),".")),(0,o.kt)("p",null,"For example, if your username is ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn")," that'd look like this:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'sed -i "s|~/.lightning|/home/lgtn/.lightning|g" "/home/lgtn/.lightning/config.toml"\n')),(0,o.kt)("p",null,"Once modified, you can run a ",(0,o.kt)("inlineCode",{parentName:"p"},"cat")," to see the content of the files to confirm it has been updated."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"cat /home/lgtn/.lightning/config.toml\n")),(0,o.kt)("p",null,"For our example where we opted in for the username ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn")," that would look like:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n')),(0,o.kt)("admonition",{title:"Warning",type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"Bear in mind that we are keeping the content of the file short to make it easier to read and follow. The content of your configuration file should look slightly different, amongst these it should contain other properties and values. You should not copy and replace the content of your files with the ones presented here.")))}i.isMDXComponent=!0},3813:(e,t,n)=>{n.d(t,{ZP:()=>i});var a=n(7462),o=(n(7294),n(3905));const r={toc:[]},l="wrapper";function i(e){let{components:t,...n}=e;return(0,o.kt)(l,(0,a.Z)({},r,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("admonition",{type:"note"},(0,o.kt)("p",{parentName:"admonition"},"The flag ",(0,o.kt)("inlineCode",{parentName:"p"},"-c")," in the ",(0,o.kt)("inlineCode",{parentName:"p"},"lightning.service")," ",(0,o.kt)("strong",{parentName:"p"},"ExecStart"),", is to provide the toml configuration file path e.g. defaults to ",(0,o.kt)("inlineCode",{parentName:"p"},"~/.lightning/config.toml"),". This is to avoid the path being determined dynamically (given path base ~ or $HOME), as users might control the systemctl service as a ",(0,o.kt)("strong",{parentName:"p"},"user")," or ",(0,o.kt)("strong",{parentName:"p"},"sudoer"),". For example, a ",(0,o.kt)("strong",{parentName:"p"},"sudoer")," would have the ",(0,o.kt)("strong",{parentName:"p"},"configuration")," set to ",(0,o.kt)("inlineCode",{parentName:"p"},"/root/.lightning/config.toml")," or ",(0,o.kt)("inlineCode",{parentName:"p"},"/home/username/.lightning/config.toml")," depending on using ",(0,o.kt)("strong",{parentName:"p"},"sudo")," which might cause some confusion to some users.")))}i.isMDXComponent=!0},2300:(e,t,n)=>{n.d(t,{ZP:()=>i});var a=n(7462),o=(n(7294),n(3905));const r={toc:[]},l="wrapper";function i(e){let{components:t,...n}=e;return(0,o.kt)(l,(0,a.Z)({},r,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"You should be following the ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/install#create-a-user-1"},"create a user")," recommendation. For our example, we have the username ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn"),"."),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"If you have chosen a different username, replace ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn")," by the correct username you have selected.")),(0,o.kt)("p",null,"In the ",(0,o.kt)("inlineCode",{parentName:"p"},"config.toml")," you'll find some and more of the following:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n')),(0,o.kt)("p",null,"Find and replace all instances of ",(0,o.kt)("inlineCode",{parentName:"p"},"~")," in the config file ",(0,o.kt)("inlineCode",{parentName:"p"},"/home/lgtn/.lightning/config.toml"),". Here's an example using ",(0,o.kt)("inlineCode",{parentName:"p"},"sed"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'sed -i "s|~/.lightning|/home/lgtn/.lightning|g" "/home/lgtn/.lightning/config.toml"\n')),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"The ",(0,o.kt)("inlineCode",{parentName:"p"},"config.toml")," example below is a shorter version of what you'll encounter, yours might look different. We do this to keep the guide simple to read. Do not copy and replace with the version demonstrated here.")),(0,o.kt)("p",null,"Once changed, all the instances of ",(0,o.kt)("inlineCode",{parentName:"p"},"~/")," should be replaced by your user path e.g. ",(0,o.kt)("inlineCode",{parentName:"p"},"/home/lgtn/"),". For our example, the output would look like the following:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "/home/lgtn/.lightning/data/app_db"\n\n[consensus]\nstore_path = "/home/lgtn/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "/home/lgtn/.lightning/blockstore"\n\n[resolver]\nstore_path = "/home/lgtn/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "/home/lgtn/.lightning/keystore/consensus.pem"\nnode_key_path = "/home/lgtn/.lightning/keystore/node.pem"\n')))}i.isMDXComponent=!0},1054:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>c,default:()=>k,frontMatter:()=>p,metadata:()=>h,toc:()=>d});var a=n(7462),o=(n(7294),n(3905)),r=n(3872),l=n(2300),i=n(3813),s=n(3242);const p={title:"Update CLI from source code",slug:"update-cli-from-source-code",hide_title:!0,tags:["references","help","update","upgrade","fix"]},c=void 0,h={unversionedId:"Lightning CLI/update-cli-from-source-code",id:"Lightning CLI/update-cli-from-source-code",title:"Update CLI from source code",description:"Although the step-by-step instructions described here are simple to follow, this process is available as an automated script. To use it execute the following command in your server terminal and follow the instructions:",source:"@site/references/Lightning CLI/update-cli-from-source-code.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/update-cli-from-source-code",permalink:"/references/Lightning CLI/update-cli-from-source-code",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/update-cli-from-source-code.md",tags:[{label:"references",permalink:"/references/tags/references"},{label:"help",permalink:"/references/tags/help"},{label:"update",permalink:"/references/tags/update"},{label:"upgrade",permalink:"/references/tags/upgrade"},{label:"fix",permalink:"/references/tags/fix"}],version:"current",lastUpdatedAt:1694784773,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Update CLI from source code",slug:"update-cli-from-source-code",hide_title:!0,tags:["references","help","update","upgrade","fix"]},sidebar:"defaultSidebar",previous:{title:"Uninstall Lightning CLI",permalink:"/references/Lightning CLI/uninstall-lightning-cli"},next:{title:"Shutting down persistance",permalink:"/references/Systemd/shutting-down-persistance"}},u={},d=[{value:"Switch to the installation user",id:"switch-to-the-installation-user",level:2},{value:"Change directory to the source code",id:"change-directory-to-the-source-code",level:2},{value:"Checkout to branch",id:"checkout-to-branch",level:2},{value:"Pull the latest changes",id:"pull-the-latest-changes",level:2},{value:"Build binary from the source",id:"build-binary-from-the-source",level:2},{value:"Update the symlink",id:"update-the-symlink",level:2},{value:"Set user path in config.toml",id:"set-user-path-in-configtoml",level:2},{value:"Update the systemd service unit",id:"update-the-systemd-service-unit",level:2},{value:"Clear the data",id:"clear-the-data",level:2},{value:"Update the config.toml with user home path",id:"update-the-configtoml-with-user-home-path",level:2},{value:"Restart the service",id:"restart-the-service",level:2},{value:"Health checkup",id:"health-checkup",level:2}],m={toc:d},g="wrapper";function k(e){let{components:t,...n}=e;return(0,o.kt)(g,(0,a.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Although the step-by-step instructions described here are simple to follow, this process is available as an automated script. To use it execute the following command in your server terminal and follow the instructions:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"curl -sS https://get.fleek.network/update | bash\n"))),(0,o.kt)("h2",{id:"switch-to-the-installation-user"},"Switch to the installation user"),(0,o.kt)("p",null,"Switch to the username you've used throughout the installation process."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"su \n")),(0,o.kt)("p",null,"For example, if you used the username ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn")," it'll look like the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"su lgtn\n")),(0,o.kt)("h2",{id:"change-directory-to-the-source-code"},"Change directory to the source code"),(0,o.kt)("p",null,"If you have installed it via the recommended process or instructions, then the default location where the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/lightning"},"source code")," is stored is ",(0,o.kt)("inlineCode",{parentName:"p"},"~/fleek-network/lightning"),"."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"cd ~/fleek-network/lightning\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Notice that we use ",(0,o.kt)("inlineCode",{parentName:"p"},"~"),", which refers to ",(0,o.kt)("inlineCode",{parentName:"p"},"$HOME"),". You must use the username used for the installation process. For example, on ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/requirements#server"},"Ubuntu")," if you use the username ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn"),", the pathname for ",(0,o.kt)("inlineCode",{parentName:"p"},"$HOME")," is ",(0,o.kt)("inlineCode",{parentName:"p"},"/home/lgtn"),".")),(0,o.kt)("h2",{id:"checkout-to-branch"},"Checkout to branch"),(0,o.kt)("p",null,"Make sure that you are checked in to the correct branch. For the current testnet phase that'd be ",(0,o.kt)("inlineCode",{parentName:"p"},"testnet-alpha-0"),". If you use any other branch name, your node will not function correctly. Use the branch name ",(0,o.kt)("inlineCode",{parentName:"p"},"testnet-alpha-0"),"."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"git checkout testnet-alpha-0\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"We try to update our documentation promptly but sometimes are a bit behind on any changes we might make in real-time. If you find any typos, such as the wrong branch name, help us by letting us know! Find us in Fleek Network section of our ",(0,o.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"Discord"),".")),(0,o.kt)("h2",{id:"pull-the-latest-changes"},"Pull the latest changes"),(0,o.kt)("p",null,"Before make sure that you stash or clear any changes you may have in the working directory, as otherwise, ",(0,o.kt)("inlineCode",{parentName:"p"},"git")," will let you know about local changes\u2013if you'd like to learn more about it read the ",(0,o.kt)("a",{parentName:"p",href:"https://git-scm.com/docs/git-stash"},"git stash document"),"."),(0,o.kt)("p",null,"A quick way to clean is to ",(0,o.kt)("inlineCode",{parentName:"p"},"stash")," the changes, for example:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"git stash \n")),(0,o.kt)("p",null,"To pull the latest changes use the ",(0,o.kt)("inlineCode",{parentName:"p"},"git pull")," command, as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"git pull origin testnet-alpha-0\n")),(0,o.kt)("p",null,"Alternatively, to have to stash and pull, you can reset the repository to the origin."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"git fetch origin testnet-alpha-0\ngit reset --hard origin/testnet-alpha-0\ngit clean -f\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"We are using the branch named ",(0,o.kt)("inlineCode",{parentName:"p"},"testnet-alpha-0"),", which is specific to the early testnet launch. Change to the correct branch name according to needs. For example, in the future the mainnet version will go on branch name ",(0,o.kt)("inlineCode",{parentName:"p"},"main"),".")),(0,o.kt)("h2",{id:"build-binary-from-the-source"},"Build binary from the source"),(0,o.kt)("p",null,"To build the binary from the source code, we execute the cargo build command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"cargo +stable build --release\n")),(0,o.kt)("h2",{id:"update-the-symlink"},"Update the symlink"),(0,o.kt)("p",null,"Start by removing the existing one:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'sudo rm -f "/usr/local/bin/lgtn"\n')),(0,o.kt)("p",null,"Create a new symlink that links the new build binary to ",(0,o.kt)("inlineCode",{parentName:"p"},"/usr/local/bin/lgtn"),", as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"sudo ln -s ~/fleek-network/lightning/target/release/lightning-node /usr/local/bin/lgtn\n")),(0,o.kt)("h2",{id:"set-user-path-in-configtoml"},"Set user path in config.toml"),(0,o.kt)(l.ZP,{mdxType:"SetUserPathInConfigToml"}),(0,o.kt)("h2",{id:"update-the-systemd-service-unit"},"Update the systemd service unit"),(0,o.kt)("p",null,"Open and edit the ",(0,o.kt)("inlineCode",{parentName:"p"},"/etc/systemd/system/lightning.service")," file."),(0,o.kt)("p",null,"1) Replace ",(0,o.kt)("inlineCode",{parentName:"p"},"")," with the username. For example, in the ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/install#create-a-user"},"documentation")," we use the username ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn"),"."),(0,o.kt)("p",null,"2) Make sure that the ",(0,o.kt)("inlineCode",{parentName:"p"},"ExecStart")," is set correctly"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"[Unit]\nDescription=Fleek Network Node lightning service\n\n[Service]\nUser=\nType=simple\nMemoryHigh=32G\nRestartSec=15s\nRestart=always\nExecStart=lgtn -c /home/lgtn/.lightning/config.toml run\nStandardOutput=append:/var/log/lightning/output.log\nStandardError=append:/var/log/lightning/diagnostic.log\nEnvironment=TMPDIR=/var/tmp\n\n[Install]\nWantedBy=multi-user.target\n")),(0,o.kt)(i.ZP,{mdxType:"NoteExecStartFlagCConfigPath"}),(0,o.kt)("p",null,"When complete make sure the file is saved. Followed by a systemctl daemon reload:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl daemon-reload\n")),(0,o.kt)("h2",{id:"clear-the-data"},"Clear the data"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"rm -rf ~/.lightning/data\n")),(0,o.kt)("p",null,"Depending on how you control the system, this might need ",(0,o.kt)("strong",{parentName:"p"},"sudo"),"."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"sudo rm -rf ~/.lightning/data\n")),(0,o.kt)("h2",{id:"update-the-configtoml-with-user-home-path"},"Update the ",(0,o.kt)("inlineCode",{parentName:"h2"},"config.toml")," with user home path"),(0,o.kt)(s.ZP,{mdxType:"FindAndReplaceConfigWithUserPaths"}),(0,o.kt)("h2",{id:"restart-the-service"},"Restart the service"),(0,o.kt)("p",null,"Once the cargo build process is completed, you have to restart the service. We're assuming you are using non-root user as ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/install#create-a-user"},"recommended"),", you won't use ",(0,o.kt)("strong",{parentName:"p"},"sudo")," to start the service. The command will look as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl restart lightning\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"If you have installed the Fleek Network lightning manually, the ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/install#systemd-service-setup"},"installation instructions")," recommended setting up a systemd service for the Fleek Network process. If you haven't, you're advised to check the instructions provided.")),(0,o.kt)("h2",{id:"health-checkup"},"Health checkup"),(0,o.kt)("p",null,"Do a quick health check by running:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'curl -w "\\p" localhost:4069/health\n')),(0,o.kt)("p",null,"If successful, you should get the response ",(0,o.kt)("inlineCode",{parentName:"p"},"OK"),", as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"OK\n")),(0,o.kt)(r.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}k.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>o});var a=n(7294);const o=e=>{let{image:t,name:n,title:o,url:r,communityMember:l=!1}=e;return a.createElement("section",{className:"author_card"},a.createElement("div",null,a.createElement("span",{className:"avatar"},a.createElement("a",{href:r,target:"_blank",alt:n},a.createElement("img",{src:t,alt:n}))),a.createElement("div",null,a.createElement("span",{className:"name"},a.createElement("a",{href:r,target:"_blank",alt:n},n)),a.createElement("span",{className:"title"},o),a.createElement("span",{className:"discord"},l?"Join our community on":"Got questions? Find us on"," ",a.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[4402],{3905:(e,t,n)=>{n.d(t,{Zo:()=>c,kt:()=>m});var a=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function r(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function l(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var s=a.createContext({}),p=function(e){var t=a.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):l(l({},t),e)),n},c=function(e){var t=p(e.components);return a.createElement(s.Provider,{value:t},e.children)},h="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return a.createElement(a.Fragment,{},t)}},d=a.forwardRef((function(e,t){var n=e.components,o=e.mdxType,r=e.originalType,s=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),h=p(n),d=o,m=h["".concat(s,".").concat(d)]||h[d]||u[d]||r;return n?a.createElement(m,l(l({ref:t},c),{},{components:n})):a.createElement(m,l({ref:t},c))}));function m(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var r=n.length,l=new Array(r);l[0]=d;var i={};for(var s in t)hasOwnProperty.call(t,s)&&(i[s]=t[s]);i.originalType=e,i[h]="string"==typeof e?e:o,l[1]=i;for(var p=2;p{n.d(t,{ZP:()=>i});var a=n(7462),o=(n(7294),n(3905));const r={toc:[]},l="wrapper";function i(e){let{components:t,...n}=e;return(0,o.kt)(l,(0,a.Z)({},r,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"In the ",(0,o.kt)("inlineCode",{parentName:"p"},"/home//.lightning/config.toml")," you'll find some and more of the following:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n')),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"The configuration properties and values presented above are a shorter version of what you'll find on your ",(0,o.kt)("strong",{parentName:"p"},"configuration.toml"),". We keep it short to make it easier to follow, do not copy and paste.")),(0,o.kt)("p",null,"Find and replace all instances of ~ in the config file ",(0,o.kt)("inlineCode",{parentName:"p"},"/home//.lightning/config.toml"),". "),(0,o.kt)("p",null,"Here's an example of how to do it using ",(0,o.kt)("strong",{parentName:"p"},"sed"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'sed -i "s|~/.lightning|/home//.lightning|g" "/home//.lightning/config.toml"\n')),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Replace the ",(0,o.kt)("inlineCode",{parentName:"p"},"")," with your username. For example, if you have followed the recommendation to ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/install#create-a-user"},"create a user")," it would look like ",(0,o.kt)("inlineCode",{parentName:"p"},"/home/lgtn/.lightning/config.toml")," for the username ",(0,o.kt)("strong",{parentName:"p"},"lgtn"),".")),(0,o.kt)("p",null,"For example, if your username is ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn")," that'd look like this:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'sed -i "s|~/.lightning|/home/lgtn/.lightning|g" "/home/lgtn/.lightning/config.toml"\n')),(0,o.kt)("p",null,"Once modified, you can run a ",(0,o.kt)("inlineCode",{parentName:"p"},"cat")," to see the content of the files to confirm it has been updated."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"cat /home/lgtn/.lightning/config.toml\n")),(0,o.kt)("p",null,"For our example where we opted in for the username ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn")," that would look like:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n')),(0,o.kt)("admonition",{title:"Warning",type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"Bear in mind that we are keeping the content of the file short to make it easier to read and follow. The content of your configuration file should look slightly different, amongst these it should contain other properties and values. You should not copy and replace the content of your files with the ones presented here.")))}i.isMDXComponent=!0},3813:(e,t,n)=>{n.d(t,{ZP:()=>i});var a=n(7462),o=(n(7294),n(3905));const r={toc:[]},l="wrapper";function i(e){let{components:t,...n}=e;return(0,o.kt)(l,(0,a.Z)({},r,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("admonition",{type:"note"},(0,o.kt)("p",{parentName:"admonition"},"The flag ",(0,o.kt)("inlineCode",{parentName:"p"},"-c")," in the ",(0,o.kt)("inlineCode",{parentName:"p"},"lightning.service")," ",(0,o.kt)("strong",{parentName:"p"},"ExecStart"),", is to provide the toml configuration file path e.g. defaults to ",(0,o.kt)("inlineCode",{parentName:"p"},"~/.lightning/config.toml"),". This is to avoid the path being determined dynamically (given path base ~ or $HOME), as users might control the systemctl service as a ",(0,o.kt)("strong",{parentName:"p"},"user")," or ",(0,o.kt)("strong",{parentName:"p"},"sudoer"),". For example, a ",(0,o.kt)("strong",{parentName:"p"},"sudoer")," would have the ",(0,o.kt)("strong",{parentName:"p"},"configuration")," set to ",(0,o.kt)("inlineCode",{parentName:"p"},"/root/.lightning/config.toml")," or ",(0,o.kt)("inlineCode",{parentName:"p"},"/home/username/.lightning/config.toml")," depending on using ",(0,o.kt)("strong",{parentName:"p"},"sudo")," which might cause some confusion to some users.")))}i.isMDXComponent=!0},2300:(e,t,n)=>{n.d(t,{ZP:()=>i});var a=n(7462),o=(n(7294),n(3905));const r={toc:[]},l="wrapper";function i(e){let{components:t,...n}=e;return(0,o.kt)(l,(0,a.Z)({},r,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"You should be following the ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/install#create-a-user-1"},"create a user")," recommendation. For our example, we have the username ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn"),"."),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"If you have chosen a different username, replace ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn")," by the correct username you have selected.")),(0,o.kt)("p",null,"In the ",(0,o.kt)("inlineCode",{parentName:"p"},"config.toml")," you'll find some and more of the following:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n')),(0,o.kt)("p",null,"Find and replace all instances of ",(0,o.kt)("inlineCode",{parentName:"p"},"~")," in the config file ",(0,o.kt)("inlineCode",{parentName:"p"},"/home/lgtn/.lightning/config.toml"),". Here's an example using ",(0,o.kt)("inlineCode",{parentName:"p"},"sed"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'sed -i "s|~/.lightning|/home/lgtn/.lightning|g" "/home/lgtn/.lightning/config.toml"\n')),(0,o.kt)("admonition",{type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"The ",(0,o.kt)("inlineCode",{parentName:"p"},"config.toml")," example below is a shorter version of what you'll encounter, yours might look different. We do this to keep the guide simple to read. Do not copy and replace with the version demonstrated here.")),(0,o.kt)("p",null,"Once changed, all the instances of ",(0,o.kt)("inlineCode",{parentName:"p"},"~/")," should be replaced by your user path e.g. ",(0,o.kt)("inlineCode",{parentName:"p"},"/home/lgtn/"),". For our example, the output would look like the following:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "/home/lgtn/.lightning/data/app_db"\n\n[consensus]\nstore_path = "/home/lgtn/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "/home/lgtn/.lightning/blockstore"\n\n[resolver]\nstore_path = "/home/lgtn/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "/home/lgtn/.lightning/keystore/consensus.pem"\nnode_key_path = "/home/lgtn/.lightning/keystore/node.pem"\n')))}i.isMDXComponent=!0},1054:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>u,contentTitle:()=>c,default:()=>k,frontMatter:()=>p,metadata:()=>h,toc:()=>d});var a=n(7462),o=(n(7294),n(3905)),r=n(3872),l=n(2300),i=n(3813),s=n(3242);const p={title:"Update CLI from source code",slug:"update-cli-from-source-code",hide_title:!0,tags:["references","help","update","upgrade","fix"]},c=void 0,h={unversionedId:"Lightning CLI/update-cli-from-source-code",id:"Lightning CLI/update-cli-from-source-code",title:"Update CLI from source code",description:"Although the step-by-step instructions described here are simple to follow, this process is available as an automated script. To use it execute the following command in your server terminal and follow the instructions:",source:"@site/references/Lightning CLI/update-cli-from-source-code.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/update-cli-from-source-code",permalink:"/references/Lightning CLI/update-cli-from-source-code",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/update-cli-from-source-code.md",tags:[{label:"references",permalink:"/references/tags/references"},{label:"help",permalink:"/references/tags/help"},{label:"update",permalink:"/references/tags/update"},{label:"upgrade",permalink:"/references/tags/upgrade"},{label:"fix",permalink:"/references/tags/fix"}],version:"current",lastUpdatedAt:1694785242,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Update CLI from source code",slug:"update-cli-from-source-code",hide_title:!0,tags:["references","help","update","upgrade","fix"]},sidebar:"defaultSidebar",previous:{title:"Uninstall Lightning CLI",permalink:"/references/Lightning CLI/uninstall-lightning-cli"},next:{title:"Shutting down persistance",permalink:"/references/Systemd/shutting-down-persistance"}},u={},d=[{value:"Switch to the installation user",id:"switch-to-the-installation-user",level:2},{value:"Change directory to the source code",id:"change-directory-to-the-source-code",level:2},{value:"Checkout to branch",id:"checkout-to-branch",level:2},{value:"Pull the latest changes",id:"pull-the-latest-changes",level:2},{value:"Build binary from the source",id:"build-binary-from-the-source",level:2},{value:"Update the symlink",id:"update-the-symlink",level:2},{value:"Set user path in config.toml",id:"set-user-path-in-configtoml",level:2},{value:"Update the systemd service unit",id:"update-the-systemd-service-unit",level:2},{value:"Clear the data",id:"clear-the-data",level:2},{value:"Update the config.toml with user home path",id:"update-the-configtoml-with-user-home-path",level:2},{value:"Restart the service",id:"restart-the-service",level:2},{value:"Health checkup",id:"health-checkup",level:2}],m={toc:d},g="wrapper";function k(e){let{components:t,...n}=e;return(0,o.kt)(g,(0,a.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Although the step-by-step instructions described here are simple to follow, this process is available as an automated script. To use it execute the following command in your server terminal and follow the instructions:"),(0,o.kt)("pre",{parentName:"admonition"},(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"curl -sS https://get.fleek.network/update | bash\n"))),(0,o.kt)("h2",{id:"switch-to-the-installation-user"},"Switch to the installation user"),(0,o.kt)("p",null,"Switch to the username you've used throughout the installation process."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"su \n")),(0,o.kt)("p",null,"For example, if you used the username ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn")," it'll look like the following command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"su lgtn\n")),(0,o.kt)("h2",{id:"change-directory-to-the-source-code"},"Change directory to the source code"),(0,o.kt)("p",null,"If you have installed it via the recommended process or instructions, then the default location where the ",(0,o.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/lightning"},"source code")," is stored is ",(0,o.kt)("inlineCode",{parentName:"p"},"~/fleek-network/lightning"),"."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"cd ~/fleek-network/lightning\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Notice that we use ",(0,o.kt)("inlineCode",{parentName:"p"},"~"),", which refers to ",(0,o.kt)("inlineCode",{parentName:"p"},"$HOME"),". You must use the username used for the installation process. For example, on ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/requirements#server"},"Ubuntu")," if you use the username ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn"),", the pathname for ",(0,o.kt)("inlineCode",{parentName:"p"},"$HOME")," is ",(0,o.kt)("inlineCode",{parentName:"p"},"/home/lgtn"),".")),(0,o.kt)("h2",{id:"checkout-to-branch"},"Checkout to branch"),(0,o.kt)("p",null,"Make sure that you are checked in to the correct branch. For the current testnet phase that'd be ",(0,o.kt)("inlineCode",{parentName:"p"},"testnet-alpha-0"),". If you use any other branch name, your node will not function correctly. Use the branch name ",(0,o.kt)("inlineCode",{parentName:"p"},"testnet-alpha-0"),"."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"git checkout testnet-alpha-0\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"We try to update our documentation promptly but sometimes are a bit behind on any changes we might make in real-time. If you find any typos, such as the wrong branch name, help us by letting us know! Find us in Fleek Network section of our ",(0,o.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"Discord"),".")),(0,o.kt)("h2",{id:"pull-the-latest-changes"},"Pull the latest changes"),(0,o.kt)("p",null,"Before make sure that you stash or clear any changes you may have in the working directory, as otherwise, ",(0,o.kt)("inlineCode",{parentName:"p"},"git")," will let you know about local changes\u2013if you'd like to learn more about it read the ",(0,o.kt)("a",{parentName:"p",href:"https://git-scm.com/docs/git-stash"},"git stash document"),"."),(0,o.kt)("p",null,"A quick way to clean is to ",(0,o.kt)("inlineCode",{parentName:"p"},"stash")," the changes, for example:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"git stash \n")),(0,o.kt)("p",null,"To pull the latest changes use the ",(0,o.kt)("inlineCode",{parentName:"p"},"git pull")," command, as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"git pull origin testnet-alpha-0\n")),(0,o.kt)("p",null,"Alternatively, to have to stash and pull, you can reset the repository to the origin."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"git fetch origin testnet-alpha-0\ngit reset --hard origin/testnet-alpha-0\ngit clean -f\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"We are using the branch named ",(0,o.kt)("inlineCode",{parentName:"p"},"testnet-alpha-0"),", which is specific to the early testnet launch. Change to the correct branch name according to needs. For example, in the future the mainnet version will go on branch name ",(0,o.kt)("inlineCode",{parentName:"p"},"main"),".")),(0,o.kt)("h2",{id:"build-binary-from-the-source"},"Build binary from the source"),(0,o.kt)("p",null,"To build the binary from the source code, we execute the cargo build command:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"cargo +stable build --release\n")),(0,o.kt)("h2",{id:"update-the-symlink"},"Update the symlink"),(0,o.kt)("p",null,"Start by removing the existing one:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'sudo rm -f "/usr/local/bin/lgtn"\n')),(0,o.kt)("p",null,"Create a new symlink that links the new build binary to ",(0,o.kt)("inlineCode",{parentName:"p"},"/usr/local/bin/lgtn"),", as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"sudo ln -s ~/fleek-network/lightning/target/release/lightning-node /usr/local/bin/lgtn\n")),(0,o.kt)("h2",{id:"set-user-path-in-configtoml"},"Set user path in config.toml"),(0,o.kt)(l.ZP,{mdxType:"SetUserPathInConfigToml"}),(0,o.kt)("h2",{id:"update-the-systemd-service-unit"},"Update the systemd service unit"),(0,o.kt)("p",null,"Open and edit the ",(0,o.kt)("inlineCode",{parentName:"p"},"/etc/systemd/system/lightning.service")," file."),(0,o.kt)("p",null,"1) Replace ",(0,o.kt)("inlineCode",{parentName:"p"},"")," with the username. For example, in the ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/install#create-a-user"},"documentation")," we use the username ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn"),"."),(0,o.kt)("p",null,"2) Make sure that the ",(0,o.kt)("inlineCode",{parentName:"p"},"ExecStart")," is set correctly"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"[Unit]\nDescription=Fleek Network Node lightning service\n\n[Service]\nUser=\nType=simple\nMemoryHigh=32G\nRestartSec=15s\nRestart=always\nExecStart=lgtn -c /home/lgtn/.lightning/config.toml run\nStandardOutput=append:/var/log/lightning/output.log\nStandardError=append:/var/log/lightning/diagnostic.log\nEnvironment=TMPDIR=/var/tmp\n\n[Install]\nWantedBy=multi-user.target\n")),(0,o.kt)(i.ZP,{mdxType:"NoteExecStartFlagCConfigPath"}),(0,o.kt)("p",null,"When complete make sure the file is saved. Followed by a systemctl daemon reload:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl daemon-reload\n")),(0,o.kt)("h2",{id:"clear-the-data"},"Clear the data"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"rm -rf ~/.lightning/data\n")),(0,o.kt)("p",null,"Depending on how you control the system, this might need ",(0,o.kt)("strong",{parentName:"p"},"sudo"),"."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"sudo rm -rf ~/.lightning/data\n")),(0,o.kt)("h2",{id:"update-the-configtoml-with-user-home-path"},"Update the ",(0,o.kt)("inlineCode",{parentName:"h2"},"config.toml")," with user home path"),(0,o.kt)(s.ZP,{mdxType:"FindAndReplaceConfigWithUserPaths"}),(0,o.kt)("h2",{id:"restart-the-service"},"Restart the service"),(0,o.kt)("p",null,"Once the cargo build process is completed, you have to restart the service. We're assuming you are using non-root user as ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/install#create-a-user"},"recommended"),", you won't use ",(0,o.kt)("strong",{parentName:"p"},"sudo")," to start the service. The command will look as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl restart lightning\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"If you have installed the Fleek Network lightning manually, the ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/install#systemd-service-setup"},"installation instructions")," recommended setting up a systemd service for the Fleek Network process. If you haven't, you're advised to check the instructions provided.")),(0,o.kt)("h2",{id:"health-checkup"},"Health checkup"),(0,o.kt)("p",null,"Do a quick health check by running:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'curl -w "\\p" localhost:4069/health\n')),(0,o.kt)("p",null,"If successful, you should get the response ",(0,o.kt)("inlineCode",{parentName:"p"},"OK"),", as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"OK\n")),(0,o.kt)(r.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}k.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>o});var a=n(7294);const o=e=>{let{image:t,name:n,title:o,url:r,communityMember:l=!1}=e;return a.createElement("section",{className:"author_card"},a.createElement("div",null,a.createElement("span",{className:"avatar"},a.createElement("a",{href:r,target:"_blank",alt:n},a.createElement("img",{src:t,alt:n}))),a.createElement("div",null,a.createElement("span",{className:"name"},a.createElement("a",{href:r,target:"_blank",alt:n},n)),a.createElement("span",{className:"title"},o),a.createElement("span",{className:"discord"},l?"Join our community on":"Got questions? Find us on"," ",a.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file diff --git a/assets/js/4d7007b2.3f406829.js b/assets/js/4d7007b2.d0f5a873.js similarity index 98% rename from assets/js/4d7007b2.3f406829.js rename to assets/js/4d7007b2.d0f5a873.js index 4db356bf6..3f75c5718 100644 --- a/assets/js/4d7007b2.3f406829.js +++ b/assets/js/4d7007b2.d0f5a873.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[6272],{3905:(e,r,t)=>{t.d(r,{Zo:()=>p,kt:()=>m});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function a(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var s=n.createContext({}),l=function(e){var r=n.useContext(s),t=r;return e&&(t="function"==typeof e?e(r):a(a({},r),e)),t},p=function(e){var r=l(e.components);return n.createElement(s.Provider,{value:r},e.children)},f="mdxType",u={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},d=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),f=l(t),d=o,m=f["".concat(s,".").concat(d)]||f[d]||u[d]||i;return t?n.createElement(m,a(a({ref:r},p),{},{components:t})):n.createElement(m,a({ref:r},p))}));function m(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=d;var c={};for(var s in r)hasOwnProperty.call(r,s)&&(c[s]=r[s]);c.originalType=e,c[f]="string"==typeof e?e:o,a[1]=c;for(var l=2;l{t.r(r),t.d(r,{assets:()=>l,contentTitle:()=>c,default:()=>d,frontMatter:()=>a,metadata:()=>s,toc:()=>p});var n=t(7462),o=(t(7294),t(3905));const i=t.p+"assets/images/banner-references-a0368a847f1d60e338779105f44a9e9a.png",a={title:"About references",hide_title:!0,sidebar_position:1,tags:["References","Help"]},c=void 0,s={unversionedId:"index",id:"index",title:"About references",description:"The references provide concise instructions to interface with the system, broken down into commands or small pieces for quick reference.",source:"@site/references/index.md",sourceDirName:".",slug:"/",permalink:"/references/",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/index.md",tags:[{label:"References",permalink:"/references/tags/references"},{label:"Help",permalink:"/references/tags/help"}],version:"current",lastUpdatedAt:1694784773,formattedLastUpdatedAt:"Sep 15, 2023",sidebarPosition:1,frontMatter:{title:"About references",hide_title:!0,sidebar_position:1,tags:["References","Help"]},sidebar:"defaultSidebar",next:{title:"Error building on ARM64",permalink:"/references/Lightning CLI/error-building-on-arm64"}},l={},p=[],f={toc:p},u="wrapper";function d(e){let{components:r,...t}=e;return(0,o.kt)(u,(0,n.Z)({},f,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("img",{className:"banner",src:i}),(0,o.kt)("p",null,"The references provide concise instructions to interface with the system, broken down into commands or small pieces for quick reference."),(0,o.kt)("p",null,"It differs from ",(0,o.kt)("a",{parentName:"p",href:"/guides"},"Guides")," which is more descriptive or verbose when providing instructions and how-to's."),(0,o.kt)("p",null,"To start, find references by consulting the available categories to locate the appropriate content on the sidebar. Our references are also available as a result when using the search feature located at the very top of the documentation site."))}d.isMDXComponent=!0}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[6272],{3905:(e,r,t)=>{t.d(r,{Zo:()=>p,kt:()=>m});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function i(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function a(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var s=n.createContext({}),l=function(e){var r=n.useContext(s),t=r;return e&&(t="function"==typeof e?e(r):a(a({},r),e)),t},p=function(e){var r=l(e.components);return n.createElement(s.Provider,{value:r},e.children)},f="mdxType",u={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},d=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,i=e.originalType,s=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),f=l(t),d=o,m=f["".concat(s,".").concat(d)]||f[d]||u[d]||i;return t?n.createElement(m,a(a({ref:r},p),{},{components:t})):n.createElement(m,a({ref:r},p))}));function m(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var i=t.length,a=new Array(i);a[0]=d;var c={};for(var s in r)hasOwnProperty.call(r,s)&&(c[s]=r[s]);c.originalType=e,c[f]="string"==typeof e?e:o,a[1]=c;for(var l=2;l{t.r(r),t.d(r,{assets:()=>l,contentTitle:()=>c,default:()=>d,frontMatter:()=>a,metadata:()=>s,toc:()=>p});var n=t(7462),o=(t(7294),t(3905));const i=t.p+"assets/images/banner-references-a0368a847f1d60e338779105f44a9e9a.png",a={title:"About references",hide_title:!0,sidebar_position:1,tags:["References","Help"]},c=void 0,s={unversionedId:"index",id:"index",title:"About references",description:"The references provide concise instructions to interface with the system, broken down into commands or small pieces for quick reference.",source:"@site/references/index.md",sourceDirName:".",slug:"/",permalink:"/references/",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/index.md",tags:[{label:"References",permalink:"/references/tags/references"},{label:"Help",permalink:"/references/tags/help"}],version:"current",lastUpdatedAt:1694785242,formattedLastUpdatedAt:"Sep 15, 2023",sidebarPosition:1,frontMatter:{title:"About references",hide_title:!0,sidebar_position:1,tags:["References","Help"]},sidebar:"defaultSidebar",next:{title:"Error building on ARM64",permalink:"/references/Lightning CLI/error-building-on-arm64"}},l={},p=[],f={toc:p},u="wrapper";function d(e){let{components:r,...t}=e;return(0,o.kt)(u,(0,n.Z)({},f,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("img",{className:"banner",src:i}),(0,o.kt)("p",null,"The references provide concise instructions to interface with the system, broken down into commands or small pieces for quick reference."),(0,o.kt)("p",null,"It differs from ",(0,o.kt)("a",{parentName:"p",href:"/guides"},"Guides")," which is more descriptive or verbose when providing instructions and how-to's."),(0,o.kt)("p",null,"To start, find references by consulting the available categories to locate the appropriate content on the sidebar. Our references are also available as a result when using the search feature located at the very top of the documentation site."))}d.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/5437f376.c438d632.js b/assets/js/5437f376.a22ff3c5.js similarity index 99% rename from assets/js/5437f376.c438d632.js rename to assets/js/5437f376.a22ff3c5.js index a0bcd7923..388d5d4fd 100644 --- a/assets/js/5437f376.c438d632.js +++ b/assets/js/5437f376.a22ff3c5.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[909],{3905:(e,t,n)=>{n.d(t,{Zo:()=>h,kt:()=>m});var i=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function r(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=i.createContext({}),p=function(e){var t=i.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},h=function(e){var t=p(e.components);return i.createElement(l.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},c=i.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,h=s(e,["components","mdxType","originalType","parentName"]),d=p(n),c=a,m=d["".concat(l,".").concat(c)]||d[c]||u[c]||o;return n?i.createElement(m,r(r({ref:t},h),{},{components:n})):i.createElement(m,r({ref:t},h))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,r=new Array(o);r[0]=c;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:a,r[1]=s;for(var p=2;p{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>s,default:()=>c,frontMatter:()=>r,metadata:()=>l,toc:()=>h});var i=n(7462),a=(n(7294),n(3905)),o=n(3872);const r={hide_title:!0,title:"Managing the keystore",slug:"managing-the-keystore",date:new Date("2023-11-14T12:00:00.000Z"),description:"The following will guide you through some of the fundamentals to help understand how to manage the key store at the very basics, and help you persist the key store identity, in any supported system you\u2019re migrating to",category:"Tutorial",tags:["guide","keystore","public keys","private keys","keys"]},s=void 0,l={unversionedId:"Node Operators/managing-the-keystore",id:"Node Operators/managing-the-keystore",title:"Managing the keystore",description:"The following will guide you through some of the fundamentals to help understand how to manage the key store at the very basics, and help you persist the key store identity, in any supported system you\u2019re migrating to",source:"@site/guides/Node Operators/managing-the-keystore.md",sourceDirName:"Node Operators",slug:"/Node Operators/managing-the-keystore",permalink:"/guides/Node Operators/managing-the-keystore",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/guides/Node Operators/managing-the-keystore.md",tags:[{label:"guide",permalink:"/guides/tags/guide"},{label:"keystore",permalink:"/guides/tags/keystore"},{label:"public keys",permalink:"/guides/tags/public-keys"},{label:"private keys",permalink:"/guides/tags/private-keys"},{label:"keys",permalink:"/guides/tags/keys"}],version:"current",lastUpdatedAt:1694784773,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{hide_title:!0,title:"Managing the keystore",slug:"managing-the-keystore",date:"2023-11-14T12:00:00.000Z",description:"The following will guide you through some of the fundamentals to help understand how to manage the key store at the very basics, and help you persist the key store identity, in any supported system you\u2019re migrating to",category:"Tutorial",tags:["guide","keystore","public keys","private keys","keys"]},sidebar:"defaultSidebar",previous:{title:"Getting Started",permalink:"/guides/Node Operators/getting-started"},next:{title:"Transfering setup ownership",permalink:"/guides/Node Operators/transfering-setup-ownership"}},p={},h=[{value:"Introduction",id:"introduction",level:2},{value:"Pre-requisites",id:"pre-requisites",level:2},{value:"Configuration file",id:"configuration-file",level:2},{value:"Locating the file",id:"locating-the-file",level:3},{value:"Configuration sections",id:"configuration-sections",level:3},{value:"Type of keys",id:"type-of-keys",level:3},{value:"Key privacy",id:"key-privacy",level:3},{value:"Identity selection",id:"identity-selection",level:3},{value:"Backing up the keystore",id:"backing-up-the-keystore",level:2},{value:"Lower security",id:"lower-security",level:3},{value:"Higher security",id:"higher-security",level:3},{value:"Storage",id:"storage",level:3},{value:"Loading keys on runtime",id:"loading-keys-on-runtime",level:2},{value:"Conclusion",id:"conclusion",level:2}],d={toc:h},u="wrapper";function c(e){let{components:t,...n}=e;return(0,a.kt)(u,(0,i.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"introduction"},"Introduction"),(0,a.kt)("p",null,"Fleek Network incentivizes participation by rewarding its node providers. A node is identifiable by an identity, which the reward mechanism uses to identify the node to reward it."),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"At time of writing the rewards mechanism hasn't yet been introduced, read the ",(0,a.kt)("a",{parentName:"p",href:"https://blog.fleek.network/post/fleek-network-testnet-plans"},"testnet plans")," to get a high level perspective over the plans. A token and economics paper should be released in the future.")),(0,a.kt)("p",null,"We'll use the term identity to describe the key store declared in the configuration, in our case ",(0,a.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail"},"PEM")," files. The content of the PEM files and the file itself should be kept secret."),(0,a.kt)("p",null,"The key store is in the file system and the location is defined in the Fleek Network ",(0,a.kt)("inlineCode",{parentName:"p"},"~/.lightning/config.toml"),", as a private key stored in an identity named PEM file (by default ",(0,a.kt)("inlineCode",{parentName:"p"},"consensus.pem")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"node.pem"),"). It's essential to understand this, as you may want to copy the identity to a new server setup, to persist the identity accross to the new server setup."),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"Security is achieved by issuing users private cryptographic keys. Only the holder of the private key has access to sensitive information, such as an identity, which relates to reputation, rewards, etc. The security of the private key is the responsibility of the user. Unfortunately, Fleek Network is unable to help you regain access to your private key if you've lost or failed to secure it. The private keys are your responsibility.")),(0,a.kt)("p",null,"The following will guide you through some of the fundamentals to help understand how to manage the key store at the very basics, and help you persist the key store identity, in any ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/requirements#server"},"supported system")," you're migrating to."),(0,a.kt)("h2",{id:"pre-requisites"},"Pre-requisites"),(0,a.kt)("p",null,"To follow the guide, you will need the following:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Familiarity with the command-line interface"),(0,a.kt)("li",{parentName:"ul"},"A basic understanding of ",(0,a.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Public-key_cryptography"},"how public key cryptography works"))),(0,a.kt)("h2",{id:"configuration-file"},"Configuration file"),(0,a.kt)("h3",{id:"locating-the-file"},"Locating the file"),(0,a.kt)("p",null,"The Lightning CLI has a configuration file in the home directory of the user, which by default is located in the path ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning")," or ",(0,a.kt)("inlineCode",{parentName:"p"},"~/.lightning")," under the name ",(0,a.kt)("inlineCode",{parentName:"p"},"config.toml"),". It's generally described as ",(0,a.kt)("inlineCode",{parentName:"p"},"~/.lightning/config.toml"),"."),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"The tilde in ",(0,a.kt)("inlineCode",{parentName:"p"},"~/.lightning")," represents ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME")," which is simpler, but we'll use ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME")," to make it easy to follow.")),(0,a.kt)("p",null,"If you're following the install recommendations you should be logged in with a ",(0,a.kt)("strong",{parentName:"p"},"sudoer")," account. For our guide, let's imagine that the ",(0,a.kt)("strong",{parentName:"p"},"sudoer")," username we are logged in with is ",(0,a.kt)("strong",{parentName:"p"},"lgtn"),"."),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"The word ",(0,a.kt)("strong",{parentName:"p"},"sudo"),' is the abbreviation of the term "super user do". As the name suggests, it is the privilege that a super user, such as an administrator has to do whatever it wants in the system. A super user can be an administrator, like the ',(0,a.kt)("strong",{parentName:"p"},"root")," or what we described here as a user in the group ",(0,a.kt)("strong",{parentName:"p"},"sudo")," aka ",(0,a.kt)("strong",{parentName:"p"},"sudoer"),".")),(0,a.kt)("p",null,"If you are logged in with a username, that'd be:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"/home//.lightning/config.toml\n")),(0,a.kt)("p",null,"For our example for user ",(0,a.kt)("inlineCode",{parentName:"p"},"lgtn")," that is:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"/home/lgtn/.lightning/config.toml\n")),(0,a.kt)("p",null,"If you log in with another user, let's say ",(0,a.kt)("inlineCode",{parentName:"p"},"fleek")," it'd be:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"/home/fleek/.lightning/config.toml\n")),(0,a.kt)("p",null,"At any time, you can check which user you are logged in with by running the command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"whoami\n")),(0,a.kt)("p",null,"Here's an example of our user ",(0,a.kt)("inlineCode",{parentName:"p"},"lgtn"),", which for the command above outputs:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn\n")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"To switch to a particular user, you can run the command ",(0,a.kt)("inlineCode",{parentName:"p"},"su ")," e.g. for the user ",(0,a.kt)("strong",{parentName:"p"},"lgtn")," we would execute the command ",(0,a.kt)("inlineCode",{parentName:"p"},"su lgtn"),".")),(0,a.kt)("p",null,"Now that you know where to locate the configuration file for any given user you are logged in with, learn about the ",(0,a.kt)("a",{parentName:"p",href:"#configuration-sections"},"Configuration sections"),"."),(0,a.kt)("h3",{id:"configuration-sections"},"Configuration sections"),(0,a.kt)("p",null,"The Fleek Network node configuration settings are located in the path ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/config.toml"),", and it's organized by configuration sections."),(0,a.kt)("p",null,"At the time of writing, we have a TOML file with sections. Here are some examples amongst others:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"application"),(0,a.kt)("li",{parentName:"ul"},"origin-ipfs"),(0,a.kt)("li",{parentName:"ul"},"rpc"),(0,a.kt)("li",{parentName:"ul"},"signer")),(0,a.kt)("p",null,"Each of the sections holds several property names and values. If you are accustomed to the ",(0,a.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/JSON"},"JSON")," or ",(0,a.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/YAML"},"YAML")," formats, you'll find the TOML format a bit similar (if you'd like to learn more about the TOML file format, read about it ",(0,a.kt)("a",{parentName:"p",href:"https://toml.io/en/"},"here"),")."),(0,a.kt)("p",null,"By default and at time of writting the Lightning CLI configuration file (config.toml) is similar to:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'[BLANK]\n\n[application]\ndb_path = "/home/lgtn/.lightning/data/app_db"\nmode = "Prod"\nstorage = "RocksDb"\ntestnet = true\n\n[blockserver]\naddress = "0.0.0.0:4211"\n\n[broadcast]\naddress = "0.0.0.0:4200"\n\n[consensus]\nstore_path = "/home/lgtn/.lightning/data/narwhal_store"\n\n[dht]\naddress = "0.0.0.0:8101"\nbootstrappers = []\n\n[fetcher]\n\n[fsstore]\nroot = "/home/lgtn/.lightning/blockstore"\n\n[[handshake.transport]]\nsignal_address = "0.0.0.0:4210"\ntype = "WebRTC"\n\n[[handshake.worker]]\ntype = "AsyncWorker"\n\n[[handshake.worker]]\ntype = "AsyncWorker"\n\n[[handshake.worker]]\ntype = "AsyncWorker"\n\n[[handshake.worker]]\ntype = "AsyncWorker"\n\n[[origin-ipfs.gateways]]\nauthority = "ipfs.io"\nprotocol = "Https"\n\n[[origin-ipfs.gateways]]\nauthority = "fleek.ipfs.io"\nprotocol = "Https"\n\n[[origin-ipfs.gateways]]\nauthority = "ipfs.runfission.com"\nprotocol = "Https"\n\n[rep-collector]\nreporter_buffer_size = 5\n\n[resolver]\nstore_path = "/home/lgtn/.lightning/data/resolver_store"\n\n[rpc]\naddr = "0.0.0.0"\nport = 4069\n\n[service-executor]\nservices = [0, 1]\n\n[signer]\nconsensus_key_path = "/home/lgtn/.lightning/keystore/consensus.pem"\nnode_key_path = "/home/lgtn/.lightning/keystore/node.pem"\n\n[topology]\ntesting_min_nodes = 9\ntesting_target_k = 8\n')),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"Beware that the configuration file might look a bit different depending on the version you're running and the current development features in place by the Fleek Network core team. You shouldn't copy the example above and replace with yours, as this only servers for illustrative purposes.")),(0,a.kt)("p",null,"Some advanced use cases might require dealing with the host and port number binding, depending on the service provider's needs and customization. We'll keep things simple and assume the default settings."),(0,a.kt)("p",null,"In this guide, we are interested in the ",(0,a.kt)("inlineCode",{parentName:"p"},"[signer]")," section settings for the ",(0,a.kt)("inlineCode",{parentName:"p"},"consensus_key_path")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"node_key_path")," which by default is set to ",(0,a.kt)("inlineCode",{parentName:"p"},"~/.lightning/keystore"),"."),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"The identity is a text description for the Keystore and at the time of writing we have not yet implemented multiple identity management via the CLI. Thereupon, the identity value serves to find the filename match in the ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore_path"),". This might change as we progress with development. Check the ",(0,a.kt)("a",{parentName:"p",href:"#identity-selection"},"Identity selection")," to learn more about it!")),(0,a.kt)("h3",{id:"type-of-keys"},"Type of keys"),(0,a.kt)("p",null,"There are three types of keys related to the identity of a node and the account ownership. The keys are based in public-key cryptography, or asymmetric cryptography where each key pair consists of a public key and a corresponding private key. The keys are described in the section ",(0,a.kt)("a",{parentName:"p",href:"docs/learn/the-network/#identity-on-the-fleek-network"},"identity on the Fleek Network")," as follows:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"A Node key (ConsensusPublicKey) is ",(0,a.kt)("a",{parentName:"p",href:"https://electriccoin.co/blog/new-snark-curve/"},"BLS12-381")," which facilitates the consensus algorithm or persistence of state, resilience and fault tolerance. Has multi-signature support, the ability to aggregate many signatures into one used for consensus committee when signing certificates")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"A Node Networking key (NodePublicKey) is ",(0,a.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/EdDSA"},"Ed25519")," used for the speed and performance of the network communications")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Account Owner keys are based on ",(0,a.kt)("a",{parentName:"p",href:"https://www.secg.org/sec2-v2.pdf"},"secp256k1"),", which corresponds to an Ethereum Address"))),(0,a.kt)("p",null,"For instance, a public key is open to anybody to see and it represents a unique node identifier in the Fleek Network, a bit like a passport number. On the other hand, the private key is secret and the operator is responsible to store it privately."),(0,a.kt)("p",null,"The Fleek Network relies on cryptography, thus the Fleek Network team and anybody can access, compromise or manipulate the secrets of an identity. On the other hand, the public key can be used by anyone, Fleek Network included, to identify a node or send rewards to the address without jeopardizing identity security."),(0,a.kt)("p",null,"To learn more about the identities on the Fleek Network ",(0,a.kt)("a",{parentName:"p",href:"docs/learn/the-network/#identity-on-the-fleek-network"},"here"),"."),(0,a.kt)("h3",{id:"key-privacy"},"Key privacy"),(0,a.kt)("p",null,"If you don\u2019t keep your private keys secret, you'll have your node compromised."),(0,a.kt)("p",null,"Here are a few examples of what you should not do:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Share the ",(0,a.kt)("inlineCode",{parentName:"li"},"$HOME/.lightning/keystore")," directory file content publicly"),(0,a.kt)("li",{parentName:"ul"},"Track the ",(0,a.kt)("inlineCode",{parentName:"li"},"$HOME/.lightning/keystore")," directory files in a version control repository e.g. git"),(0,a.kt)("li",{parentName:"ul"},'Have poor "rights" permissions in UNIX systems e.g. everyone can read, delete, modify ',(0,a.kt)("inlineCode",{parentName:"li"},"$HOME/.lightning")),(0,a.kt)("li",{parentName:"ul"},"Allow anyone to access the node provider physically without any access control to the operating and file systems e.g. a VPS provider"),(0,a.kt)("li",{parentName:"ul"},"Get rid of a hard drive unformatted or blind erased by selling to somebody or dumping in the bin, which contains ",(0,a.kt)("inlineCode",{parentName:"li"},"$HOME/.lightning/keystore"))),(0,a.kt)("p",null,"There are many other ways of getting compromised, but hopefully, the ones put above give you a good starter into the subject."),(0,a.kt)("p",null,"Remember, the node provider is the only one responsible when managing the key store. Neither Fleek Network nor the most sophisticated AI system presently can compromise the cryptography in use to help you out. You are fully responsible for securing and retaining your private keys."),(0,a.kt)("h3",{id:"identity-selection"},"Identity selection"),(0,a.kt)("p",null,"Multiple identity management is yet to be implemented but in any case, some users might find it trivial to keep multiple identities and switch between them referencing them by name. The following section is not advocating this approach but sharing some approaches that can help certain use-cases."),(0,a.kt)("p",null,"Let's suppose that we've recently moved to a new server setup and copied our previous server keystore keys as ",(0,a.kt)("inlineCode",{parentName:"p"},"consensus.pem")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"node.pem")," and renamed the ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/keystore/*.pem")," to ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/keystore/new-*.pem"),"."),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"We are using a wildcard ",(0,a.kt)("inlineCode",{parentName:"p"},"*")," to reduce verbosity. The wildcard means as replacement for all the filenames encountered in the path and extension without having to name them individually as we know they are ",(0,a.kt)("inlineCode",{parentName:"p"},"consensus.pem")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"node.pem"),".")),(0,a.kt)("p",null,"To illustrate this scenario, here's an example of how our ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/keystore")," directory could look like:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},".\n\u251c\u2500\u2500 new-consensus.pem\n\u251c\u2500\u2500 new-node.pem\n\u2514\u2500\u2500 old-consensus.pem\n\u2514\u2500\u2500 old-node.pem\n\n0 directories, 4 file\n")),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"old-*.pem")," files are the original key store and ",(0,a.kt)("inlineCode",{parentName:"p"},"new-*.pem")," could correspond to the new identity created while setting up the node in the new server."),(0,a.kt)("p",null,"Since we have ",(0,a.kt)("inlineCode",{parentName:"p"},"[signer]")," set to the default values, in particular:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-toml"},'[signer]\nconsensus_key_path = "/home/lgtn/.lightning/keystore/consensus.pem"\nnode_key_path = "/home/lgtn/.lightning/keystore/node.pem"\n')),(0,a.kt)("p",null,"We'd be required to change and switch to the preferred keys. The identity is switch to the provided values once the node is restarted. Thus, we can switch to any identity by changing the ",(0,a.kt)("inlineCode",{parentName:"p"},"[signer]")," ",(0,a.kt)("inlineCode",{parentName:"p"},"consensus_key_path")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"node_key_path")," pathname values anytime as long we restart the server successfully."),(0,a.kt)("p",null,"To verify which keys are loaded by the Lightning CLI run the command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn keys show\n")),(0,a.kt)("p",null,"You'd find the public keys in the output, which can be used for comparision and should be different everytime the configuration changes and reloaded. Here's an example of the output:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"Node Public Key: RwPpr35H5AAfWwSDFxwYuJv5TA8PWUd2pdBg+UKsORc=\nConsensus Public Key: s36g09qQzaaOJxi0UZDRCXj3HUUWjaGiYrQV6Ylo9Ih6jMvrnxM5s1OpBnsEj5R1AVYcuxlnVR+oyEjgJ3WpI5LOHSN1Q6Zur33vka3IachBEIKIbsiXMJW16vu4n4bG\n")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"The PEM files can be named as you wish, but by default we like to keep it sound to avoid confusion and make it as clear as possible.")),(0,a.kt)("h2",{id:"backing-up-the-keystore"},"Backing up the keystore"),(0,a.kt)("p",null,"When dealing with Fleek Network it's crucial to always be aware of the identity. You should backup private keys in case the unexpected happens, as it's impossible to recover the identity in any other way, including the core team, any other person or system."),(0,a.kt)("p",null,"Backing up your keystore pem files are crucial to ensure the safety and accessibility of your identity on the Fleek Network. For example, if your ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning")," is deleted you'll still be able to restore it if you have backed it up properly."),(0,a.kt)("p",null,"There are many ways to make identity backups, each with its own benefits and drawbacks. At risk of oversimplifying, we'll focus on a simple manual approach to expose some of the principles you should be have awareness."),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"The security is never stronger than its weakest link, and it is very likely that the weakest link is not the method itself. It's pointless to encrypt the backup archive with sophisticated methods when the passphrase is weak or of an easy guess.")),(0,a.kt)("p",null,"None of the methods described here are being endorsed by the Fleek Network team use the knowledge provided here for educational purposes only and at your own risk."),(0,a.kt)("h3",{id:"lower-security"},"Lower security"),(0,a.kt)("p",null,"If you opt for the lowest level of security, you can use zip and unzip. The man page of zip described the encryption algorithm used to be weaker than PGP."),(0,a.kt)("p",null,"To zip and encrypto the ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/keystore")," directory run:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"# It'll prompt for password (remember)\nzip --encrypt -r keystore.zip.enc $HOME/.lightning/keystore\n")),(0,a.kt)("p",null,"To unzip and decrypt the ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore.zip.enc"),", you'd run:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"# It'll prompt for password (recall)\nunzip keystore.zip.enc -d $HOME/.lightning/keystore\n")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"We provide the unzip destiny target to the flag ",(0,a.kt)("inlineCode",{parentName:"p"},"-d"),". The unzip process outputs the files onto the desired location ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/keystore"),", thus overriding any contents. If you have any files in the destiny target directory it'll be overriden, effectively replacing with the output of the unzipped directory content, so make sure you backup any files as required.")),(0,a.kt)("h3",{id:"higher-security"},"Higher security"),(0,a.kt)("p",null,"Create a ",(0,a.kt)("inlineCode",{parentName:"p"},"Tar")," archive, which will contain the target directory, files and the Tar stores all of the relative paths in the tarball itself."),(0,a.kt)("p",null,"Create a ",(0,a.kt)("inlineCode",{parentName:"p"},"tarbar")," by executing:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'tar -cf "keystore.tar" $HOME/.lightning/keystore\n')),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore.tar")," should be in the current work directory."),(0,a.kt)("p",null,"Use ",(0,a.kt)("inlineCode",{parentName:"p"},"gpg")," with the ",(0,a.kt)("a",{parentName:"p",href:"ttps://www.gnupg.org/gph/en/manual/x110.html"},"symmetric option"),", it creates the keys for that file and request a password to protect them. If you are familiar with assymetric ",(0,a.kt)("inlineCode",{parentName:"p"},"gpg"),", it's similar but it's not signed with your public key or such."),(0,a.kt)("p",null,"The encryption command is:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"sudo gpg -a --symmetric --cipher-algo AES256 keystore.tar\n")),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore.tar.asc")," should be in the current work directory."),(0,a.kt)("p",null,"To decrypt the ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore.tar.asc")," file, enter:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"sudo gpg -a --output keystore.tar --decrypt keystore.tar.asc\n")),(0,a.kt)("p",null,"To extract the ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore.tar")," is simple, but be aware that it unarchives with the original directory structure, which might be a bit confusing. So, we'll create a new temporary directory for our example that will use to extract to."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"mkdir $HOME/tar_keystore_extract\n")),(0,a.kt)("p",null,"Now, run the command to extract to the target directory, as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"tar -xf keystore.tar -C $HOME/tar_keystore_extract\n")),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"/home//.lightning/keystore")," should be in the ",(0,a.kt)("inlineCode",{parentName:"p"},"tar_keystore_extract")," directory where you'll find the PEM files."),(0,a.kt)("h3",{id:"storage"},"Storage"),(0,a.kt)("p",null,"The backup archive should only be accessible by yourself. If you decided to store it in a cloud storage provider, be aware of increased security risks. Cloud storage is convenient, but it ultimately puts data into the hands of others. If you're not particularly concerned, or have confidence about the encryption of the files, then that's at your own risk. But it's recommended to store in a physical hard drive that remains disconnected from computers and network devices."),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"If you use cloud storage to store your sensitive data, encryption should be your first line of defense. Encrypting files before uploading them to the cloud is crucial to reduce others from accessing information without your permissions and knowledge.")),(0,a.kt)("p",null,"Remember that the security of the private key is the responsibility of the user. Unfortunately, the Fleek Network team and any others are unable to help regain access to private key if lost or failed to secure them. The private keys are the user responsibility. The Fleek Network team doesn't endorse any methods of encryption and storage, the methods described here are for educational purposes only."),(0,a.kt)("h2",{id:"loading-keys-on-runtime"},"Loading keys on runtime"),(0,a.kt)("p",null,"As described in the section ",(0,a.kt)("a",{parentName:"p",href:"#configuration-file"},"configuration files")," the default location of the ",(0,a.kt)("inlineCode",{parentName:"p"},".lightning")," system configuration directory is ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning"),"."),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/config.toml")," holds the information of where the Lightning CLI node process should pull the keystore pem files. The location of the pem files can be placed anywhere the node process has permissions to read."),(0,a.kt)("p",null,"When unarchiving the backup files, the keystore directory or pem files should be placed in the directory declared in the ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/config.toml"),". That is if the location is the one specified on the runtime\u2013the command declared to launch and run the lightning service, that has the optional ",(0,a.kt)("inlineCode",{parentName:"p"},"-c")," configuration flag that takes any custom location which overrides the default ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/config.toml"),"."),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"On runtime, the Lightning service can have specified a configuration file in any readable location. If a configuration pathname isn't passed, it'll default to the ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/config.toml"),". It's important to understand this to avoid confusion."),(0,a.kt)("p",{parentName:"admonition"},"The service that starts with:"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn -c /root/custom-configuration.toml run\n")),(0,a.kt)("p",{parentName:"admonition"},"Can have complete different settings from any of the following:"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn -c /home/lgtn/.lightning/config.toml run\n")),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn -c ~/.lightning/config.toml run\n")),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn run\n")),(0,a.kt)("p",{parentName:"admonition"},"Due to the fact that any of the fails above might contain different settings declared in the file body.")),(0,a.kt)("p",null,"For instance, we can imagine a scenario where our service is started with the command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn -c /home/lgtn/.lightning/config.toml run\n")),(0,a.kt)("p",null,"Where the ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore")," is placed under the parent directory ",(0,a.kt)("inlineCode",{parentName:"p"},"/home/lgtn/.lightning/"),". Resulting in the configuration file have the following settings for the hypotetical username ",(0,a.kt)("inlineCode",{parentName:"p"},"lgtn"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'[signer]\nconsensus_key_path = "/home/lgtn/.lightning/keystore/consensus.pem"\nnode_key_path = "/home/lgtn/.lightning/keystore/node.pem"\n')),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"On the ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/install"},"install instructions")," provided by the documentation, a ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/Install/#systemd-service-setup"},"Systemd service unit")," is recommended to allow the user control the Lightning service via systemctl. The Systemd service unit file should contain the recommended usage of ",(0,a.kt)("inlineCode",{parentName:"p"},"-c")," configuration. If you have followed the recommendations it should be familiar.")),(0,a.kt)("h2",{id:"conclusion"},"Conclusion"),(0,a.kt)("p",null,"We've walked through most basics of where the configuration file is located, the configuration settings we use to set up and run the node, the different configuration sections we have, and most importantly the identity section."),(0,a.kt)("p",null,"Additionally, a brief guide on the ",(0,a.kt)("a",{parentName:"p",href:"#identity"},"identity"),", more specifically an introduction to the ",(0,a.kt)("a",{parentName:"p",href:"#type-of-keys"},"type of keys")," and ",(0,a.kt)("a",{parentName:"p",href:"#key-privacy"},"key privacy"),", which we find important to understand for anyone seriously interested in running a node by hinting into some system administration and security principles."),(0,a.kt)("p",null,"Separatily, at risk of oversimpliying provided an brief introduction into the backup of the keystore directory."),(0,a.kt)("p",null,"In the future, we'll introduce more advanced topics that will help you improve the knowledge you get from this, but we are glad that you followed this guide and got some comprehension to help you manage the key store."),(0,a.kt)("p",null,"While we do our best to provide the clearest instructions, there's always space for improvement, therefore feel free to make any contributions by messaging us on our ",(0,a.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"Discord")," or by opening a ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/fleek-network"},"PR")," in any of our repositories."),(0,a.kt)("p",null,"Discover more about the project by ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/lightning"},"watching/contributing on Github"),", following us on ",(0,a.kt)("a",{parentName:"p",href:"https://twitter.com/fleek_net"},"Twitter"),", and joining ",(0,a.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"our community Discord")," for all the best updates!"),(0,a.kt)(o.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}c.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>a});var i=n(7294);const a=e=>{let{image:t,name:n,title:a,url:o,communityMember:r=!1}=e;return i.createElement("section",{className:"author_card"},i.createElement("div",null,i.createElement("span",{className:"avatar"},i.createElement("a",{href:o,target:"_blank",alt:n},i.createElement("img",{src:t,alt:n}))),i.createElement("div",null,i.createElement("span",{className:"name"},i.createElement("a",{href:o,target:"_blank",alt:n},n)),i.createElement("span",{className:"title"},a),i.createElement("span",{className:"discord"},r?"Join our community on":"Got questions? Find us on"," ",i.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[909],{3905:(e,t,n)=>{n.d(t,{Zo:()=>h,kt:()=>m});var i=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function o(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,i)}return n}function r(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(i=0;i=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var l=i.createContext({}),p=function(e){var t=i.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):r(r({},t),e)),n},h=function(e){var t=p(e.components);return i.createElement(l.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return i.createElement(i.Fragment,{},t)}},c=i.forwardRef((function(e,t){var n=e.components,a=e.mdxType,o=e.originalType,l=e.parentName,h=s(e,["components","mdxType","originalType","parentName"]),d=p(n),c=a,m=d["".concat(l,".").concat(c)]||d[c]||u[c]||o;return n?i.createElement(m,r(r({ref:t},h),{},{components:n})):i.createElement(m,r({ref:t},h))}));function m(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var o=n.length,r=new Array(o);r[0]=c;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:a,r[1]=s;for(var p=2;p{n.r(t),n.d(t,{assets:()=>p,contentTitle:()=>s,default:()=>c,frontMatter:()=>r,metadata:()=>l,toc:()=>h});var i=n(7462),a=(n(7294),n(3905)),o=n(3872);const r={hide_title:!0,title:"Managing the keystore",slug:"managing-the-keystore",date:new Date("2023-11-14T12:00:00.000Z"),description:"The following will guide you through some of the fundamentals to help understand how to manage the key store at the very basics, and help you persist the key store identity, in any supported system you\u2019re migrating to",category:"Tutorial",tags:["guide","keystore","public keys","private keys","keys"]},s=void 0,l={unversionedId:"Node Operators/managing-the-keystore",id:"Node Operators/managing-the-keystore",title:"Managing the keystore",description:"The following will guide you through some of the fundamentals to help understand how to manage the key store at the very basics, and help you persist the key store identity, in any supported system you\u2019re migrating to",source:"@site/guides/Node Operators/managing-the-keystore.md",sourceDirName:"Node Operators",slug:"/Node Operators/managing-the-keystore",permalink:"/guides/Node Operators/managing-the-keystore",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/guides/Node Operators/managing-the-keystore.md",tags:[{label:"guide",permalink:"/guides/tags/guide"},{label:"keystore",permalink:"/guides/tags/keystore"},{label:"public keys",permalink:"/guides/tags/public-keys"},{label:"private keys",permalink:"/guides/tags/private-keys"},{label:"keys",permalink:"/guides/tags/keys"}],version:"current",lastUpdatedAt:1694785242,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{hide_title:!0,title:"Managing the keystore",slug:"managing-the-keystore",date:"2023-11-14T12:00:00.000Z",description:"The following will guide you through some of the fundamentals to help understand how to manage the key store at the very basics, and help you persist the key store identity, in any supported system you\u2019re migrating to",category:"Tutorial",tags:["guide","keystore","public keys","private keys","keys"]},sidebar:"defaultSidebar",previous:{title:"Getting Started",permalink:"/guides/Node Operators/getting-started"},next:{title:"Transfering setup ownership",permalink:"/guides/Node Operators/transfering-setup-ownership"}},p={},h=[{value:"Introduction",id:"introduction",level:2},{value:"Pre-requisites",id:"pre-requisites",level:2},{value:"Configuration file",id:"configuration-file",level:2},{value:"Locating the file",id:"locating-the-file",level:3},{value:"Configuration sections",id:"configuration-sections",level:3},{value:"Type of keys",id:"type-of-keys",level:3},{value:"Key privacy",id:"key-privacy",level:3},{value:"Identity selection",id:"identity-selection",level:3},{value:"Backing up the keystore",id:"backing-up-the-keystore",level:2},{value:"Lower security",id:"lower-security",level:3},{value:"Higher security",id:"higher-security",level:3},{value:"Storage",id:"storage",level:3},{value:"Loading keys on runtime",id:"loading-keys-on-runtime",level:2},{value:"Conclusion",id:"conclusion",level:2}],d={toc:h},u="wrapper";function c(e){let{components:t,...n}=e;return(0,a.kt)(u,(0,i.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"introduction"},"Introduction"),(0,a.kt)("p",null,"Fleek Network incentivizes participation by rewarding its node providers. A node is identifiable by an identity, which the reward mechanism uses to identify the node to reward it."),(0,a.kt)("admonition",{type:"info"},(0,a.kt)("p",{parentName:"admonition"},"At time of writing the rewards mechanism hasn't yet been introduced, read the ",(0,a.kt)("a",{parentName:"p",href:"https://blog.fleek.network/post/fleek-network-testnet-plans"},"testnet plans")," to get a high level perspective over the plans. A token and economics paper should be released in the future.")),(0,a.kt)("p",null,"We'll use the term identity to describe the key store declared in the configuration, in our case ",(0,a.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail"},"PEM")," files. The content of the PEM files and the file itself should be kept secret."),(0,a.kt)("p",null,"The key store is in the file system and the location is defined in the Fleek Network ",(0,a.kt)("inlineCode",{parentName:"p"},"~/.lightning/config.toml"),", as a private key stored in an identity named PEM file (by default ",(0,a.kt)("inlineCode",{parentName:"p"},"consensus.pem")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"node.pem"),"). It's essential to understand this, as you may want to copy the identity to a new server setup, to persist the identity accross to the new server setup."),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"Security is achieved by issuing users private cryptographic keys. Only the holder of the private key has access to sensitive information, such as an identity, which relates to reputation, rewards, etc. The security of the private key is the responsibility of the user. Unfortunately, Fleek Network is unable to help you regain access to your private key if you've lost or failed to secure it. The private keys are your responsibility.")),(0,a.kt)("p",null,"The following will guide you through some of the fundamentals to help understand how to manage the key store at the very basics, and help you persist the key store identity, in any ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/requirements#server"},"supported system")," you're migrating to."),(0,a.kt)("h2",{id:"pre-requisites"},"Pre-requisites"),(0,a.kt)("p",null,"To follow the guide, you will need the following:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Familiarity with the command-line interface"),(0,a.kt)("li",{parentName:"ul"},"A basic understanding of ",(0,a.kt)("a",{parentName:"li",href:"https://en.wikipedia.org/wiki/Public-key_cryptography"},"how public key cryptography works"))),(0,a.kt)("h2",{id:"configuration-file"},"Configuration file"),(0,a.kt)("h3",{id:"locating-the-file"},"Locating the file"),(0,a.kt)("p",null,"The Lightning CLI has a configuration file in the home directory of the user, which by default is located in the path ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning")," or ",(0,a.kt)("inlineCode",{parentName:"p"},"~/.lightning")," under the name ",(0,a.kt)("inlineCode",{parentName:"p"},"config.toml"),". It's generally described as ",(0,a.kt)("inlineCode",{parentName:"p"},"~/.lightning/config.toml"),"."),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"The tilde in ",(0,a.kt)("inlineCode",{parentName:"p"},"~/.lightning")," represents ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME")," which is simpler, but we'll use ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME")," to make it easy to follow.")),(0,a.kt)("p",null,"If you're following the install recommendations you should be logged in with a ",(0,a.kt)("strong",{parentName:"p"},"sudoer")," account. For our guide, let's imagine that the ",(0,a.kt)("strong",{parentName:"p"},"sudoer")," username we are logged in with is ",(0,a.kt)("strong",{parentName:"p"},"lgtn"),"."),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"The word ",(0,a.kt)("strong",{parentName:"p"},"sudo"),' is the abbreviation of the term "super user do". As the name suggests, it is the privilege that a super user, such as an administrator has to do whatever it wants in the system. A super user can be an administrator, like the ',(0,a.kt)("strong",{parentName:"p"},"root")," or what we described here as a user in the group ",(0,a.kt)("strong",{parentName:"p"},"sudo")," aka ",(0,a.kt)("strong",{parentName:"p"},"sudoer"),".")),(0,a.kt)("p",null,"If you are logged in with a username, that'd be:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"/home//.lightning/config.toml\n")),(0,a.kt)("p",null,"For our example for user ",(0,a.kt)("inlineCode",{parentName:"p"},"lgtn")," that is:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"/home/lgtn/.lightning/config.toml\n")),(0,a.kt)("p",null,"If you log in with another user, let's say ",(0,a.kt)("inlineCode",{parentName:"p"},"fleek")," it'd be:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"/home/fleek/.lightning/config.toml\n")),(0,a.kt)("p",null,"At any time, you can check which user you are logged in with by running the command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"whoami\n")),(0,a.kt)("p",null,"Here's an example of our user ",(0,a.kt)("inlineCode",{parentName:"p"},"lgtn"),", which for the command above outputs:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn\n")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"To switch to a particular user, you can run the command ",(0,a.kt)("inlineCode",{parentName:"p"},"su ")," e.g. for the user ",(0,a.kt)("strong",{parentName:"p"},"lgtn")," we would execute the command ",(0,a.kt)("inlineCode",{parentName:"p"},"su lgtn"),".")),(0,a.kt)("p",null,"Now that you know where to locate the configuration file for any given user you are logged in with, learn about the ",(0,a.kt)("a",{parentName:"p",href:"#configuration-sections"},"Configuration sections"),"."),(0,a.kt)("h3",{id:"configuration-sections"},"Configuration sections"),(0,a.kt)("p",null,"The Fleek Network node configuration settings are located in the path ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/config.toml"),", and it's organized by configuration sections."),(0,a.kt)("p",null,"At the time of writing, we have a TOML file with sections. Here are some examples amongst others:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"application"),(0,a.kt)("li",{parentName:"ul"},"origin-ipfs"),(0,a.kt)("li",{parentName:"ul"},"rpc"),(0,a.kt)("li",{parentName:"ul"},"signer")),(0,a.kt)("p",null,"Each of the sections holds several property names and values. If you are accustomed to the ",(0,a.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/JSON"},"JSON")," or ",(0,a.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/YAML"},"YAML")," formats, you'll find the TOML format a bit similar (if you'd like to learn more about the TOML file format, read about it ",(0,a.kt)("a",{parentName:"p",href:"https://toml.io/en/"},"here"),")."),(0,a.kt)("p",null,"By default and at time of writting the Lightning CLI configuration file (config.toml) is similar to:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'[BLANK]\n\n[application]\ndb_path = "/home/lgtn/.lightning/data/app_db"\nmode = "Prod"\nstorage = "RocksDb"\ntestnet = true\n\n[blockserver]\naddress = "0.0.0.0:4211"\n\n[broadcast]\naddress = "0.0.0.0:4200"\n\n[consensus]\nstore_path = "/home/lgtn/.lightning/data/narwhal_store"\n\n[dht]\naddress = "0.0.0.0:8101"\nbootstrappers = []\n\n[fetcher]\n\n[fsstore]\nroot = "/home/lgtn/.lightning/blockstore"\n\n[[handshake.transport]]\nsignal_address = "0.0.0.0:4210"\ntype = "WebRTC"\n\n[[handshake.worker]]\ntype = "AsyncWorker"\n\n[[handshake.worker]]\ntype = "AsyncWorker"\n\n[[handshake.worker]]\ntype = "AsyncWorker"\n\n[[handshake.worker]]\ntype = "AsyncWorker"\n\n[[origin-ipfs.gateways]]\nauthority = "ipfs.io"\nprotocol = "Https"\n\n[[origin-ipfs.gateways]]\nauthority = "fleek.ipfs.io"\nprotocol = "Https"\n\n[[origin-ipfs.gateways]]\nauthority = "ipfs.runfission.com"\nprotocol = "Https"\n\n[rep-collector]\nreporter_buffer_size = 5\n\n[resolver]\nstore_path = "/home/lgtn/.lightning/data/resolver_store"\n\n[rpc]\naddr = "0.0.0.0"\nport = 4069\n\n[service-executor]\nservices = [0, 1]\n\n[signer]\nconsensus_key_path = "/home/lgtn/.lightning/keystore/consensus.pem"\nnode_key_path = "/home/lgtn/.lightning/keystore/node.pem"\n\n[topology]\ntesting_min_nodes = 9\ntesting_target_k = 8\n')),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"Beware that the configuration file might look a bit different depending on the version you're running and the current development features in place by the Fleek Network core team. You shouldn't copy the example above and replace with yours, as this only servers for illustrative purposes.")),(0,a.kt)("p",null,"Some advanced use cases might require dealing with the host and port number binding, depending on the service provider's needs and customization. We'll keep things simple and assume the default settings."),(0,a.kt)("p",null,"In this guide, we are interested in the ",(0,a.kt)("inlineCode",{parentName:"p"},"[signer]")," section settings for the ",(0,a.kt)("inlineCode",{parentName:"p"},"consensus_key_path")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"node_key_path")," which by default is set to ",(0,a.kt)("inlineCode",{parentName:"p"},"~/.lightning/keystore"),"."),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"The identity is a text description for the Keystore and at the time of writing we have not yet implemented multiple identity management via the CLI. Thereupon, the identity value serves to find the filename match in the ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore_path"),". This might change as we progress with development. Check the ",(0,a.kt)("a",{parentName:"p",href:"#identity-selection"},"Identity selection")," to learn more about it!")),(0,a.kt)("h3",{id:"type-of-keys"},"Type of keys"),(0,a.kt)("p",null,"There are three types of keys related to the identity of a node and the account ownership. The keys are based in public-key cryptography, or asymmetric cryptography where each key pair consists of a public key and a corresponding private key. The keys are described in the section ",(0,a.kt)("a",{parentName:"p",href:"docs/learn/the-network/#identity-on-the-fleek-network"},"identity on the Fleek Network")," as follows:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"A Node key (ConsensusPublicKey) is ",(0,a.kt)("a",{parentName:"p",href:"https://electriccoin.co/blog/new-snark-curve/"},"BLS12-381")," which facilitates the consensus algorithm or persistence of state, resilience and fault tolerance. Has multi-signature support, the ability to aggregate many signatures into one used for consensus committee when signing certificates")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"A Node Networking key (NodePublicKey) is ",(0,a.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/EdDSA"},"Ed25519")," used for the speed and performance of the network communications")),(0,a.kt)("li",{parentName:"ul"},(0,a.kt)("p",{parentName:"li"},"Account Owner keys are based on ",(0,a.kt)("a",{parentName:"p",href:"https://www.secg.org/sec2-v2.pdf"},"secp256k1"),", which corresponds to an Ethereum Address"))),(0,a.kt)("p",null,"For instance, a public key is open to anybody to see and it represents a unique node identifier in the Fleek Network, a bit like a passport number. On the other hand, the private key is secret and the operator is responsible to store it privately."),(0,a.kt)("p",null,"The Fleek Network relies on cryptography, thus the Fleek Network team and anybody can access, compromise or manipulate the secrets of an identity. On the other hand, the public key can be used by anyone, Fleek Network included, to identify a node or send rewards to the address without jeopardizing identity security."),(0,a.kt)("p",null,"To learn more about the identities on the Fleek Network ",(0,a.kt)("a",{parentName:"p",href:"docs/learn/the-network/#identity-on-the-fleek-network"},"here"),"."),(0,a.kt)("h3",{id:"key-privacy"},"Key privacy"),(0,a.kt)("p",null,"If you don\u2019t keep your private keys secret, you'll have your node compromised."),(0,a.kt)("p",null,"Here are a few examples of what you should not do:"),(0,a.kt)("ul",null,(0,a.kt)("li",{parentName:"ul"},"Share the ",(0,a.kt)("inlineCode",{parentName:"li"},"$HOME/.lightning/keystore")," directory file content publicly"),(0,a.kt)("li",{parentName:"ul"},"Track the ",(0,a.kt)("inlineCode",{parentName:"li"},"$HOME/.lightning/keystore")," directory files in a version control repository e.g. git"),(0,a.kt)("li",{parentName:"ul"},'Have poor "rights" permissions in UNIX systems e.g. everyone can read, delete, modify ',(0,a.kt)("inlineCode",{parentName:"li"},"$HOME/.lightning")),(0,a.kt)("li",{parentName:"ul"},"Allow anyone to access the node provider physically without any access control to the operating and file systems e.g. a VPS provider"),(0,a.kt)("li",{parentName:"ul"},"Get rid of a hard drive unformatted or blind erased by selling to somebody or dumping in the bin, which contains ",(0,a.kt)("inlineCode",{parentName:"li"},"$HOME/.lightning/keystore"))),(0,a.kt)("p",null,"There are many other ways of getting compromised, but hopefully, the ones put above give you a good starter into the subject."),(0,a.kt)("p",null,"Remember, the node provider is the only one responsible when managing the key store. Neither Fleek Network nor the most sophisticated AI system presently can compromise the cryptography in use to help you out. You are fully responsible for securing and retaining your private keys."),(0,a.kt)("h3",{id:"identity-selection"},"Identity selection"),(0,a.kt)("p",null,"Multiple identity management is yet to be implemented but in any case, some users might find it trivial to keep multiple identities and switch between them referencing them by name. The following section is not advocating this approach but sharing some approaches that can help certain use-cases."),(0,a.kt)("p",null,"Let's suppose that we've recently moved to a new server setup and copied our previous server keystore keys as ",(0,a.kt)("inlineCode",{parentName:"p"},"consensus.pem")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"node.pem")," and renamed the ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/keystore/*.pem")," to ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/keystore/new-*.pem"),"."),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"We are using a wildcard ",(0,a.kt)("inlineCode",{parentName:"p"},"*")," to reduce verbosity. The wildcard means as replacement for all the filenames encountered in the path and extension without having to name them individually as we know they are ",(0,a.kt)("inlineCode",{parentName:"p"},"consensus.pem")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"node.pem"),".")),(0,a.kt)("p",null,"To illustrate this scenario, here's an example of how our ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/keystore")," directory could look like:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},".\n\u251c\u2500\u2500 new-consensus.pem\n\u251c\u2500\u2500 new-node.pem\n\u2514\u2500\u2500 old-consensus.pem\n\u2514\u2500\u2500 old-node.pem\n\n0 directories, 4 file\n")),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"old-*.pem")," files are the original key store and ",(0,a.kt)("inlineCode",{parentName:"p"},"new-*.pem")," could correspond to the new identity created while setting up the node in the new server."),(0,a.kt)("p",null,"Since we have ",(0,a.kt)("inlineCode",{parentName:"p"},"[signer]")," set to the default values, in particular:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-toml"},'[signer]\nconsensus_key_path = "/home/lgtn/.lightning/keystore/consensus.pem"\nnode_key_path = "/home/lgtn/.lightning/keystore/node.pem"\n')),(0,a.kt)("p",null,"We'd be required to change and switch to the preferred keys. The identity is switch to the provided values once the node is restarted. Thus, we can switch to any identity by changing the ",(0,a.kt)("inlineCode",{parentName:"p"},"[signer]")," ",(0,a.kt)("inlineCode",{parentName:"p"},"consensus_key_path")," and ",(0,a.kt)("inlineCode",{parentName:"p"},"node_key_path")," pathname values anytime as long we restart the server successfully."),(0,a.kt)("p",null,"To verify which keys are loaded by the Lightning CLI run the command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn keys show\n")),(0,a.kt)("p",null,"You'd find the public keys in the output, which can be used for comparision and should be different everytime the configuration changes and reloaded. Here's an example of the output:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"Node Public Key: RwPpr35H5AAfWwSDFxwYuJv5TA8PWUd2pdBg+UKsORc=\nConsensus Public Key: s36g09qQzaaOJxi0UZDRCXj3HUUWjaGiYrQV6Ylo9Ih6jMvrnxM5s1OpBnsEj5R1AVYcuxlnVR+oyEjgJ3WpI5LOHSN1Q6Zur33vka3IachBEIKIbsiXMJW16vu4n4bG\n")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"The PEM files can be named as you wish, but by default we like to keep it sound to avoid confusion and make it as clear as possible.")),(0,a.kt)("h2",{id:"backing-up-the-keystore"},"Backing up the keystore"),(0,a.kt)("p",null,"When dealing with Fleek Network it's crucial to always be aware of the identity. You should backup private keys in case the unexpected happens, as it's impossible to recover the identity in any other way, including the core team, any other person or system."),(0,a.kt)("p",null,"Backing up your keystore pem files are crucial to ensure the safety and accessibility of your identity on the Fleek Network. For example, if your ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning")," is deleted you'll still be able to restore it if you have backed it up properly."),(0,a.kt)("p",null,"There are many ways to make identity backups, each with its own benefits and drawbacks. At risk of oversimplifying, we'll focus on a simple manual approach to expose some of the principles you should be have awareness."),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"The security is never stronger than its weakest link, and it is very likely that the weakest link is not the method itself. It's pointless to encrypt the backup archive with sophisticated methods when the passphrase is weak or of an easy guess.")),(0,a.kt)("p",null,"None of the methods described here are being endorsed by the Fleek Network team use the knowledge provided here for educational purposes only and at your own risk."),(0,a.kt)("h3",{id:"lower-security"},"Lower security"),(0,a.kt)("p",null,"If you opt for the lowest level of security, you can use zip and unzip. The man page of zip described the encryption algorithm used to be weaker than PGP."),(0,a.kt)("p",null,"To zip and encrypto the ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/keystore")," directory run:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"# It'll prompt for password (remember)\nzip --encrypt -r keystore.zip.enc $HOME/.lightning/keystore\n")),(0,a.kt)("p",null,"To unzip and decrypt the ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore.zip.enc"),", you'd run:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"# It'll prompt for password (recall)\nunzip keystore.zip.enc -d $HOME/.lightning/keystore\n")),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"We provide the unzip destiny target to the flag ",(0,a.kt)("inlineCode",{parentName:"p"},"-d"),". The unzip process outputs the files onto the desired location ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/keystore"),", thus overriding any contents. If you have any files in the destiny target directory it'll be overriden, effectively replacing with the output of the unzipped directory content, so make sure you backup any files as required.")),(0,a.kt)("h3",{id:"higher-security"},"Higher security"),(0,a.kt)("p",null,"Create a ",(0,a.kt)("inlineCode",{parentName:"p"},"Tar")," archive, which will contain the target directory, files and the Tar stores all of the relative paths in the tarball itself."),(0,a.kt)("p",null,"Create a ",(0,a.kt)("inlineCode",{parentName:"p"},"tarbar")," by executing:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'tar -cf "keystore.tar" $HOME/.lightning/keystore\n')),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore.tar")," should be in the current work directory."),(0,a.kt)("p",null,"Use ",(0,a.kt)("inlineCode",{parentName:"p"},"gpg")," with the ",(0,a.kt)("a",{parentName:"p",href:"ttps://www.gnupg.org/gph/en/manual/x110.html"},"symmetric option"),", it creates the keys for that file and request a password to protect them. If you are familiar with assymetric ",(0,a.kt)("inlineCode",{parentName:"p"},"gpg"),", it's similar but it's not signed with your public key or such."),(0,a.kt)("p",null,"The encryption command is:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"sudo gpg -a --symmetric --cipher-algo AES256 keystore.tar\n")),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore.tar.asc")," should be in the current work directory."),(0,a.kt)("p",null,"To decrypt the ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore.tar.asc")," file, enter:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"sudo gpg -a --output keystore.tar --decrypt keystore.tar.asc\n")),(0,a.kt)("p",null,"To extract the ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore.tar")," is simple, but be aware that it unarchives with the original directory structure, which might be a bit confusing. So, we'll create a new temporary directory for our example that will use to extract to."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"mkdir $HOME/tar_keystore_extract\n")),(0,a.kt)("p",null,"Now, run the command to extract to the target directory, as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"tar -xf keystore.tar -C $HOME/tar_keystore_extract\n")),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"/home//.lightning/keystore")," should be in the ",(0,a.kt)("inlineCode",{parentName:"p"},"tar_keystore_extract")," directory where you'll find the PEM files."),(0,a.kt)("h3",{id:"storage"},"Storage"),(0,a.kt)("p",null,"The backup archive should only be accessible by yourself. If you decided to store it in a cloud storage provider, be aware of increased security risks. Cloud storage is convenient, but it ultimately puts data into the hands of others. If you're not particularly concerned, or have confidence about the encryption of the files, then that's at your own risk. But it's recommended to store in a physical hard drive that remains disconnected from computers and network devices."),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"If you use cloud storage to store your sensitive data, encryption should be your first line of defense. Encrypting files before uploading them to the cloud is crucial to reduce others from accessing information without your permissions and knowledge.")),(0,a.kt)("p",null,"Remember that the security of the private key is the responsibility of the user. Unfortunately, the Fleek Network team and any others are unable to help regain access to private key if lost or failed to secure them. The private keys are the user responsibility. The Fleek Network team doesn't endorse any methods of encryption and storage, the methods described here are for educational purposes only."),(0,a.kt)("h2",{id:"loading-keys-on-runtime"},"Loading keys on runtime"),(0,a.kt)("p",null,"As described in the section ",(0,a.kt)("a",{parentName:"p",href:"#configuration-file"},"configuration files")," the default location of the ",(0,a.kt)("inlineCode",{parentName:"p"},".lightning")," system configuration directory is ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning"),"."),(0,a.kt)("p",null,"The ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/config.toml")," holds the information of where the Lightning CLI node process should pull the keystore pem files. The location of the pem files can be placed anywhere the node process has permissions to read."),(0,a.kt)("p",null,"When unarchiving the backup files, the keystore directory or pem files should be placed in the directory declared in the ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/config.toml"),". That is if the location is the one specified on the runtime\u2013the command declared to launch and run the lightning service, that has the optional ",(0,a.kt)("inlineCode",{parentName:"p"},"-c")," configuration flag that takes any custom location which overrides the default ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/config.toml"),"."),(0,a.kt)("admonition",{type:"caution"},(0,a.kt)("p",{parentName:"admonition"},"On runtime, the Lightning service can have specified a configuration file in any readable location. If a configuration pathname isn't passed, it'll default to the ",(0,a.kt)("inlineCode",{parentName:"p"},"$HOME/.lightning/config.toml"),". It's important to understand this to avoid confusion."),(0,a.kt)("p",{parentName:"admonition"},"The service that starts with:"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn -c /root/custom-configuration.toml run\n")),(0,a.kt)("p",{parentName:"admonition"},"Can have complete different settings from any of the following:"),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn -c /home/lgtn/.lightning/config.toml run\n")),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn -c ~/.lightning/config.toml run\n")),(0,a.kt)("pre",{parentName:"admonition"},(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn run\n")),(0,a.kt)("p",{parentName:"admonition"},"Due to the fact that any of the fails above might contain different settings declared in the file body.")),(0,a.kt)("p",null,"For instance, we can imagine a scenario where our service is started with the command:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn -c /home/lgtn/.lightning/config.toml run\n")),(0,a.kt)("p",null,"Where the ",(0,a.kt)("inlineCode",{parentName:"p"},"keystore")," is placed under the parent directory ",(0,a.kt)("inlineCode",{parentName:"p"},"/home/lgtn/.lightning/"),". Resulting in the configuration file have the following settings for the hypotetical username ",(0,a.kt)("inlineCode",{parentName:"p"},"lgtn"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'[signer]\nconsensus_key_path = "/home/lgtn/.lightning/keystore/consensus.pem"\nnode_key_path = "/home/lgtn/.lightning/keystore/node.pem"\n')),(0,a.kt)("admonition",{type:"tip"},(0,a.kt)("p",{parentName:"admonition"},"On the ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/install"},"install instructions")," provided by the documentation, a ",(0,a.kt)("a",{parentName:"p",href:"/docs/node/Install/#systemd-service-setup"},"Systemd service unit")," is recommended to allow the user control the Lightning service via systemctl. The Systemd service unit file should contain the recommended usage of ",(0,a.kt)("inlineCode",{parentName:"p"},"-c")," configuration. If you have followed the recommendations it should be familiar.")),(0,a.kt)("h2",{id:"conclusion"},"Conclusion"),(0,a.kt)("p",null,"We've walked through most basics of where the configuration file is located, the configuration settings we use to set up and run the node, the different configuration sections we have, and most importantly the identity section."),(0,a.kt)("p",null,"Additionally, a brief guide on the ",(0,a.kt)("a",{parentName:"p",href:"#identity"},"identity"),", more specifically an introduction to the ",(0,a.kt)("a",{parentName:"p",href:"#type-of-keys"},"type of keys")," and ",(0,a.kt)("a",{parentName:"p",href:"#key-privacy"},"key privacy"),", which we find important to understand for anyone seriously interested in running a node by hinting into some system administration and security principles."),(0,a.kt)("p",null,"Separatily, at risk of oversimpliying provided an brief introduction into the backup of the keystore directory."),(0,a.kt)("p",null,"In the future, we'll introduce more advanced topics that will help you improve the knowledge you get from this, but we are glad that you followed this guide and got some comprehension to help you manage the key store."),(0,a.kt)("p",null,"While we do our best to provide the clearest instructions, there's always space for improvement, therefore feel free to make any contributions by messaging us on our ",(0,a.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"Discord")," or by opening a ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/fleek-network"},"PR")," in any of our repositories."),(0,a.kt)("p",null,"Discover more about the project by ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/lightning"},"watching/contributing on Github"),", following us on ",(0,a.kt)("a",{parentName:"p",href:"https://twitter.com/fleek_net"},"Twitter"),", and joining ",(0,a.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"our community Discord")," for all the best updates!"),(0,a.kt)(o.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}c.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>a});var i=n(7294);const a=e=>{let{image:t,name:n,title:a,url:o,communityMember:r=!1}=e;return i.createElement("section",{className:"author_card"},i.createElement("div",null,i.createElement("span",{className:"avatar"},i.createElement("a",{href:o,target:"_blank",alt:n},i.createElement("img",{src:t,alt:n}))),i.createElement("div",null,i.createElement("span",{className:"name"},i.createElement("a",{href:o,target:"_blank",alt:n},n)),i.createElement("span",{className:"title"},a),i.createElement("span",{className:"discord"},r?"Join our community on":"Got questions? Find us on"," ",i.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file diff --git a/assets/js/5b6134d1.4ba8eca7.js b/assets/js/5b6134d1.afc8ef03.js similarity index 99% rename from assets/js/5b6134d1.4ba8eca7.js rename to assets/js/5b6134d1.afc8ef03.js index f54313ed3..e31735af4 100644 --- a/assets/js/5b6134d1.4ba8eca7.js +++ b/assets/js/5b6134d1.afc8ef03.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[9752],{3905:(e,t,n)=>{n.d(t,{Zo:()=>h,kt:()=>c});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),p=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},h=function(e){var t=p(e.components);return r.createElement(l.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},g=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,h=s(e,["components","mdxType","originalType","parentName"]),d=p(n),g=o,c=d["".concat(l,".").concat(g)]||d[g]||u[g]||a;return n?r.createElement(c,i(i({ref:t},h),{},{components:n})):r.createElement(c,i({ref:t},h))}));function c(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=g;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:o,i[1]=s;for(var p=2;p{n.d(t,{ZP:()=>s});var r=n(7462),o=(n(7294),n(3905));const a={toc:[]},i="wrapper";function s(e){let{components:t,...n}=e;return(0,o.kt)(i,(0,r.Z)({},a,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"In the ",(0,o.kt)("inlineCode",{parentName:"p"},"/home//.lightning/config.toml")," you'll find some and more of the following:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n')),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"The configuration properties and values presented above are a shorter version of what you'll find on your ",(0,o.kt)("strong",{parentName:"p"},"configuration.toml"),". We keep it short to make it easier to follow, do not copy and paste.")),(0,o.kt)("p",null,"Find and replace all instances of ~ in the config file ",(0,o.kt)("inlineCode",{parentName:"p"},"/home//.lightning/config.toml"),". "),(0,o.kt)("p",null,"Here's an example of how to do it using ",(0,o.kt)("strong",{parentName:"p"},"sed"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'sed -i "s|~/.lightning|/home//.lightning|g" "/home//.lightning/config.toml"\n')),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Replace the ",(0,o.kt)("inlineCode",{parentName:"p"},"")," with your username. For example, if you have followed the recommendation to ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/install#create-a-user"},"create a user")," it would look like ",(0,o.kt)("inlineCode",{parentName:"p"},"/home/lgtn/.lightning/config.toml")," for the username ",(0,o.kt)("strong",{parentName:"p"},"lgtn"),".")),(0,o.kt)("p",null,"For example, if your username is ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn")," that'd look like this:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'sed -i "s|~/.lightning|/home/lgtn/.lightning|g" "/home/lgtn/.lightning/config.toml"\n')),(0,o.kt)("p",null,"Once modified, you can run a ",(0,o.kt)("inlineCode",{parentName:"p"},"cat")," to see the content of the files to confirm it has been updated."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"cat /home/lgtn/.lightning/config.toml\n")),(0,o.kt)("p",null,"For our example where we opted in for the username ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn")," that would look like:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n')),(0,o.kt)("admonition",{title:"Warning",type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"Bear in mind that we are keeping the content of the file short to make it easier to read and follow. The content of your configuration file should look slightly different, amongst these it should contain other properties and values. You should not copy and replace the content of your files with the ones presented here.")))}s.isMDXComponent=!0},5852:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>h,contentTitle:()=>l,default:()=>c,frontMatter:()=>s,metadata:()=>p,toc:()=>d});var r=n(7462),o=(n(7294),n(3905)),a=n(3872),i=n(3242);const s={title:"File permissions and Ownership",slug:"file-permissions-and-ownership",hide_title:!0,tags:["ownership","file permissions","sudoer","root"]},l=void 0,p={unversionedId:"Lightning CLI/file-permissions-and-ownership",id:"Lightning CLI/file-permissions-and-ownership",title:"File permissions and Ownership",description:"Ownership",source:"@site/references/Lightning CLI/file-permissions-and-ownership.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/file-permissions-and-ownership",permalink:"/references/Lightning CLI/file-permissions-and-ownership",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/file-permissions-and-ownership.md",tags:[{label:"ownership",permalink:"/references/tags/ownership"},{label:"file permissions",permalink:"/references/tags/file-permissions"},{label:"sudoer",permalink:"/references/tags/sudoer"},{label:"root",permalink:"/references/tags/root"}],version:"current",lastUpdatedAt:1694784773,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"File permissions and Ownership",slug:"file-permissions-and-ownership",hide_title:!0,tags:["ownership","file permissions","sudoer","root"]},sidebar:"defaultSidebar",previous:{title:"Error linking with cc",permalink:"/references/Lightning CLI/error-linking-with-cc-failed-exist-status-1"},next:{title:"Keys not found",permalink:"/references/Lightning CLI/keys-not-found"}},h={},d=[{value:"Ownership",id:"ownership",level:2},{value:"Using sudo to delegate permissions",id:"using-sudo-to-delegate-permissions",level:2},{value:"User $HOME directory",id:"user-home-directory",level:2},{value:"Set the locations of the user paths",id:"set-the-locations-of-the-user-paths",level:2},{value:"Set the configuration flag -c on the service unit file",id:"set-the-configuration-flag--c-on-the-service-unit-file",level:2}],u={toc:d},g="wrapper";function c(e){let{components:t,...n}=e;return(0,o.kt)(g,(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"ownership"},"Ownership"),(0,o.kt)("p",null,"The user who installs the Fleek Network Lightning CLI matters, as it can own or delegate ownership of the dependencies and applications being installed."),(0,o.kt)("p",null,"For example, if you have followed the install document recommendations and have:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Created a user ",(0,o.kt)("strong",{parentName:"li"},"lgtn")),(0,o.kt)("li",{parentName:"ul"},"Switched to the user ",(0,o.kt)("strong",{parentName:"li"},"lgtn")),(0,o.kt)("li",{parentName:"ul"},"Executed the installation process as ",(0,o.kt)("strong",{parentName:"li"},"lgtn")," ")),(0,o.kt)("p",null,"You'll find that it owns the following directories under the user home (/home/lgtn):"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"drwxr-x--- 6 lgtn lgtn 4096 Sep 12 10:27 .\ndrwxr-xr-x 3 root root 4096 Sep 11 12:28 ..\ndrwxrwxr-x 5 lgtn lgtn 4096 Sep 11 12:29 .cargo\ndrwxrwxr-x 5 lgtn lgtn 4096 Sep 11 15:25 .lightning\ndrwxrwxr-x 6 lgtn lgtn 4096 Sep 11 12:29 .rustup\ndrwxrwxr-x 3 lgtn lgtn 4096 Sep 11 12:28 fleek-network\n")),(0,o.kt)("p",null,"Above, we have the listing properties set as ",(0,o.kt)("strong",{parentName:"p"},"drwxrwxr-x")," and the ownership ",(0,o.kt)("strong",{parentName:"p"},"lgtn:lgtn"),"."),(0,o.kt)("p",null,"On the other hand, if you have done the installation process as ",(0,o.kt)("strong",{parentName:"p"},"root")," superuser, you'll find that:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"The location of the directories and files goes under the ",(0,o.kt)("inlineCode",{parentName:"li"},"/root")," pathname"),(0,o.kt)("li",{parentName:"ul"},"The ownership is set to ",(0,o.kt)("strong",{parentName:"li"},"root:root"))),(0,o.kt)("p",null,"Learn more about ",(0,o.kt)("a",{parentName:"p",href:"https://www.linuxfoundation.org/blog/blog/classic-sysadmin-understanding-linux-file-permissions"},"file permissions")," from the ",(0,o.kt)("a",{parentName:"p",href:"https://www.linuxfoundation.org/"},"Linux Foundation"),"."),(0,o.kt)("p",null,"To learn more about file permission on Linux, read the ",(0,o.kt)("a",{parentName:"p",href:"https://www.linuxfoundation.org/blog/blog/classic-sysadmin-understanding-linux-file-permissions"},"Understanding Linux File Permissions"),"."),(0,o.kt)("h2",{id:"using-sudo-to-delegate-permissions"},"Using sudo to delegate permissions"),(0,o.kt)("p",null,"Consider file ownership and permissions to understand where the keystore is located. Take close attention when executing commands as an admin\u2013with or without ",(0,o.kt)("strong",{parentName:"p"},"super user")," (root) or ",(0,o.kt)("strong",{parentName:"p"},"sudo"),"."),(0,o.kt)("p",null,"If a command is executed without ",(0,o.kt)("strong",{parentName:"p"},"sudo")," then the generated output goes onto the ",(0,o.kt)("strong",{parentName:"p"},"user")," home."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn keys generate\n")),(0,o.kt)("p",null,"Resulting in having the ",(0,o.kt)("strong",{parentName:"p"},"keystore")," saved onto ",(0,o.kt)("inlineCode",{parentName:"p"},"/home/username/.lightning/keystore"),"."),(0,o.kt)("p",null,"On the other hand, if a command is executed with ",(0,o.kt)("strong",{parentName:"p"},"sudo")," then the generated output is delegated to ",(0,o.kt)("strong",{parentName:"p"},"root")," directory."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"sudo lgtn keys generate\n")),(0,o.kt)("p",null,"Resulting in having the ",(0,o.kt)("strong",{parentName:"p"},"keystore")," saved onto ",(0,o.kt)("inlineCode",{parentName:"p"},"/root/.lightning/keystore"),"."),(0,o.kt)("h2",{id:"user-home-directory"},"User $HOME directory"),(0,o.kt)("p",null,"The home directory is a directory that contains the personal files of a particular user of the system. On Linux, the ",(0,o.kt)("inlineCode",{parentName:"p"},"$HOME")," environment variable is set by the login program, which sets the user `$HOME`` accordingly. A user's home goes by the username, the user who's logged in."),(0,o.kt)("p",null,"For this reason, a user can change to the home directory by executing:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"cd $HOME\n")),(0,o.kt)("p",null,"A shorthand allows a user to refer to their home directory simply as ",(0,o.kt)("inlineCode",{parentName:"p"},"~")," (tilde), as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"cd ~\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"We can find that the HOME or ~ (tilde) is highly dependent on the user who's logged in. Since we know that the user might delegate to ",(0,o.kt)("strong",{parentName:"p"},"root")," by the usage of ",(0,o.kt)("strong",{parentName:"p"},"sudo"),", this can help troubleshoot and explain the location of our files e.g. the keystore. In the section ",(0,o.kt)("a",{parentName:"p",href:"#set-the-locations-of-the-user-paths"},"Set the locations of the user paths"),", we learn how to define the location of our user configuration paths to avoid confusion. By doing it we ensure that when running the service, the service picks the correct configuration paths for our user.")),(0,o.kt)("p",null,"To learn more about the user $HOME directory read the wikipedia ",(0,o.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Home_directory"},"Home directory")," document."),(0,o.kt)("h2",{id:"set-the-locations-of-the-user-paths"},"Set the locations of the user paths"),(0,o.kt)(i.ZP,{mdxType:"FindAndReplaceConfigWithUserPaths"}),(0,o.kt)("h2",{id:"set-the-configuration-flag--c-on-the-service-unit-file"},"Set the configuration flag -c on the service unit file"),(0,o.kt)("p",null,"The following section assumes that a System service unit has been declared and you're using systemctl to control the service, as described in our ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/install#systemd-service-setup"},"Systemd Service Setup")," install section."),(0,o.kt)("p",null,"Open and edit the ",(0,o.kt)("strong",{parentName:"p"},"/etc/systemd/system/lightning.service")," file."),(0,o.kt)("p",null,"1) Replace ",(0,o.kt)("inlineCode",{parentName:"p"},"")," with YOUR username. For example, in the documentation we use the username ",(0,o.kt)("strong",{parentName:"p"},"lgtn"),", which means we'd replace ",(0,o.kt)("inlineCode",{parentName:"p"},"User=")," with ",(0,o.kt)("inlineCode",{parentName:"p"},"User=lgtn"),"."),(0,o.kt)("p",null,"2) Make sure that the ExecStart is set correctly, including the ",(0,o.kt)("inlineCode",{parentName:"p"},"-c")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"[Unit]\nDescription=Fleek Network Node lightning service\n\n[Service]\nUser=\nType=simple\nMemoryHigh=32G\nRestartSec=15s\nRestart=always\nExecStart=lgtn -c /home//.lightning/config.toml run\nStandardOutput=append:/var/log/lightning/output.log\nStandardError=append:/var/log/lightning/diagnostic.log\nEnvironment=TMPDIR=/var/tmp\n\n[Install]\nWantedBy=multi-user.target\n")),(0,o.kt)("p",null,"For our example, as the username ",(0,o.kt)("strong",{parentName:"p"},"lgtn")," it would look like:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"[Unit]\nDescription=Fleek Network Node lightning service\n\n[Service]\nUser=lgtn\nType=simple\nMemoryHigh=32G\nRestartSec=15s\nRestart=always\nExecStart=lgtn -c /home/lgtn/.lightning/config.toml run\nStandardOutput=append:/var/log/lightning/output.log\nStandardError=append:/var/log/lightning/diagnostic.log\nEnvironment=/var/tmp\n\n[Install]\nWantedBy=multi-user.target\n")),(0,o.kt)("p",null,"When complete make sure the file is saved and the systemctl daemon is reloaded, as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl daemon-reload\n")),(0,o.kt)("p",null,"Consequently, when a user manages the service via the systemctl, the Lightning CLI process will read the configuration file settings provided above. It includes the location of the user preferences, such as the keystore location amongst others, preventing confusion regardless of ",(0,o.kt)("strong",{parentName:"p"},"root")," delegation."),(0,o.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}c.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>o});var r=n(7294);const o=e=>{let{image:t,name:n,title:o,url:a,communityMember:i=!1}=e;return r.createElement("section",{className:"author_card"},r.createElement("div",null,r.createElement("span",{className:"avatar"},r.createElement("a",{href:a,target:"_blank",alt:n},r.createElement("img",{src:t,alt:n}))),r.createElement("div",null,r.createElement("span",{className:"name"},r.createElement("a",{href:a,target:"_blank",alt:n},n)),r.createElement("span",{className:"title"},o),r.createElement("span",{className:"discord"},i?"Join our community on":"Got questions? Find us on"," ",r.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[9752],{3905:(e,t,n)=>{n.d(t,{Zo:()=>h,kt:()=>c});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),p=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},h=function(e){var t=p(e.components);return r.createElement(l.Provider,{value:t},e.children)},d="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},g=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,h=s(e,["components","mdxType","originalType","parentName"]),d=p(n),g=o,c=d["".concat(l,".").concat(g)]||d[g]||u[g]||a;return n?r.createElement(c,i(i({ref:t},h),{},{components:n})):r.createElement(c,i({ref:t},h))}));function c(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,i=new Array(a);i[0]=g;var s={};for(var l in t)hasOwnProperty.call(t,l)&&(s[l]=t[l]);s.originalType=e,s[d]="string"==typeof e?e:o,i[1]=s;for(var p=2;p{n.d(t,{ZP:()=>s});var r=n(7462),o=(n(7294),n(3905));const a={toc:[]},i="wrapper";function s(e){let{components:t,...n}=e;return(0,o.kt)(i,(0,r.Z)({},a,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"In the ",(0,o.kt)("inlineCode",{parentName:"p"},"/home//.lightning/config.toml")," you'll find some and more of the following:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n')),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"The configuration properties and values presented above are a shorter version of what you'll find on your ",(0,o.kt)("strong",{parentName:"p"},"configuration.toml"),". We keep it short to make it easier to follow, do not copy and paste.")),(0,o.kt)("p",null,"Find and replace all instances of ~ in the config file ",(0,o.kt)("inlineCode",{parentName:"p"},"/home//.lightning/config.toml"),". "),(0,o.kt)("p",null,"Here's an example of how to do it using ",(0,o.kt)("strong",{parentName:"p"},"sed"),":"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'sed -i "s|~/.lightning|/home//.lightning|g" "/home//.lightning/config.toml"\n')),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"Replace the ",(0,o.kt)("inlineCode",{parentName:"p"},"")," with your username. For example, if you have followed the recommendation to ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/install#create-a-user"},"create a user")," it would look like ",(0,o.kt)("inlineCode",{parentName:"p"},"/home/lgtn/.lightning/config.toml")," for the username ",(0,o.kt)("strong",{parentName:"p"},"lgtn"),".")),(0,o.kt)("p",null,"For example, if your username is ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn")," that'd look like this:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},'sed -i "s|~/.lightning|/home/lgtn/.lightning|g" "/home/lgtn/.lightning/config.toml"\n')),(0,o.kt)("p",null,"Once modified, you can run a ",(0,o.kt)("inlineCode",{parentName:"p"},"cat")," to see the content of the files to confirm it has been updated."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"cat /home/lgtn/.lightning/config.toml\n")),(0,o.kt)("p",null,"For our example where we opted in for the username ",(0,o.kt)("inlineCode",{parentName:"p"},"lgtn")," that would look like:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-toml"},'[BLANK]\n\n[application]\ndb_path = "~/.lightning/data/app_db"\n\n[consensus]\nstore_path = "~/.lightning/data/narwhal_store"\n\n[fsstore]\nroot = "~/.lightning/blockstore"\n\n[resolver]\nstore_path = "~/.lightning/data/resolver_store"\n\n[signer]\nconsensus_key_path = "~/.lightning/keystore/consensus.pem"\nnode_key_path = "~/.lightning/keystore/node.pem"\n')),(0,o.kt)("admonition",{title:"Warning",type:"caution"},(0,o.kt)("p",{parentName:"admonition"},"Bear in mind that we are keeping the content of the file short to make it easier to read and follow. The content of your configuration file should look slightly different, amongst these it should contain other properties and values. You should not copy and replace the content of your files with the ones presented here.")))}s.isMDXComponent=!0},5852:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>h,contentTitle:()=>l,default:()=>c,frontMatter:()=>s,metadata:()=>p,toc:()=>d});var r=n(7462),o=(n(7294),n(3905)),a=n(3872),i=n(3242);const s={title:"File permissions and Ownership",slug:"file-permissions-and-ownership",hide_title:!0,tags:["ownership","file permissions","sudoer","root"]},l=void 0,p={unversionedId:"Lightning CLI/file-permissions-and-ownership",id:"Lightning CLI/file-permissions-and-ownership",title:"File permissions and Ownership",description:"Ownership",source:"@site/references/Lightning CLI/file-permissions-and-ownership.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/file-permissions-and-ownership",permalink:"/references/Lightning CLI/file-permissions-and-ownership",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/file-permissions-and-ownership.md",tags:[{label:"ownership",permalink:"/references/tags/ownership"},{label:"file permissions",permalink:"/references/tags/file-permissions"},{label:"sudoer",permalink:"/references/tags/sudoer"},{label:"root",permalink:"/references/tags/root"}],version:"current",lastUpdatedAt:1694785242,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"File permissions and Ownership",slug:"file-permissions-and-ownership",hide_title:!0,tags:["ownership","file permissions","sudoer","root"]},sidebar:"defaultSidebar",previous:{title:"Error linking with cc",permalink:"/references/Lightning CLI/error-linking-with-cc-failed-exist-status-1"},next:{title:"Keys not found",permalink:"/references/Lightning CLI/keys-not-found"}},h={},d=[{value:"Ownership",id:"ownership",level:2},{value:"Using sudo to delegate permissions",id:"using-sudo-to-delegate-permissions",level:2},{value:"User $HOME directory",id:"user-home-directory",level:2},{value:"Set the locations of the user paths",id:"set-the-locations-of-the-user-paths",level:2},{value:"Set the configuration flag -c on the service unit file",id:"set-the-configuration-flag--c-on-the-service-unit-file",level:2}],u={toc:d},g="wrapper";function c(e){let{components:t,...n}=e;return(0,o.kt)(g,(0,r.Z)({},u,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"ownership"},"Ownership"),(0,o.kt)("p",null,"The user who installs the Fleek Network Lightning CLI matters, as it can own or delegate ownership of the dependencies and applications being installed."),(0,o.kt)("p",null,"For example, if you have followed the install document recommendations and have:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"Created a user ",(0,o.kt)("strong",{parentName:"li"},"lgtn")),(0,o.kt)("li",{parentName:"ul"},"Switched to the user ",(0,o.kt)("strong",{parentName:"li"},"lgtn")),(0,o.kt)("li",{parentName:"ul"},"Executed the installation process as ",(0,o.kt)("strong",{parentName:"li"},"lgtn")," ")),(0,o.kt)("p",null,"You'll find that it owns the following directories under the user home (/home/lgtn):"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"drwxr-x--- 6 lgtn lgtn 4096 Sep 12 10:27 .\ndrwxr-xr-x 3 root root 4096 Sep 11 12:28 ..\ndrwxrwxr-x 5 lgtn lgtn 4096 Sep 11 12:29 .cargo\ndrwxrwxr-x 5 lgtn lgtn 4096 Sep 11 15:25 .lightning\ndrwxrwxr-x 6 lgtn lgtn 4096 Sep 11 12:29 .rustup\ndrwxrwxr-x 3 lgtn lgtn 4096 Sep 11 12:28 fleek-network\n")),(0,o.kt)("p",null,"Above, we have the listing properties set as ",(0,o.kt)("strong",{parentName:"p"},"drwxrwxr-x")," and the ownership ",(0,o.kt)("strong",{parentName:"p"},"lgtn:lgtn"),"."),(0,o.kt)("p",null,"On the other hand, if you have done the installation process as ",(0,o.kt)("strong",{parentName:"p"},"root")," superuser, you'll find that:"),(0,o.kt)("ul",null,(0,o.kt)("li",{parentName:"ul"},"The location of the directories and files goes under the ",(0,o.kt)("inlineCode",{parentName:"li"},"/root")," pathname"),(0,o.kt)("li",{parentName:"ul"},"The ownership is set to ",(0,o.kt)("strong",{parentName:"li"},"root:root"))),(0,o.kt)("p",null,"Learn more about ",(0,o.kt)("a",{parentName:"p",href:"https://www.linuxfoundation.org/blog/blog/classic-sysadmin-understanding-linux-file-permissions"},"file permissions")," from the ",(0,o.kt)("a",{parentName:"p",href:"https://www.linuxfoundation.org/"},"Linux Foundation"),"."),(0,o.kt)("p",null,"To learn more about file permission on Linux, read the ",(0,o.kt)("a",{parentName:"p",href:"https://www.linuxfoundation.org/blog/blog/classic-sysadmin-understanding-linux-file-permissions"},"Understanding Linux File Permissions"),"."),(0,o.kt)("h2",{id:"using-sudo-to-delegate-permissions"},"Using sudo to delegate permissions"),(0,o.kt)("p",null,"Consider file ownership and permissions to understand where the keystore is located. Take close attention when executing commands as an admin\u2013with or without ",(0,o.kt)("strong",{parentName:"p"},"super user")," (root) or ",(0,o.kt)("strong",{parentName:"p"},"sudo"),"."),(0,o.kt)("p",null,"If a command is executed without ",(0,o.kt)("strong",{parentName:"p"},"sudo")," then the generated output goes onto the ",(0,o.kt)("strong",{parentName:"p"},"user")," home."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"lgtn keys generate\n")),(0,o.kt)("p",null,"Resulting in having the ",(0,o.kt)("strong",{parentName:"p"},"keystore")," saved onto ",(0,o.kt)("inlineCode",{parentName:"p"},"/home/username/.lightning/keystore"),"."),(0,o.kt)("p",null,"On the other hand, if a command is executed with ",(0,o.kt)("strong",{parentName:"p"},"sudo")," then the generated output is delegated to ",(0,o.kt)("strong",{parentName:"p"},"root")," directory."),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"sudo lgtn keys generate\n")),(0,o.kt)("p",null,"Resulting in having the ",(0,o.kt)("strong",{parentName:"p"},"keystore")," saved onto ",(0,o.kt)("inlineCode",{parentName:"p"},"/root/.lightning/keystore"),"."),(0,o.kt)("h2",{id:"user-home-directory"},"User $HOME directory"),(0,o.kt)("p",null,"The home directory is a directory that contains the personal files of a particular user of the system. On Linux, the ",(0,o.kt)("inlineCode",{parentName:"p"},"$HOME")," environment variable is set by the login program, which sets the user `$HOME`` accordingly. A user's home goes by the username, the user who's logged in."),(0,o.kt)("p",null,"For this reason, a user can change to the home directory by executing:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"cd $HOME\n")),(0,o.kt)("p",null,"A shorthand allows a user to refer to their home directory simply as ",(0,o.kt)("inlineCode",{parentName:"p"},"~")," (tilde), as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"cd ~\n")),(0,o.kt)("admonition",{type:"tip"},(0,o.kt)("p",{parentName:"admonition"},"We can find that the HOME or ~ (tilde) is highly dependent on the user who's logged in. Since we know that the user might delegate to ",(0,o.kt)("strong",{parentName:"p"},"root")," by the usage of ",(0,o.kt)("strong",{parentName:"p"},"sudo"),", this can help troubleshoot and explain the location of our files e.g. the keystore. In the section ",(0,o.kt)("a",{parentName:"p",href:"#set-the-locations-of-the-user-paths"},"Set the locations of the user paths"),", we learn how to define the location of our user configuration paths to avoid confusion. By doing it we ensure that when running the service, the service picks the correct configuration paths for our user.")),(0,o.kt)("p",null,"To learn more about the user $HOME directory read the wikipedia ",(0,o.kt)("a",{parentName:"p",href:"https://en.wikipedia.org/wiki/Home_directory"},"Home directory")," document."),(0,o.kt)("h2",{id:"set-the-locations-of-the-user-paths"},"Set the locations of the user paths"),(0,o.kt)(i.ZP,{mdxType:"FindAndReplaceConfigWithUserPaths"}),(0,o.kt)("h2",{id:"set-the-configuration-flag--c-on-the-service-unit-file"},"Set the configuration flag -c on the service unit file"),(0,o.kt)("p",null,"The following section assumes that a System service unit has been declared and you're using systemctl to control the service, as described in our ",(0,o.kt)("a",{parentName:"p",href:"/docs/node/install#systemd-service-setup"},"Systemd Service Setup")," install section."),(0,o.kt)("p",null,"Open and edit the ",(0,o.kt)("strong",{parentName:"p"},"/etc/systemd/system/lightning.service")," file."),(0,o.kt)("p",null,"1) Replace ",(0,o.kt)("inlineCode",{parentName:"p"},"")," with YOUR username. For example, in the documentation we use the username ",(0,o.kt)("strong",{parentName:"p"},"lgtn"),", which means we'd replace ",(0,o.kt)("inlineCode",{parentName:"p"},"User=")," with ",(0,o.kt)("inlineCode",{parentName:"p"},"User=lgtn"),"."),(0,o.kt)("p",null,"2) Make sure that the ExecStart is set correctly, including the ",(0,o.kt)("inlineCode",{parentName:"p"},"-c")),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"[Unit]\nDescription=Fleek Network Node lightning service\n\n[Service]\nUser=\nType=simple\nMemoryHigh=32G\nRestartSec=15s\nRestart=always\nExecStart=lgtn -c /home//.lightning/config.toml run\nStandardOutput=append:/var/log/lightning/output.log\nStandardError=append:/var/log/lightning/diagnostic.log\nEnvironment=TMPDIR=/var/tmp\n\n[Install]\nWantedBy=multi-user.target\n")),(0,o.kt)("p",null,"For our example, as the username ",(0,o.kt)("strong",{parentName:"p"},"lgtn")," it would look like:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"[Unit]\nDescription=Fleek Network Node lightning service\n\n[Service]\nUser=lgtn\nType=simple\nMemoryHigh=32G\nRestartSec=15s\nRestart=always\nExecStart=lgtn -c /home/lgtn/.lightning/config.toml run\nStandardOutput=append:/var/log/lightning/output.log\nStandardError=append:/var/log/lightning/diagnostic.log\nEnvironment=/var/tmp\n\n[Install]\nWantedBy=multi-user.target\n")),(0,o.kt)("p",null,"When complete make sure the file is saved and the systemctl daemon is reloaded, as follows:"),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl daemon-reload\n")),(0,o.kt)("p",null,"Consequently, when a user manages the service via the systemctl, the Lightning CLI process will read the configuration file settings provided above. It includes the location of the user preferences, such as the keystore location amongst others, preventing confusion regardless of ",(0,o.kt)("strong",{parentName:"p"},"root")," delegation."),(0,o.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}c.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>o});var r=n(7294);const o=e=>{let{image:t,name:n,title:o,url:a,communityMember:i=!1}=e;return r.createElement("section",{className:"author_card"},r.createElement("div",null,r.createElement("span",{className:"avatar"},r.createElement("a",{href:a,target:"_blank",alt:n},r.createElement("img",{src:t,alt:n}))),r.createElement("div",null,r.createElement("span",{className:"name"},r.createElement("a",{href:a,target:"_blank",alt:n},n)),r.createElement("span",{className:"title"},o),r.createElement("span",{className:"discord"},i?"Join our community on":"Got questions? Find us on"," ",r.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file diff --git a/assets/js/6be32138.1a97f838.js b/assets/js/6be32138.894c0f2b.js similarity index 99% rename from assets/js/6be32138.1a97f838.js rename to assets/js/6be32138.894c0f2b.js index 01a05a7f0..270232a3a 100644 --- a/assets/js/6be32138.1a97f838.js +++ b/assets/js/6be32138.894c0f2b.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[3396],{3905:(e,t,i)=>{i.d(t,{Zo:()=>h,kt:()=>f});var o=i(7294);function n(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}function r(e,t){var i=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),i.push.apply(i,o)}return i}function a(e){for(var t=1;t=0||(n[i]=e[i]);return n}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,i)&&(n[i]=e[i])}return n}var s=o.createContext({}),c=function(e){var t=o.useContext(s),i=t;return e&&(i="function"==typeof e?e(t):a(a({},t),e)),i},h=function(e){var t=c(e.components);return o.createElement(s.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},u=o.forwardRef((function(e,t){var i=e.components,n=e.mdxType,r=e.originalType,s=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),p=c(i),u=n,f=p["".concat(s,".").concat(u)]||p[u]||m[u]||r;return i?o.createElement(f,a(a({ref:t},h),{},{components:i})):o.createElement(f,a({ref:t},h))}));function f(e,t){var i=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var r=i.length,a=new Array(r);a[0]=u;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[p]="string"==typeof e?e:n,a[1]=l;for(var c=2;c{i.r(t),i.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>m,frontMatter:()=>r,metadata:()=>l,toc:()=>c});var o=i(7462),n=(i(7294),i(3905));const r={title:"Bloom Filters and Cuckoo Filters for Cache Summarization",description:"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.",slug:"bloom-and-cuckoo-filters-for-cache-summarization",image:"./assets/bloom-cuckoo/bloom.png?202301181528",authors:{name:"Matthias Wright",title:"Software Engineer",url:"https://github.com/matthias-wright",image_url:"https://github.com/matthias-wright.png"},tags:["fleek network","blog","engineering","content routing"]},a=void 0,l={permalink:"/blog/bloom-and-cuckoo-filters-for-cache-summarization",source:"@site/blog/bloom-and-cuckoo-filters-for-cache-summarization.md",title:"Bloom Filters and Cuckoo Filters for Cache Summarization",description:"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.",date:"2023-09-15T13:32:53.000Z",formattedDate:"September 15, 2023",tags:[{label:"fleek network",permalink:"/blog/tags/fleek-network"},{label:"blog",permalink:"/blog/tags/blog"},{label:"engineering",permalink:"/blog/tags/engineering"},{label:"content routing",permalink:"/blog/tags/content-routing"}],readingTime:10.355,hasTruncateMarker:!0,authors:[{name:"Matthias Wright",title:"Software Engineer",url:"https://github.com/matthias-wright",image_url:"https://github.com/matthias-wright.png",imageURL:"https://github.com/matthias-wright.png"}],frontMatter:{title:"Bloom Filters and Cuckoo Filters for Cache Summarization",description:"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.",slug:"bloom-and-cuckoo-filters-for-cache-summarization",image:"./assets/bloom-cuckoo/bloom.png?202301181528",authors:{name:"Matthias Wright",title:"Software Engineer",url:"https://github.com/matthias-wright",image_url:"https://github.com/matthias-wright.png",imageURL:"https://github.com/matthias-wright.png"},tags:["fleek network","blog","engineering","content routing"]}},s={image:i(4221).Z,authorsImageUrls:[void 0]},c=[{value:"Background",id:"background",level:2},{value:"Bloom Filters",id:"bloom-filters",level:2},{value:"Cuckoo Filters",id:"cuckoo-filters",level:2},{value:"Benchmarking",id:"benchmarking",level:2},{value:"Experimental Setup",id:"experimental-setup",level:2},{value:"Memory Footprint",id:"memory-footprint",level:2},{value:"Lookup Performance",id:"lookup-performance",level:2},{value:"Insertion Performance",id:"insertion-performance",level:2},{value:"Capacity and Scaling",id:"capacity-and-scaling",level:2},{value:"Other Filters",id:"other-filters",level:2},{value:"Conclusion",id:"conclusion",level:2},{value:"References",id:"references",level:3}],h={toc:c},p="wrapper";function m(e){let{components:t,...r}=e;return(0,n.kt)(p,(0,o.Z)({},h,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("p",null,"Disclaimer: This is not a general comparison between Bloom filters and Cuckoo filters. This blog post summarizes some of the experiments we conducted to decide whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters, for a specific use case."),(0,n.kt)("h2",{id:"background"},"Background"),(0,n.kt)("p",null,"Nodes on Fleek Network currently use Counting Bloom filters to summarize their cached content. These cache summaries are exchanged with other nodes in order to facilitate content routing."),(0,n.kt)("p",null,"If a particular node does not store a requested piece of content, it can use the Bloom filters that it received from its peers to check if a peer stores the requested content."),(0,n.kt)("p",null,"We are using Counting Bloom filters rather than regular Bloom filters because we need to be able to remove elements from the filter to support cache eviction."),(0,n.kt)("h2",{id:"bloom-filters"},"Bloom Filters"),(0,n.kt)("p",null,"A Bloom filter is a space-efficient probabilistic data structure that can be used to perform approximate set membership queries.\nThe answer to an approximate set membership query is not ",(0,n.kt)("inlineCode",{parentName:"p"},"no")," or ",(0,n.kt)("inlineCode",{parentName:"p"},"yes,")," but rather ",(0,n.kt)("inlineCode",{parentName:"p"},"no")," or ",(0,n.kt)("inlineCode",{parentName:"p"},"probably.")," This ",(0,n.kt)("inlineCode",{parentName:"p"},"probably")," is quantified with the false positive rate. "),(0,n.kt)("p",null,"One of the convenient features of Bloom filters is that they can be configured to have a specific false positive rate.\nOf course, there is a tradeoff here; the lower the false positive rate, the larger the memory footprint. Bloom filters support two operations: ",(0,n.kt)("inlineCode",{parentName:"p"},"insert")," and ",(0,n.kt)("inlineCode",{parentName:"p"},"contains.")," "),(0,n.kt)("p",null,"A Bloom filter is represented by an array of m bits together with k independent hash functions. To insert an element into the filter, it is hashed with each of the k hash functions.\nThe resulting hashes are interpreted as integers (modulo m) to obtain k array positions. The bits at these positions are then set to 1 (if there aren't already 1).",(0,n.kt)("br",{parentName:"p"}),"\n","To check whether or not an element is contained in the filter, the element is hashed k times with the different hash functions."),(0,n.kt)("p",null,"If all bits at the resulting array positions are 1, the element is assumed to be present. If any of the k bits are zero, we can be certain that the queried element is not present in the set."),(0,n.kt)("p",null,"However, even if all bits are 1, it might still be the case that the bits were set by a combination of other elements. This is where the aforementioned false positive rate comes into play. "),(0,n.kt)("p",null,"Since we also need a ",(0,n.kt)("inlineCode",{parentName:"p"},"remove")," operation for our use case, we have been using Counting Bloom filters, a variant of Bloom filters.\nCounting Bloom filters retain most of the properties that regular Bloom filters have. The ",(0,n.kt)("inlineCode",{parentName:"p"},"remove")," operation comes at the cost of an increased memory footprint."),(0,n.kt)("p",null,"Each position in the array is no longer a single bit but a group of bits representing a counter.\nWhenever an element is inserted into the filter, the counters for all k positions are incremented by 1. To remove an element, we decrement the counters."),(0,n.kt)("h2",{id:"cuckoo-filters"},"Cuckoo Filters"),(0,n.kt)("p",null,"Bloom filters are the most known members of a class of data structures called Approximate Membership Query Filters (AMQ Filters).\nA relatively recent addition to this class is the Cuckoo filter ","[1]",". Cuckoo filters share many similarities with Bloom filters, especially Counting Bloom filters."),(0,n.kt)("p",null,"They are space-efficient and can be used for approximate set membership queries. Cuckoo filters also support the operations ",(0,n.kt)("inlineCode",{parentName:"p"},"insert,")," ",(0,n.kt)("inlineCode",{parentName:"p"},"contains,")," and ",(0,n.kt)("inlineCode",{parentName:"p"},"remove,")," and have configurable false positive rates. "),(0,n.kt)("p",null,"Cuckoo filters are based on Cuckoo hash tables ","[2]"," and leverage an optimization called partial-key cuckoo hashing. A basic Cuckoo hash table consists of an array of buckets.\nWe determine two candidate buckets for each element using two different hash functions, h1 and h2. "),(0,n.kt)("p",null,"The ",(0,n.kt)("inlineCode",{parentName:"p"},"contains")," operation will check if either bucket contains the element.\nFor insertion, if either bucket is empty, the element will be inserted into the empty bucket."),(0,n.kt)("p",null,"If neither bucket is empty, one of the buckets is selected, and the existing element is removed and inserted into its alternate location.\nThis may trigger another relocation if the alternate location is not empty. "),(0,n.kt)("p",null,"Although the insertion operation may perform a sequence of relocations, the amortized runtime is O(1). "),(0,n.kt)("p",null,"Most implementations of Cuckoo hash tables and, consequently, Cuckoo filters will use buckets that can hold multiple elements, as proposed in ","[3]","."),(0,n.kt)("p",null,"For Cuckoo filters, the hash table size is reduced by only storing fingerprints - a bit string calculated from an element's hash - rather than key-value pairs."),(0,n.kt)("p",null,"The fingerprint size is derived from the desired false positive rate.",(0,n.kt)("br",{parentName:"p"}),"\n","A problem that arises is that, to relocate existing fingerprints using the Cuckoo hashing approach described above, we need the original hash from which the fingerprint was derived."),(0,n.kt)("p",null,"Of course, we could store this hash somewhere, but the whole point of using fingerprints is to reduce the memory footprint of the filter."),(0,n.kt)("p",null,"The solution to this predicament is the aforementioned partial-key cuckoo hashing, a technique for determining an element's alternate location using only its fingerprint.",(0,n.kt)("br",{parentName:"p"}),"\n","For a given element x, the two candidate buckets are computed as follows: "),(0,n.kt)("p",null,(0,n.kt)("img",{src:i(9440).Z,width:"1324",height:"194"})),(0,n.kt)("p",null,"An important property of this technique is that h1(x) can also be computed from h2(x) and the fingerprint."),(0,n.kt)("h2",{id:"benchmarking"},"Benchmarking"),(0,n.kt)("p",null,"As this post mentioned, we are not aiming for a general comparison of Counting Bloom and Cuckoo filters."),(0,n.kt)("p",null,"Instead, we want to determine which filter suits our specific use case better. The two main properties we are looking for are space efficiency and lookup performance. "),(0,n.kt)("p",null,"Space efficiency is important because nodes frequently update their cache and have to communicate these changes with their peers. These messages should take up as little bandwidth as possible."),(0,n.kt)("p",null,"Lookup speed is also important because Fleek Network aims to serve user requests as quickly as possible. Checking whether a peer has some content stored in their cache summary should not be a bottleneck. "),(0,n.kt)("h2",{id:"experimental-setup"},"Experimental Setup"),(0,n.kt)("p",null,"We are using our own Counting Bloom filter ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/ursa/blob/483f4d56cbaa5e83182454d2c1db6f6af7c54912/crates/ursa-network/src/utils/bloom_filter.rs#L11"},"implementation")," and\n",(0,n.kt)("a",{parentName:"p",href:"https://github.com/sile/scalable_cuckoo_filter"},"this")," Cuckoo filter implementation in Rust (the ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/efficient/cuckoofilter"},"original")," implementation is in C++). All experiments\nwere performed on a Linux machine with 16 GB RAM and an Intel Core i7 (10th Gen). Whenever the experiment is probabilistic, we repeat the experiment 20 times and report the mean and standard deviation."),(0,n.kt)("h2",{id:"memory-footprint"},"Memory Footprint"),(0,n.kt)("p",null,"For both Counting Bloom filters and Cuckoo filters, the memory footprint is determined by two factors: the filter's capacity and the desired false positive rate. In the first experiment, we examine the impact that\nthese factors have on the memory footprint. "),(0,n.kt)("p",null,"To this end, we fix the false positive rate and initialize the filters with capacities ranging from 100K to 1M. The result is shown in Fig. 1.\nThe size of Bloom filters scales linearly with the capacity. Cuckoo filters are more space-efficient. This result is consistent with the experiments reported in ","[1]","."),(0,n.kt)("p",null,(0,n.kt)("img",{src:i(5441).Z,width:"640",height:"480"})),(0,n.kt)("blockquote",null,(0,n.kt)("p",{parentName:"blockquote"},"Figure 1: We fix the false positive rate and initialize the filters with capacities ranging from 100K to 1M. The y-axis shows the size of the filters in Megabytes.")),(0,n.kt)("p",null,"Next, we fix the capacity and initialize the filters with false positive rates ranging from 0.0001 to 0.5. Fig. 2 shows that Cuckoo filters are more space-efficient."),(0,n.kt)("p",null,"The gap between Counting Bloom filters and Cuckoo filters grows as the false positive rate decreases. This is also consistent with experiments in ","[1]","."),(0,n.kt)("p",null,(0,n.kt)("img",{src:i(9844).Z,width:"640",height:"480"})),(0,n.kt)("blockquote",null,(0,n.kt)("p",{parentName:"blockquote"},"Figure 2: We fix the capacity and initialize the filters with false positive rates ranging from 0.0001 to 0.5. The y-axis shows the size of the filters in Megabytes.")),(0,n.kt)("h2",{id:"lookup-performance"},"Lookup Performance"),(0,n.kt)("p",null,"We first add elements to both filters until the capacity is reached. We then measure the lookup performance for different ratios of positive and negative lookups."),(0,n.kt)("p",null,"A positive lookup is for an existing element, and a negative lookup is for an element not contained in the filter. We perform 100K lookups for each ratio and report the average lookup duration and standard deviation. "),(0,n.kt)("p",null,"Fig. 3 shows the results. Bloom filters perform slightly better on average than Cuckoo filters. This result is inconsistent with ","[1]",",\nwhere Cuckoo filters were reported to have a better lookup performance than Bloom filters. It should be noted here that the authors in ","[1]"," use the original C++ Cuckoo filter implementation and their own unreleased Bloom filter implementation. In contrast, we use a Rust Cuckoo filter implementation and our Bloom filter implementation. We cannot easily determine the reason for this discrepancy."),(0,n.kt)("p",null,"However, the performance difference is negligible."),(0,n.kt)("p",null,(0,n.kt)("img",{src:i(8915).Z,width:"640",height:"480"})),(0,n.kt)("blockquote",null,(0,n.kt)("p",{parentName:"blockquote"},"Figure 3: Lookup performance for different ratios of positive and negative lookups. For example, ratio 0.25 indicates that 25% of lookups are positive and 75% are negative.\nThe shaded region indicates the standard deviation.")),(0,n.kt)("h2",{id:"insertion-performance"},"Insertion Performance"),(0,n.kt)("p",null,"Less critical than lookup performance but still important for our purposes is insertion performance. We measure how the insertion performance varies for different occupancy levels.\nFig. 4 shows the results. The insertion performance is constant across all levels of occupancy for Bloom filters."),(0,n.kt)("p",null,"For Cuckoo filters, the performance decreases as the filter becomes fuller because more relocations are required. In Fig. 4, the performance for Bloom filters is not constant. It quickly increases and then remains constant. This can be explained by CPU caching. "),(0,n.kt)("p",null,(0,n.kt)("img",{src:i(989).Z,width:"640",height:"480"})),(0,n.kt)("blockquote",null,(0,n.kt)("p",{parentName:"blockquote"},"Figure 4: Insertion performance for different occupancy levels. The shaded region indicates the standard deviation.")),(0,n.kt)("h2",{id:"capacity-and-scaling"},"Capacity and Scaling"),(0,n.kt)("p",null,"We have mentioned the capacity of a filter several times now. An interesting case is what happens when a filter's capacity is exceeded.\nBloom filters and Cuckoo filters behave differently in this scenario."),(0,n.kt)("p",null,"For Bloom filters, the ",(0,n.kt)("inlineCode",{parentName:"p"},"insertion")," operation always succeeds. However, the false positive rate will rapidly increase as we exceed the filter's capacity. While Bloom filters fail silently, Cuckoo filters are more explicit. Most implementations have a maximum number of\nrelocations that will be performed for an insertion. The ",(0,n.kt)("inlineCode",{parentName:"p"},"insertion")," operation will return an error if more relocations are required. "),(0,n.kt)("p",null,"For both filters, we can avoid this problem by simply initializing the filter with a sufficiently large capacity. However, this will increase the memory footprint of the filter."),(0,n.kt)("p",null,"Furthermore, it is difficult to predict how many elements a node on Fleek Network will cache. It is also likely that the number of cached elements will greatly vary for different nodes. "),(0,n.kt)("p",null,"Fortunately, a variant of Bloom filters called Scalable Bloom Filters ","[4]"," can adapt dynamically to the number of elements stored while guaranteeing a maximum false positive rate."),(0,n.kt)("p",null,"The proposed technique is also applicable to Cuckoo filters."),(0,n.kt)("h2",{id:"other-filters"},"Other Filters"),(0,n.kt)("p",null,"While we only looked at Bloom filters and Cuckoo filters, there are other AMQ filters that we want to mention here briefly:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"Quotient filters ","[5, 6]",": Compact hash tables that support insertion, lookup, and deletion. Less space-efficient than Bloom filters and Cuckoo filters. ")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"XOR filters ","[7]",": More space-efficient than Bloom filters and Cuckoo filters. However, they are static, meaning the filter has to be rebuilt if additional elements are added. "))),(0,n.kt)("h2",{id:"conclusion"},"Conclusion"),(0,n.kt)("p",null,"We examined whether Counting Bloom filters or Cuckoo filters are more suitable for summarizing caches on Fleek Network. Cuckoo filters are more space-efficient, especially for lower false positive rates. Bloom filters have a slightly better insertion and lookup performance for the implementations we tested."),(0,n.kt)("p",null,"Both filters can be adapted to grow and shrink in size dynamically. Since the difference in insertion and lookup performance is negligible while Cuckoo filters are significantly more space-efficient, we favor Cuckoo filters for our use case. "),(0,n.kt)("h3",{id:"references"},"References"),(0,n.kt)("p",null,"[1]"," Bin Fan, Dave G. Andersen, Michael Kaminsky, and Michael D. Mitzenmacher. Cuckoo Filter: Practically Better Than Bloom.\nIn Proceedings of the 10th ACM International Conference on emerging Networking Experiments and Technologies (CoNEXT 14). Association for Computing Machinery, New York, NY, USA, pp. 75-88, 2014. "),(0,n.kt)("p",null,"[2]"," Rasmus Pagha and Flemming Friche Rodler. Cuckoo hashing. Journal of Algorithms, 51(2), pp. 122-144, 2004. "),(0,n.kt)("p",null,"[3]"," Martin Dietzfelbinger and Christoph Weidling. Balanced Allocation and Dictionaries with Tightly Packed Constant Size Bins. Theoretical Computer Science, 380(1), pp. 47-68, 2007. "),(0,n.kt)("p",null,"[4]"," Paulo S. Almeida, Carlos Baquero, Nuno Pregui\xe7a, and David Hutchison. Scalable Bloom Filters. Information Processing Letters, 101(6), pp. 255-261, 2007. "),(0,n.kt)("p",null,"[5]"," John G. Cleary. Compact hash tables using bidirectional linear probing. IEEE Transactions on Computers. 33(9), pp. 828-834, 1984. "),(0,n.kt)("p",null,"[6]"," Anna Pagh, Rasmus Pagh, and S. Srinivasa Rao. An optimal Bloom filter replacement. Proceedings of the Sixteenth Annual ACM-SIAM Symposium on Discrete Algorithms, pp. 823-829, 2005. "),(0,n.kt)("p",null,"[7]"," Thomas Mueller Graf and Daniel Lemire. Xor Filters: Faster and Smaller Than Bloom and Cuckoo Filters. ACM Journal of Experimental Algorithmics. 25, pp. 1-16, 2020."))}m.isMDXComponent=!0},4221:(e,t,i)=>{i.d(t,{Z:()=>o});const o=i.p+"assets/images/bloom-79da0db687b4fb2060758838b9c44513.png"},5441:(e,t,i)=>{i.d(t,{Z:()=>o});const o=i.p+"assets/images/capacity-size-5c2576bd69db0e5b510781e7cc1c5257.png"},9844:(e,t,i)=>{i.d(t,{Z:()=>o});const o=i.p+"assets/images/fp-rate-size-fbb54b2450b4a91e28c97d8adf0253e8.png"},989:(e,t,i)=>{i.d(t,{Z:()=>o});const o=i.p+"assets/images/insert-3ff48d4c63724adcf399f81b29607691.png"},8915:(e,t,i)=>{i.d(t,{Z:()=>o});const o=i.p+"assets/images/lookup-e36011237d8602b5f6c36fe5dd145bf5.png"},9440:(e,t,i)=>{i.d(t,{Z:()=>o});const o=i.p+"assets/images/math-formul-a247d4df475b26b1e7cbb2acfc0ab8c2.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[3396],{3905:(e,t,i)=>{i.d(t,{Zo:()=>h,kt:()=>f});var o=i(7294);function n(e,t,i){return t in e?Object.defineProperty(e,t,{value:i,enumerable:!0,configurable:!0,writable:!0}):e[t]=i,e}function r(e,t){var i=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),i.push.apply(i,o)}return i}function a(e){for(var t=1;t=0||(n[i]=e[i]);return n}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,i)&&(n[i]=e[i])}return n}var s=o.createContext({}),c=function(e){var t=o.useContext(s),i=t;return e&&(i="function"==typeof e?e(t):a(a({},t),e)),i},h=function(e){var t=c(e.components);return o.createElement(s.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},u=o.forwardRef((function(e,t){var i=e.components,n=e.mdxType,r=e.originalType,s=e.parentName,h=l(e,["components","mdxType","originalType","parentName"]),p=c(i),u=n,f=p["".concat(s,".").concat(u)]||p[u]||m[u]||r;return i?o.createElement(f,a(a({ref:t},h),{},{components:i})):o.createElement(f,a({ref:t},h))}));function f(e,t){var i=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var r=i.length,a=new Array(r);a[0]=u;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l[p]="string"==typeof e?e:n,a[1]=l;for(var c=2;c{i.r(t),i.d(t,{assets:()=>s,contentTitle:()=>a,default:()=>m,frontMatter:()=>r,metadata:()=>l,toc:()=>c});var o=i(7462),n=(i(7294),i(3905));const r={title:"Bloom Filters and Cuckoo Filters for Cache Summarization",description:"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.",slug:"bloom-and-cuckoo-filters-for-cache-summarization",image:"./assets/bloom-cuckoo/bloom.png?202301181528",authors:{name:"Matthias Wright",title:"Software Engineer",url:"https://github.com/matthias-wright",image_url:"https://github.com/matthias-wright.png"},tags:["fleek network","blog","engineering","content routing"]},a=void 0,l={permalink:"/blog/bloom-and-cuckoo-filters-for-cache-summarization",source:"@site/blog/bloom-and-cuckoo-filters-for-cache-summarization.md",title:"Bloom Filters and Cuckoo Filters for Cache Summarization",description:"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.",date:"2023-09-15T13:40:42.000Z",formattedDate:"September 15, 2023",tags:[{label:"fleek network",permalink:"/blog/tags/fleek-network"},{label:"blog",permalink:"/blog/tags/blog"},{label:"engineering",permalink:"/blog/tags/engineering"},{label:"content routing",permalink:"/blog/tags/content-routing"}],readingTime:10.355,hasTruncateMarker:!0,authors:[{name:"Matthias Wright",title:"Software Engineer",url:"https://github.com/matthias-wright",image_url:"https://github.com/matthias-wright.png",imageURL:"https://github.com/matthias-wright.png"}],frontMatter:{title:"Bloom Filters and Cuckoo Filters for Cache Summarization",description:"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.",slug:"bloom-and-cuckoo-filters-for-cache-summarization",image:"./assets/bloom-cuckoo/bloom.png?202301181528",authors:{name:"Matthias Wright",title:"Software Engineer",url:"https://github.com/matthias-wright",image_url:"https://github.com/matthias-wright.png",imageURL:"https://github.com/matthias-wright.png"},tags:["fleek network","blog","engineering","content routing"]}},s={image:i(4221).Z,authorsImageUrls:[void 0]},c=[{value:"Background",id:"background",level:2},{value:"Bloom Filters",id:"bloom-filters",level:2},{value:"Cuckoo Filters",id:"cuckoo-filters",level:2},{value:"Benchmarking",id:"benchmarking",level:2},{value:"Experimental Setup",id:"experimental-setup",level:2},{value:"Memory Footprint",id:"memory-footprint",level:2},{value:"Lookup Performance",id:"lookup-performance",level:2},{value:"Insertion Performance",id:"insertion-performance",level:2},{value:"Capacity and Scaling",id:"capacity-and-scaling",level:2},{value:"Other Filters",id:"other-filters",level:2},{value:"Conclusion",id:"conclusion",level:2},{value:"References",id:"references",level:3}],h={toc:c},p="wrapper";function m(e){let{components:t,...r}=e;return(0,n.kt)(p,(0,o.Z)({},h,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("p",null,"Disclaimer: This is not a general comparison between Bloom filters and Cuckoo filters. This blog post summarizes some of the experiments we conducted to decide whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters, for a specific use case."),(0,n.kt)("h2",{id:"background"},"Background"),(0,n.kt)("p",null,"Nodes on Fleek Network currently use Counting Bloom filters to summarize their cached content. These cache summaries are exchanged with other nodes in order to facilitate content routing."),(0,n.kt)("p",null,"If a particular node does not store a requested piece of content, it can use the Bloom filters that it received from its peers to check if a peer stores the requested content."),(0,n.kt)("p",null,"We are using Counting Bloom filters rather than regular Bloom filters because we need to be able to remove elements from the filter to support cache eviction."),(0,n.kt)("h2",{id:"bloom-filters"},"Bloom Filters"),(0,n.kt)("p",null,"A Bloom filter is a space-efficient probabilistic data structure that can be used to perform approximate set membership queries.\nThe answer to an approximate set membership query is not ",(0,n.kt)("inlineCode",{parentName:"p"},"no")," or ",(0,n.kt)("inlineCode",{parentName:"p"},"yes,")," but rather ",(0,n.kt)("inlineCode",{parentName:"p"},"no")," or ",(0,n.kt)("inlineCode",{parentName:"p"},"probably.")," This ",(0,n.kt)("inlineCode",{parentName:"p"},"probably")," is quantified with the false positive rate. "),(0,n.kt)("p",null,"One of the convenient features of Bloom filters is that they can be configured to have a specific false positive rate.\nOf course, there is a tradeoff here; the lower the false positive rate, the larger the memory footprint. Bloom filters support two operations: ",(0,n.kt)("inlineCode",{parentName:"p"},"insert")," and ",(0,n.kt)("inlineCode",{parentName:"p"},"contains.")," "),(0,n.kt)("p",null,"A Bloom filter is represented by an array of m bits together with k independent hash functions. To insert an element into the filter, it is hashed with each of the k hash functions.\nThe resulting hashes are interpreted as integers (modulo m) to obtain k array positions. The bits at these positions are then set to 1 (if there aren't already 1).",(0,n.kt)("br",{parentName:"p"}),"\n","To check whether or not an element is contained in the filter, the element is hashed k times with the different hash functions."),(0,n.kt)("p",null,"If all bits at the resulting array positions are 1, the element is assumed to be present. If any of the k bits are zero, we can be certain that the queried element is not present in the set."),(0,n.kt)("p",null,"However, even if all bits are 1, it might still be the case that the bits were set by a combination of other elements. This is where the aforementioned false positive rate comes into play. "),(0,n.kt)("p",null,"Since we also need a ",(0,n.kt)("inlineCode",{parentName:"p"},"remove")," operation for our use case, we have been using Counting Bloom filters, a variant of Bloom filters.\nCounting Bloom filters retain most of the properties that regular Bloom filters have. The ",(0,n.kt)("inlineCode",{parentName:"p"},"remove")," operation comes at the cost of an increased memory footprint."),(0,n.kt)("p",null,"Each position in the array is no longer a single bit but a group of bits representing a counter.\nWhenever an element is inserted into the filter, the counters for all k positions are incremented by 1. To remove an element, we decrement the counters."),(0,n.kt)("h2",{id:"cuckoo-filters"},"Cuckoo Filters"),(0,n.kt)("p",null,"Bloom filters are the most known members of a class of data structures called Approximate Membership Query Filters (AMQ Filters).\nA relatively recent addition to this class is the Cuckoo filter ","[1]",". Cuckoo filters share many similarities with Bloom filters, especially Counting Bloom filters."),(0,n.kt)("p",null,"They are space-efficient and can be used for approximate set membership queries. Cuckoo filters also support the operations ",(0,n.kt)("inlineCode",{parentName:"p"},"insert,")," ",(0,n.kt)("inlineCode",{parentName:"p"},"contains,")," and ",(0,n.kt)("inlineCode",{parentName:"p"},"remove,")," and have configurable false positive rates. "),(0,n.kt)("p",null,"Cuckoo filters are based on Cuckoo hash tables ","[2]"," and leverage an optimization called partial-key cuckoo hashing. A basic Cuckoo hash table consists of an array of buckets.\nWe determine two candidate buckets for each element using two different hash functions, h1 and h2. "),(0,n.kt)("p",null,"The ",(0,n.kt)("inlineCode",{parentName:"p"},"contains")," operation will check if either bucket contains the element.\nFor insertion, if either bucket is empty, the element will be inserted into the empty bucket."),(0,n.kt)("p",null,"If neither bucket is empty, one of the buckets is selected, and the existing element is removed and inserted into its alternate location.\nThis may trigger another relocation if the alternate location is not empty. "),(0,n.kt)("p",null,"Although the insertion operation may perform a sequence of relocations, the amortized runtime is O(1). "),(0,n.kt)("p",null,"Most implementations of Cuckoo hash tables and, consequently, Cuckoo filters will use buckets that can hold multiple elements, as proposed in ","[3]","."),(0,n.kt)("p",null,"For Cuckoo filters, the hash table size is reduced by only storing fingerprints - a bit string calculated from an element's hash - rather than key-value pairs."),(0,n.kt)("p",null,"The fingerprint size is derived from the desired false positive rate.",(0,n.kt)("br",{parentName:"p"}),"\n","A problem that arises is that, to relocate existing fingerprints using the Cuckoo hashing approach described above, we need the original hash from which the fingerprint was derived."),(0,n.kt)("p",null,"Of course, we could store this hash somewhere, but the whole point of using fingerprints is to reduce the memory footprint of the filter."),(0,n.kt)("p",null,"The solution to this predicament is the aforementioned partial-key cuckoo hashing, a technique for determining an element's alternate location using only its fingerprint.",(0,n.kt)("br",{parentName:"p"}),"\n","For a given element x, the two candidate buckets are computed as follows: "),(0,n.kt)("p",null,(0,n.kt)("img",{src:i(9440).Z,width:"1324",height:"194"})),(0,n.kt)("p",null,"An important property of this technique is that h1(x) can also be computed from h2(x) and the fingerprint."),(0,n.kt)("h2",{id:"benchmarking"},"Benchmarking"),(0,n.kt)("p",null,"As this post mentioned, we are not aiming for a general comparison of Counting Bloom and Cuckoo filters."),(0,n.kt)("p",null,"Instead, we want to determine which filter suits our specific use case better. The two main properties we are looking for are space efficiency and lookup performance. "),(0,n.kt)("p",null,"Space efficiency is important because nodes frequently update their cache and have to communicate these changes with their peers. These messages should take up as little bandwidth as possible."),(0,n.kt)("p",null,"Lookup speed is also important because Fleek Network aims to serve user requests as quickly as possible. Checking whether a peer has some content stored in their cache summary should not be a bottleneck. "),(0,n.kt)("h2",{id:"experimental-setup"},"Experimental Setup"),(0,n.kt)("p",null,"We are using our own Counting Bloom filter ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/ursa/blob/483f4d56cbaa5e83182454d2c1db6f6af7c54912/crates/ursa-network/src/utils/bloom_filter.rs#L11"},"implementation")," and\n",(0,n.kt)("a",{parentName:"p",href:"https://github.com/sile/scalable_cuckoo_filter"},"this")," Cuckoo filter implementation in Rust (the ",(0,n.kt)("a",{parentName:"p",href:"https://github.com/efficient/cuckoofilter"},"original")," implementation is in C++). All experiments\nwere performed on a Linux machine with 16 GB RAM and an Intel Core i7 (10th Gen). Whenever the experiment is probabilistic, we repeat the experiment 20 times and report the mean and standard deviation."),(0,n.kt)("h2",{id:"memory-footprint"},"Memory Footprint"),(0,n.kt)("p",null,"For both Counting Bloom filters and Cuckoo filters, the memory footprint is determined by two factors: the filter's capacity and the desired false positive rate. In the first experiment, we examine the impact that\nthese factors have on the memory footprint. "),(0,n.kt)("p",null,"To this end, we fix the false positive rate and initialize the filters with capacities ranging from 100K to 1M. The result is shown in Fig. 1.\nThe size of Bloom filters scales linearly with the capacity. Cuckoo filters are more space-efficient. This result is consistent with the experiments reported in ","[1]","."),(0,n.kt)("p",null,(0,n.kt)("img",{src:i(5441).Z,width:"640",height:"480"})),(0,n.kt)("blockquote",null,(0,n.kt)("p",{parentName:"blockquote"},"Figure 1: We fix the false positive rate and initialize the filters with capacities ranging from 100K to 1M. The y-axis shows the size of the filters in Megabytes.")),(0,n.kt)("p",null,"Next, we fix the capacity and initialize the filters with false positive rates ranging from 0.0001 to 0.5. Fig. 2 shows that Cuckoo filters are more space-efficient."),(0,n.kt)("p",null,"The gap between Counting Bloom filters and Cuckoo filters grows as the false positive rate decreases. This is also consistent with experiments in ","[1]","."),(0,n.kt)("p",null,(0,n.kt)("img",{src:i(9844).Z,width:"640",height:"480"})),(0,n.kt)("blockquote",null,(0,n.kt)("p",{parentName:"blockquote"},"Figure 2: We fix the capacity and initialize the filters with false positive rates ranging from 0.0001 to 0.5. The y-axis shows the size of the filters in Megabytes.")),(0,n.kt)("h2",{id:"lookup-performance"},"Lookup Performance"),(0,n.kt)("p",null,"We first add elements to both filters until the capacity is reached. We then measure the lookup performance for different ratios of positive and negative lookups."),(0,n.kt)("p",null,"A positive lookup is for an existing element, and a negative lookup is for an element not contained in the filter. We perform 100K lookups for each ratio and report the average lookup duration and standard deviation. "),(0,n.kt)("p",null,"Fig. 3 shows the results. Bloom filters perform slightly better on average than Cuckoo filters. This result is inconsistent with ","[1]",",\nwhere Cuckoo filters were reported to have a better lookup performance than Bloom filters. It should be noted here that the authors in ","[1]"," use the original C++ Cuckoo filter implementation and their own unreleased Bloom filter implementation. In contrast, we use a Rust Cuckoo filter implementation and our Bloom filter implementation. We cannot easily determine the reason for this discrepancy."),(0,n.kt)("p",null,"However, the performance difference is negligible."),(0,n.kt)("p",null,(0,n.kt)("img",{src:i(8915).Z,width:"640",height:"480"})),(0,n.kt)("blockquote",null,(0,n.kt)("p",{parentName:"blockquote"},"Figure 3: Lookup performance for different ratios of positive and negative lookups. For example, ratio 0.25 indicates that 25% of lookups are positive and 75% are negative.\nThe shaded region indicates the standard deviation.")),(0,n.kt)("h2",{id:"insertion-performance"},"Insertion Performance"),(0,n.kt)("p",null,"Less critical than lookup performance but still important for our purposes is insertion performance. We measure how the insertion performance varies for different occupancy levels.\nFig. 4 shows the results. The insertion performance is constant across all levels of occupancy for Bloom filters."),(0,n.kt)("p",null,"For Cuckoo filters, the performance decreases as the filter becomes fuller because more relocations are required. In Fig. 4, the performance for Bloom filters is not constant. It quickly increases and then remains constant. This can be explained by CPU caching. "),(0,n.kt)("p",null,(0,n.kt)("img",{src:i(989).Z,width:"640",height:"480"})),(0,n.kt)("blockquote",null,(0,n.kt)("p",{parentName:"blockquote"},"Figure 4: Insertion performance for different occupancy levels. The shaded region indicates the standard deviation.")),(0,n.kt)("h2",{id:"capacity-and-scaling"},"Capacity and Scaling"),(0,n.kt)("p",null,"We have mentioned the capacity of a filter several times now. An interesting case is what happens when a filter's capacity is exceeded.\nBloom filters and Cuckoo filters behave differently in this scenario."),(0,n.kt)("p",null,"For Bloom filters, the ",(0,n.kt)("inlineCode",{parentName:"p"},"insertion")," operation always succeeds. However, the false positive rate will rapidly increase as we exceed the filter's capacity. While Bloom filters fail silently, Cuckoo filters are more explicit. Most implementations have a maximum number of\nrelocations that will be performed for an insertion. The ",(0,n.kt)("inlineCode",{parentName:"p"},"insertion")," operation will return an error if more relocations are required. "),(0,n.kt)("p",null,"For both filters, we can avoid this problem by simply initializing the filter with a sufficiently large capacity. However, this will increase the memory footprint of the filter."),(0,n.kt)("p",null,"Furthermore, it is difficult to predict how many elements a node on Fleek Network will cache. It is also likely that the number of cached elements will greatly vary for different nodes. "),(0,n.kt)("p",null,"Fortunately, a variant of Bloom filters called Scalable Bloom Filters ","[4]"," can adapt dynamically to the number of elements stored while guaranteeing a maximum false positive rate."),(0,n.kt)("p",null,"The proposed technique is also applicable to Cuckoo filters."),(0,n.kt)("h2",{id:"other-filters"},"Other Filters"),(0,n.kt)("p",null,"While we only looked at Bloom filters and Cuckoo filters, there are other AMQ filters that we want to mention here briefly:"),(0,n.kt)("ul",null,(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"Quotient filters ","[5, 6]",": Compact hash tables that support insertion, lookup, and deletion. Less space-efficient than Bloom filters and Cuckoo filters. ")),(0,n.kt)("li",{parentName:"ul"},(0,n.kt)("p",{parentName:"li"},"XOR filters ","[7]",": More space-efficient than Bloom filters and Cuckoo filters. However, they are static, meaning the filter has to be rebuilt if additional elements are added. "))),(0,n.kt)("h2",{id:"conclusion"},"Conclusion"),(0,n.kt)("p",null,"We examined whether Counting Bloom filters or Cuckoo filters are more suitable for summarizing caches on Fleek Network. Cuckoo filters are more space-efficient, especially for lower false positive rates. Bloom filters have a slightly better insertion and lookup performance for the implementations we tested."),(0,n.kt)("p",null,"Both filters can be adapted to grow and shrink in size dynamically. Since the difference in insertion and lookup performance is negligible while Cuckoo filters are significantly more space-efficient, we favor Cuckoo filters for our use case. "),(0,n.kt)("h3",{id:"references"},"References"),(0,n.kt)("p",null,"[1]"," Bin Fan, Dave G. Andersen, Michael Kaminsky, and Michael D. Mitzenmacher. Cuckoo Filter: Practically Better Than Bloom.\nIn Proceedings of the 10th ACM International Conference on emerging Networking Experiments and Technologies (CoNEXT 14). Association for Computing Machinery, New York, NY, USA, pp. 75-88, 2014. "),(0,n.kt)("p",null,"[2]"," Rasmus Pagha and Flemming Friche Rodler. Cuckoo hashing. Journal of Algorithms, 51(2), pp. 122-144, 2004. "),(0,n.kt)("p",null,"[3]"," Martin Dietzfelbinger and Christoph Weidling. Balanced Allocation and Dictionaries with Tightly Packed Constant Size Bins. Theoretical Computer Science, 380(1), pp. 47-68, 2007. "),(0,n.kt)("p",null,"[4]"," Paulo S. Almeida, Carlos Baquero, Nuno Pregui\xe7a, and David Hutchison. Scalable Bloom Filters. Information Processing Letters, 101(6), pp. 255-261, 2007. "),(0,n.kt)("p",null,"[5]"," John G. Cleary. Compact hash tables using bidirectional linear probing. IEEE Transactions on Computers. 33(9), pp. 828-834, 1984. "),(0,n.kt)("p",null,"[6]"," Anna Pagh, Rasmus Pagh, and S. Srinivasa Rao. An optimal Bloom filter replacement. Proceedings of the Sixteenth Annual ACM-SIAM Symposium on Discrete Algorithms, pp. 823-829, 2005. "),(0,n.kt)("p",null,"[7]"," Thomas Mueller Graf and Daniel Lemire. Xor Filters: Faster and Smaller Than Bloom and Cuckoo Filters. ACM Journal of Experimental Algorithmics. 25, pp. 1-16, 2020."))}m.isMDXComponent=!0},4221:(e,t,i)=>{i.d(t,{Z:()=>o});const o=i.p+"assets/images/bloom-79da0db687b4fb2060758838b9c44513.png"},5441:(e,t,i)=>{i.d(t,{Z:()=>o});const o=i.p+"assets/images/capacity-size-5c2576bd69db0e5b510781e7cc1c5257.png"},9844:(e,t,i)=>{i.d(t,{Z:()=>o});const o=i.p+"assets/images/fp-rate-size-fbb54b2450b4a91e28c97d8adf0253e8.png"},989:(e,t,i)=>{i.d(t,{Z:()=>o});const o=i.p+"assets/images/insert-3ff48d4c63724adcf399f81b29607691.png"},8915:(e,t,i)=>{i.d(t,{Z:()=>o});const o=i.p+"assets/images/lookup-e36011237d8602b5f6c36fe5dd145bf5.png"},9440:(e,t,i)=>{i.d(t,{Z:()=>o});const o=i.p+"assets/images/math-formul-a247d4df475b26b1e7cbb2acfc0ab8c2.png"}}]); \ No newline at end of file diff --git a/assets/js/8a92e787.cf4549b3.js b/assets/js/8a92e787.7a2a56d9.js similarity index 99% rename from assets/js/8a92e787.cf4549b3.js rename to assets/js/8a92e787.7a2a56d9.js index dfd3ec9cf..66f853ac8 100644 --- a/assets/js/8a92e787.cf4549b3.js +++ b/assets/js/8a92e787.7a2a56d9.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[2517],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>m});var r=n(7294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var c=r.createContext({}),i=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},u=function(e){var t=i(e.components);return r.createElement(c.Provider,{value:t},e.children)},d="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},g=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,a=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=i(n),g=s,m=d["".concat(c,".").concat(g)]||d[g]||p[g]||a;return n?r.createElement(m,o(o({ref:t},u),{},{components:n})):r.createElement(m,o({ref:t},u))}));function m(e,t){var n=arguments,s=t&&t.mdxType;if("string"==typeof e||s){var a=n.length,o=new Array(a);o[0]=g;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[d]="string"==typeof e?e:s,o[1]=l;for(var i=2;i{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>l,default:()=>g,frontMatter:()=>o,metadata:()=>c,toc:()=>u});var r=n(7462),s=(n(7294),n(3905)),a=n(3872);const o={title:"Shutting down persistance",slug:"shutting-down-persistance",hide_title:!0,tags:["reference","shutdown","frozen","idle","service error","systemctl","systemd"]},l=void 0,c={unversionedId:"Systemd/shutting-down-persistance",id:"Systemd/shutting-down-persistance",title:"Shutting down persistance",description:"Systemd Service as frozen or idle",source:"@site/references/Systemd/shutting-down-persistance.md",sourceDirName:"Systemd",slug:"/Systemd/shutting-down-persistance",permalink:"/references/Systemd/shutting-down-persistance",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Systemd/shutting-down-persistance.md",tags:[{label:"reference",permalink:"/references/tags/reference"},{label:"shutdown",permalink:"/references/tags/shutdown"},{label:"frozen",permalink:"/references/tags/frozen"},{label:"idle",permalink:"/references/tags/idle"},{label:"service error",permalink:"/references/tags/service-error"},{label:"systemctl",permalink:"/references/tags/systemctl"},{label:"systemd",permalink:"/references/tags/systemd"}],version:"current",lastUpdatedAt:1694784773,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Shutting down persistance",slug:"shutting-down-persistance",hide_title:!0,tags:["reference","shutdown","frozen","idle","service error","systemctl","systemd"]},sidebar:"defaultSidebar",previous:{title:"Update CLI from source code",permalink:"/references/Lightning CLI/update-cli-from-source-code"},next:{title:"User service",permalink:"/references/Systemd/user-service"}},i={},u=[{value:"Systemd Service as frozen or idle",id:"systemd-service-as-frozen-or-idle",level:2}],d={toc:u},p="wrapper";function g(e){let{components:t,...n}=e;return(0,s.kt)(p,(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,s.kt)("h2",{id:"systemd-service-as-frozen-or-idle"},"Systemd Service as frozen or idle"),(0,s.kt)("p",null,"If you have a ",(0,s.kt)("inlineCode",{parentName:"p"},"Shutting node down")," message on the service log, the process is likely failing to respond to Systemd shut down command by failing to terminate all the child processes that were started by the service."),(0,s.kt)("p",null,"The logs should be similar to the following:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"2023-09-11 18:02:07 | ERROR | lightning_consensus::consensus - core/consensus/src/consensus.rs:371 - node: XsE9KtedDRUGv22MLHvy8qcc52QsWGWJYY1LBnWhglg=\n2023-09-11 18:02:07 | ERROR | lightning_consensus::consensus - core/consensus/src/consensus.rs:371 - node: zBmZaycvQsdFRfe0p5Rig/KgyYPD4yNKQTPDo7JrugM=\n2023-09-11 18:02:07 | WARN | lightning_consensus::consensus - core/consensus/src/consensus.rs:373 - ##################\n2023-09-11 18:02:07 | WARN | lightning_consensus::consensus - core/consensus/src/consensus.rs:374 - ********************************\nRPC server starting up\nlistening on 0.0.0.0:4069\nShutting node down.\nShutting node down.\nShutting node down.\nShutting node down.\nShutting node down.\n")),(0,s.kt)("p",null,"To resolve this issue, start by executing a new ",(0,s.kt)("inlineCode",{parentName:"p"},"shutdown")," command as follows:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl stop lightning\n")),(0,s.kt)("p",null,"If you need to delegate to root, then use the ",(0,s.kt)("strong",{parentName:"p"},"sudo")," keyword, as follows:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl stop lightning\n")),(0,s.kt)("p",null,"Once completed, clear the logs to avoid confusion as the log aggregates messages past and current."),(0,s.kt)("p",null,"Delete all the log files (output.log and diagnostic.log) by running:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"sudo rm -f /var/log/lightning/*.log\n")),(0,s.kt)("p",null,"Launch the service:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl start lightning\n")),(0,s.kt)("p",null,"If you need to delegate to root, then use the ",(0,s.kt)("strong",{parentName:"p"},"sudo")," keyword, as follows:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl start lightning\n")),(0,s.kt)("p",null,"You can watch the log output of the service by running:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"tail -f /var/log/lightning/output.log\n")),(0,s.kt)("p",null,"The output should be similar to:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"2023-09-12 13:53:51 | WARN | lightning_consensus::consensus - core/consensus/src/consensus.rs:373 - ##################\n2023-09-12 13:53:51 | WARN | lightning_consensus::consensus - core/consensus/src/consensus.rs:374 - ********************************\n")),(0,s.kt)("p",null,"Alternatively, you can watch the diagnostic.log"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"tail -f /var/log/lightning/diagnostic.log\n")),(0,s.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}g.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>s});var r=n(7294);const s=e=>{let{image:t,name:n,title:s,url:a,communityMember:o=!1}=e;return r.createElement("section",{className:"author_card"},r.createElement("div",null,r.createElement("span",{className:"avatar"},r.createElement("a",{href:a,target:"_blank",alt:n},r.createElement("img",{src:t,alt:n}))),r.createElement("div",null,r.createElement("span",{className:"name"},r.createElement("a",{href:a,target:"_blank",alt:n},n)),r.createElement("span",{className:"title"},s),r.createElement("span",{className:"discord"},o?"Join our community on":"Got questions? Find us on"," ",r.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[2517],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>m});var r=n(7294);function s(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function o(e){for(var t=1;t=0||(s[n]=e[n]);return s}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(s[n]=e[n])}return s}var c=r.createContext({}),i=function(e){var t=r.useContext(c),n=t;return e&&(n="function"==typeof e?e(t):o(o({},t),e)),n},u=function(e){var t=i(e.components);return r.createElement(c.Provider,{value:t},e.children)},d="mdxType",p={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},g=r.forwardRef((function(e,t){var n=e.components,s=e.mdxType,a=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),d=i(n),g=s,m=d["".concat(c,".").concat(g)]||d[g]||p[g]||a;return n?r.createElement(m,o(o({ref:t},u),{},{components:n})):r.createElement(m,o({ref:t},u))}));function m(e,t){var n=arguments,s=t&&t.mdxType;if("string"==typeof e||s){var a=n.length,o=new Array(a);o[0]=g;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[d]="string"==typeof e?e:s,o[1]=l;for(var i=2;i{n.r(t),n.d(t,{assets:()=>i,contentTitle:()=>l,default:()=>g,frontMatter:()=>o,metadata:()=>c,toc:()=>u});var r=n(7462),s=(n(7294),n(3905)),a=n(3872);const o={title:"Shutting down persistance",slug:"shutting-down-persistance",hide_title:!0,tags:["reference","shutdown","frozen","idle","service error","systemctl","systemd"]},l=void 0,c={unversionedId:"Systemd/shutting-down-persistance",id:"Systemd/shutting-down-persistance",title:"Shutting down persistance",description:"Systemd Service as frozen or idle",source:"@site/references/Systemd/shutting-down-persistance.md",sourceDirName:"Systemd",slug:"/Systemd/shutting-down-persistance",permalink:"/references/Systemd/shutting-down-persistance",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Systemd/shutting-down-persistance.md",tags:[{label:"reference",permalink:"/references/tags/reference"},{label:"shutdown",permalink:"/references/tags/shutdown"},{label:"frozen",permalink:"/references/tags/frozen"},{label:"idle",permalink:"/references/tags/idle"},{label:"service error",permalink:"/references/tags/service-error"},{label:"systemctl",permalink:"/references/tags/systemctl"},{label:"systemd",permalink:"/references/tags/systemd"}],version:"current",lastUpdatedAt:1694785242,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Shutting down persistance",slug:"shutting-down-persistance",hide_title:!0,tags:["reference","shutdown","frozen","idle","service error","systemctl","systemd"]},sidebar:"defaultSidebar",previous:{title:"Update CLI from source code",permalink:"/references/Lightning CLI/update-cli-from-source-code"},next:{title:"User service",permalink:"/references/Systemd/user-service"}},i={},u=[{value:"Systemd Service as frozen or idle",id:"systemd-service-as-frozen-or-idle",level:2}],d={toc:u},p="wrapper";function g(e){let{components:t,...n}=e;return(0,s.kt)(p,(0,r.Z)({},d,n,{components:t,mdxType:"MDXLayout"}),(0,s.kt)("h2",{id:"systemd-service-as-frozen-or-idle"},"Systemd Service as frozen or idle"),(0,s.kt)("p",null,"If you have a ",(0,s.kt)("inlineCode",{parentName:"p"},"Shutting node down")," message on the service log, the process is likely failing to respond to Systemd shut down command by failing to terminate all the child processes that were started by the service."),(0,s.kt)("p",null,"The logs should be similar to the following:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"2023-09-11 18:02:07 | ERROR | lightning_consensus::consensus - core/consensus/src/consensus.rs:371 - node: XsE9KtedDRUGv22MLHvy8qcc52QsWGWJYY1LBnWhglg=\n2023-09-11 18:02:07 | ERROR | lightning_consensus::consensus - core/consensus/src/consensus.rs:371 - node: zBmZaycvQsdFRfe0p5Rig/KgyYPD4yNKQTPDo7JrugM=\n2023-09-11 18:02:07 | WARN | lightning_consensus::consensus - core/consensus/src/consensus.rs:373 - ##################\n2023-09-11 18:02:07 | WARN | lightning_consensus::consensus - core/consensus/src/consensus.rs:374 - ********************************\nRPC server starting up\nlistening on 0.0.0.0:4069\nShutting node down.\nShutting node down.\nShutting node down.\nShutting node down.\nShutting node down.\n")),(0,s.kt)("p",null,"To resolve this issue, start by executing a new ",(0,s.kt)("inlineCode",{parentName:"p"},"shutdown")," command as follows:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl stop lightning\n")),(0,s.kt)("p",null,"If you need to delegate to root, then use the ",(0,s.kt)("strong",{parentName:"p"},"sudo")," keyword, as follows:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl stop lightning\n")),(0,s.kt)("p",null,"Once completed, clear the logs to avoid confusion as the log aggregates messages past and current."),(0,s.kt)("p",null,"Delete all the log files (output.log and diagnostic.log) by running:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"sudo rm -f /var/log/lightning/*.log\n")),(0,s.kt)("p",null,"Launch the service:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl start lightning\n")),(0,s.kt)("p",null,"If you need to delegate to root, then use the ",(0,s.kt)("strong",{parentName:"p"},"sudo")," keyword, as follows:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl start lightning\n")),(0,s.kt)("p",null,"You can watch the log output of the service by running:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"tail -f /var/log/lightning/output.log\n")),(0,s.kt)("p",null,"The output should be similar to:"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"2023-09-12 13:53:51 | WARN | lightning_consensus::consensus - core/consensus/src/consensus.rs:373 - ##################\n2023-09-12 13:53:51 | WARN | lightning_consensus::consensus - core/consensus/src/consensus.rs:374 - ********************************\n")),(0,s.kt)("p",null,"Alternatively, you can watch the diagnostic.log"),(0,s.kt)("pre",null,(0,s.kt)("code",{parentName:"pre",className:"language-sh"},"tail -f /var/log/lightning/diagnostic.log\n")),(0,s.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}g.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>s});var r=n(7294);const s=e=>{let{image:t,name:n,title:s,url:a,communityMember:o=!1}=e;return r.createElement("section",{className:"author_card"},r.createElement("div",null,r.createElement("span",{className:"avatar"},r.createElement("a",{href:a,target:"_blank",alt:n},r.createElement("img",{src:t,alt:n}))),r.createElement("div",null,r.createElement("span",{className:"name"},r.createElement("a",{href:a,target:"_blank",alt:n},n)),r.createElement("span",{className:"title"},s),r.createElement("span",{className:"discord"},o?"Join our community on":"Got questions? Find us on"," ",r.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file diff --git a/assets/js/b2f554cd.2a1afe50.js b/assets/js/b2f554cd.9709e83e.js similarity index 99% rename from assets/js/b2f554cd.2a1afe50.js rename to assets/js/b2f554cd.9709e83e.js index a4ebbcb93..81c2842ad 100644 --- a/assets/js/b2f554cd.2a1afe50.js +++ b/assets/js/b2f554cd.9709e83e.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[1477],{10:e=>{e.exports=JSON.parse('{"blogPosts":[{"id":"bloom-and-cuckoo-filters-for-cache-summarization","metadata":{"permalink":"/blog/bloom-and-cuckoo-filters-for-cache-summarization","source":"@site/blog/bloom-and-cuckoo-filters-for-cache-summarization.md","title":"Bloom Filters and Cuckoo Filters for Cache Summarization","description":"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.","date":"2023-09-15T13:32:53.000Z","formattedDate":"September 15, 2023","tags":[{"label":"fleek network","permalink":"/blog/tags/fleek-network"},{"label":"blog","permalink":"/blog/tags/blog"},{"label":"engineering","permalink":"/blog/tags/engineering"},{"label":"content routing","permalink":"/blog/tags/content-routing"}],"readingTime":10.355,"hasTruncateMarker":true,"authors":[{"name":"Matthias Wright","title":"Software Engineer","url":"https://github.com/matthias-wright","image_url":"https://github.com/matthias-wright.png","imageURL":"https://github.com/matthias-wright.png"}],"frontMatter":{"title":"Bloom Filters and Cuckoo Filters for Cache Summarization","description":"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.","slug":"bloom-and-cuckoo-filters-for-cache-summarization","image":"./assets/bloom-cuckoo/bloom.png?202301181528","authors":{"name":"Matthias Wright","title":"Software Engineer","url":"https://github.com/matthias-wright","image_url":"https://github.com/matthias-wright.png","imageURL":"https://github.com/matthias-wright.png"},"tags":["fleek network","blog","engineering","content routing"]}},"content":"Disclaimer: This is not a general comparison between Bloom filters and Cuckoo filters. This blog post summarizes some of the experiments we conducted to decide whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters, for a specific use case.\\n\\n\x3c!--truncate--\x3e\\n\\n## Background\\n\\nNodes on Fleek Network currently use Counting Bloom filters to summarize their cached content. These cache summaries are exchanged with other nodes in order to facilitate content routing.\\n\\nIf a particular node does not store a requested piece of content, it can use the Bloom filters that it received from its peers to check if a peer stores the requested content.\\n\\nWe are using Counting Bloom filters rather than regular Bloom filters because we need to be able to remove elements from the filter to support cache eviction.\\n\\n## Bloom Filters\\n\\nA Bloom filter is a space-efficient probabilistic data structure that can be used to perform approximate set membership queries.\\nThe answer to an approximate set membership query is not `no` or `yes,` but rather `no` or `probably.` This `probably` is quantified with the false positive rate. \\n\\nOne of the convenient features of Bloom filters is that they can be configured to have a specific false positive rate.\\nOf course, there is a tradeoff here; the lower the false positive rate, the larger the memory footprint. Bloom filters support two operations: `insert` and `contains.` \\n\\nA Bloom filter is represented by an array of m bits together with k independent hash functions. To insert an element into the filter, it is hashed with each of the k hash functions.\\nThe resulting hashes are interpreted as integers (modulo m) to obtain k array positions. The bits at these positions are then set to 1 (if there aren\'t already 1). \\nTo check whether or not an element is contained in the filter, the element is hashed k times with the different hash functions.\\n\\nIf all bits at the resulting array positions are 1, the element is assumed to be present. If any of the k bits are zero, we can be certain that the queried element is not present in the set.\\n\\nHowever, even if all bits are 1, it might still be the case that the bits were set by a combination of other elements. This is where the aforementioned false positive rate comes into play. \\n\\nSince we also need a `remove` operation for our use case, we have been using Counting Bloom filters, a variant of Bloom filters.\\nCounting Bloom filters retain most of the properties that regular Bloom filters have. The `remove` operation comes at the cost of an increased memory footprint.\\n\\nEach position in the array is no longer a single bit but a group of bits representing a counter.\\nWhenever an element is inserted into the filter, the counters for all k positions are incremented by 1. To remove an element, we decrement the counters.\\n\\n## Cuckoo Filters\\n\\nBloom filters are the most known members of a class of data structures called Approximate Membership Query Filters (AMQ Filters).\\nA relatively recent addition to this class is the Cuckoo filter [1]. Cuckoo filters share many similarities with Bloom filters, especially Counting Bloom filters.\\n\\nThey are space-efficient and can be used for approximate set membership queries. Cuckoo filters also support the operations `insert,` `contains,` and `remove,` and have configurable false positive rates. \\n\\nCuckoo filters are based on Cuckoo hash tables [2] and leverage an optimization called partial-key cuckoo hashing. A basic Cuckoo hash table consists of an array of buckets.\\nWe determine two candidate buckets for each element using two different hash functions, h1 and h2. \\n\\nThe `contains` operation will check if either bucket contains the element.\\nFor insertion, if either bucket is empty, the element will be inserted into the empty bucket.\\n\\nIf neither bucket is empty, one of the buckets is selected, and the existing element is removed and inserted into its alternate location.\\nThis may trigger another relocation if the alternate location is not empty. \\n\\nAlthough the insertion operation may perform a sequence of relocations, the amortized runtime is O(1). \\n\\nMost implementations of Cuckoo hash tables and, consequently, Cuckoo filters will use buckets that can hold multiple elements, as proposed in [3].\\n\\nFor Cuckoo filters, the hash table size is reduced by only storing fingerprints - a bit string calculated from an element\'s hash - rather than key-value pairs.\\n\\nThe fingerprint size is derived from the desired false positive rate. \\nA problem that arises is that, to relocate existing fingerprints using the Cuckoo hashing approach described above, we need the original hash from which the fingerprint was derived.\\n\\nOf course, we could store this hash somewhere, but the whole point of using fingerprints is to reduce the memory footprint of the filter.\\n\\nThe solution to this predicament is the aforementioned partial-key cuckoo hashing, a technique for determining an element\'s alternate location using only its fingerprint. \\nFor a given element x, the two candidate buckets are computed as follows: \\n\\n\\n\x3c!-- \\nTODO: Install math forms renderer, till then use img\\n\\n$h_1(x) = \\\\text{hash}(x)$\\n\\n$h_2(x) = h_1(x) \\\\oplus \\\\text{hash}(\\\\text{fingerprint}(x))$\\n--\x3e\\n\\n![](./assets/bloom-cuckoo/math-formul.png?202301181528)\\n\\nAn important property of this technique is that h1(x) can also be computed from h2(x) and the fingerprint.\\n\\n## Benchmarking\\n\\nAs this post mentioned, we are not aiming for a general comparison of Counting Bloom and Cuckoo filters.\\n\\nInstead, we want to determine which filter suits our specific use case better. The two main properties we are looking for are space efficiency and lookup performance. \\n\\nSpace efficiency is important because nodes frequently update their cache and have to communicate these changes with their peers. These messages should take up as little bandwidth as possible.\\n\\nLookup speed is also important because Fleek Network aims to serve user requests as quickly as possible. Checking whether a peer has some content stored in their cache summary should not be a bottleneck. \\n\\n## Experimental Setup\\n\\nWe are using our own Counting Bloom filter [implementation](https://github.com/fleek-network/ursa/blob/483f4d56cbaa5e83182454d2c1db6f6af7c54912/crates/ursa-network/src/utils/bloom_filter.rs#L11) and \\n[this](https://github.com/sile/scalable_cuckoo_filter) Cuckoo filter implementation in Rust (the [original](https://github.com/efficient/cuckoofilter) implementation is in C++). All experiments\\nwere performed on a Linux machine with 16 GB RAM and an Intel Core i7 (10th Gen). Whenever the experiment is probabilistic, we repeat the experiment 20 times and report the mean and standard deviation.\\n\\n## Memory Footprint\\n\\nFor both Counting Bloom filters and Cuckoo filters, the memory footprint is determined by two factors: the filter\'s capacity and the desired false positive rate. In the first experiment, we examine the impact that\\nthese factors have on the memory footprint. \\n\\nTo this end, we fix the false positive rate and initialize the filters with capacities ranging from 100K to 1M. The result is shown in Fig. 1. \\nThe size of Bloom filters scales linearly with the capacity. Cuckoo filters are more space-efficient. This result is consistent with the experiments reported in [1].\\n\\n![](./assets/bloom-cuckoo/capacity-size.png?202301121718)\\n\\n> Figure 1: We fix the false positive rate and initialize the filters with capacities ranging from 100K to 1M. The y-axis shows the size of the filters in Megabytes.\\n\\nNext, we fix the capacity and initialize the filters with false positive rates ranging from 0.0001 to 0.5. Fig. 2 shows that Cuckoo filters are more space-efficient.\\n\\nThe gap between Counting Bloom filters and Cuckoo filters grows as the false positive rate decreases. This is also consistent with experiments in [1].\\n\\n![](./assets/bloom-cuckoo/fp-rate-size.png?202301121718)\\n\\n> Figure 2: We fix the capacity and initialize the filters with false positive rates ranging from 0.0001 to 0.5. The y-axis shows the size of the filters in Megabytes.\\n\\n## Lookup Performance\\n\\nWe first add elements to both filters until the capacity is reached. We then measure the lookup performance for different ratios of positive and negative lookups.\\n\\nA positive lookup is for an existing element, and a negative lookup is for an element not contained in the filter. We perform 100K lookups for each ratio and report the average lookup duration and standard deviation. \\n\\nFig. 3 shows the results. Bloom filters perform slightly better on average than Cuckoo filters. This result is inconsistent with [1],\\nwhere Cuckoo filters were reported to have a better lookup performance than Bloom filters. It should be noted here that the authors in [1] use the original C++ Cuckoo filter implementation and their own unreleased Bloom filter implementation. In contrast, we use a Rust Cuckoo filter implementation and our Bloom filter implementation. We cannot easily determine the reason for this discrepancy.\\n\\nHowever, the performance difference is negligible.\\n\\n![](./assets/bloom-cuckoo/lookup.png?202301121718)\\n\\n> Figure 3: Lookup performance for different ratios of positive and negative lookups. For example, ratio 0.25 indicates that 25% of lookups are positive and 75% are negative.\\nThe shaded region indicates the standard deviation.\\n\\n## Insertion Performance\\n\\nLess critical than lookup performance but still important for our purposes is insertion performance. We measure how the insertion performance varies for different occupancy levels.\\nFig. 4 shows the results. The insertion performance is constant across all levels of occupancy for Bloom filters.\\n\\nFor Cuckoo filters, the performance decreases as the filter becomes fuller because more relocations are required. In Fig. 4, the performance for Bloom filters is not constant. It quickly increases and then remains constant. This can be explained by CPU caching. \\n\\n![](./assets/bloom-cuckoo/insert.png?202301121718)\\n\\n> Figure 4: Insertion performance for different occupancy levels. The shaded region indicates the standard deviation.\\n\\n## Capacity and Scaling\\n\\nWe have mentioned the capacity of a filter several times now. An interesting case is what happens when a filter\'s capacity is exceeded.\\nBloom filters and Cuckoo filters behave differently in this scenario.\\n\\nFor Bloom filters, the `insertion` operation always succeeds. However, the false positive rate will rapidly increase as we exceed the filter\'s capacity. While Bloom filters fail silently, Cuckoo filters are more explicit. Most implementations have a maximum number of\\nrelocations that will be performed for an insertion. The `insertion` operation will return an error if more relocations are required. \\n\\nFor both filters, we can avoid this problem by simply initializing the filter with a sufficiently large capacity. However, this will increase the memory footprint of the filter.\\n\\nFurthermore, it is difficult to predict how many elements a node on Fleek Network will cache. It is also likely that the number of cached elements will greatly vary for different nodes. \\n\\nFortunately, a variant of Bloom filters called Scalable Bloom Filters [4] can adapt dynamically to the number of elements stored while guaranteeing a maximum false positive rate.\\n\\nThe proposed technique is also applicable to Cuckoo filters.\\n\\n## Other Filters\\n\\nWhile we only looked at Bloom filters and Cuckoo filters, there are other AMQ filters that we want to mention here briefly:\\n\\n* Quotient filters [5, 6]: Compact hash tables that support insertion, lookup, and deletion. Less space-efficient than Bloom filters and Cuckoo filters. \\n\\n* XOR filters [7]: More space-efficient than Bloom filters and Cuckoo filters. However, they are static, meaning the filter has to be rebuilt if additional elements are added. \\n\\n## Conclusion\\n\\nWe examined whether Counting Bloom filters or Cuckoo filters are more suitable for summarizing caches on Fleek Network. Cuckoo filters are more space-efficient, especially for lower false positive rates. Bloom filters have a slightly better insertion and lookup performance for the implementations we tested.\\n\\nBoth filters can be adapted to grow and shrink in size dynamically. Since the difference in insertion and lookup performance is negligible while Cuckoo filters are significantly more space-efficient, we favor Cuckoo filters for our use case. \\n\\n### References\\n\\n[1] Bin Fan, Dave G. Andersen, Michael Kaminsky, and Michael D. Mitzenmacher. Cuckoo Filter: Practically Better Than Bloom.\\nIn Proceedings of the 10th ACM International Conference on emerging Networking Experiments and Technologies (CoNEXT 14). Association for Computing Machinery, New York, NY, USA, pp. 75-88, 2014. \\n\\n[2] Rasmus Pagha and Flemming Friche Rodler. Cuckoo hashing. Journal of Algorithms, 51(2), pp. 122-144, 2004. \\n\\n[3] Martin Dietzfelbinger and Christoph Weidling. Balanced Allocation and Dictionaries with Tightly Packed Constant Size Bins. Theoretical Computer Science, 380(1), pp. 47-68, 2007. \\n\\n[4] Paulo S. Almeida, Carlos Baquero, Nuno Pregui\xe7a, and David Hutchison. Scalable Bloom Filters. Information Processing Letters, 101(6), pp. 255-261, 2007. \\n\\n[5] John G. Cleary. Compact hash tables using bidirectional linear probing. IEEE Transactions on Computers. 33(9), pp. 828-834, 1984. \\n\\n[6] Anna Pagh, Rasmus Pagh, and S. Srinivasa Rao. An optimal Bloom filter replacement. Proceedings of the Sixteenth Annual ACM-SIAM Symposium on Discrete Algorithms, pp. 823-829, 2005. \\n \\n[7] Thomas Mueller Graf and Daniel Lemire. Xor Filters: Faster and Smaller Than Bloom and Cuckoo Filters. ACM Journal of Experimental Algorithmics. 25, pp. 1-16, 2020."}]}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[1477],{10:e=>{e.exports=JSON.parse('{"blogPosts":[{"id":"bloom-and-cuckoo-filters-for-cache-summarization","metadata":{"permalink":"/blog/bloom-and-cuckoo-filters-for-cache-summarization","source":"@site/blog/bloom-and-cuckoo-filters-for-cache-summarization.md","title":"Bloom Filters and Cuckoo Filters for Cache Summarization","description":"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.","date":"2023-09-15T13:40:42.000Z","formattedDate":"September 15, 2023","tags":[{"label":"fleek network","permalink":"/blog/tags/fleek-network"},{"label":"blog","permalink":"/blog/tags/blog"},{"label":"engineering","permalink":"/blog/tags/engineering"},{"label":"content routing","permalink":"/blog/tags/content-routing"}],"readingTime":10.355,"hasTruncateMarker":true,"authors":[{"name":"Matthias Wright","title":"Software Engineer","url":"https://github.com/matthias-wright","image_url":"https://github.com/matthias-wright.png","imageURL":"https://github.com/matthias-wright.png"}],"frontMatter":{"title":"Bloom Filters and Cuckoo Filters for Cache Summarization","description":"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.","slug":"bloom-and-cuckoo-filters-for-cache-summarization","image":"./assets/bloom-cuckoo/bloom.png?202301181528","authors":{"name":"Matthias Wright","title":"Software Engineer","url":"https://github.com/matthias-wright","image_url":"https://github.com/matthias-wright.png","imageURL":"https://github.com/matthias-wright.png"},"tags":["fleek network","blog","engineering","content routing"]}},"content":"Disclaimer: This is not a general comparison between Bloom filters and Cuckoo filters. This blog post summarizes some of the experiments we conducted to decide whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters, for a specific use case.\\n\\n\x3c!--truncate--\x3e\\n\\n## Background\\n\\nNodes on Fleek Network currently use Counting Bloom filters to summarize their cached content. These cache summaries are exchanged with other nodes in order to facilitate content routing.\\n\\nIf a particular node does not store a requested piece of content, it can use the Bloom filters that it received from its peers to check if a peer stores the requested content.\\n\\nWe are using Counting Bloom filters rather than regular Bloom filters because we need to be able to remove elements from the filter to support cache eviction.\\n\\n## Bloom Filters\\n\\nA Bloom filter is a space-efficient probabilistic data structure that can be used to perform approximate set membership queries.\\nThe answer to an approximate set membership query is not `no` or `yes,` but rather `no` or `probably.` This `probably` is quantified with the false positive rate. \\n\\nOne of the convenient features of Bloom filters is that they can be configured to have a specific false positive rate.\\nOf course, there is a tradeoff here; the lower the false positive rate, the larger the memory footprint. Bloom filters support two operations: `insert` and `contains.` \\n\\nA Bloom filter is represented by an array of m bits together with k independent hash functions. To insert an element into the filter, it is hashed with each of the k hash functions.\\nThe resulting hashes are interpreted as integers (modulo m) to obtain k array positions. The bits at these positions are then set to 1 (if there aren\'t already 1). \\nTo check whether or not an element is contained in the filter, the element is hashed k times with the different hash functions.\\n\\nIf all bits at the resulting array positions are 1, the element is assumed to be present. If any of the k bits are zero, we can be certain that the queried element is not present in the set.\\n\\nHowever, even if all bits are 1, it might still be the case that the bits were set by a combination of other elements. This is where the aforementioned false positive rate comes into play. \\n\\nSince we also need a `remove` operation for our use case, we have been using Counting Bloom filters, a variant of Bloom filters.\\nCounting Bloom filters retain most of the properties that regular Bloom filters have. The `remove` operation comes at the cost of an increased memory footprint.\\n\\nEach position in the array is no longer a single bit but a group of bits representing a counter.\\nWhenever an element is inserted into the filter, the counters for all k positions are incremented by 1. To remove an element, we decrement the counters.\\n\\n## Cuckoo Filters\\n\\nBloom filters are the most known members of a class of data structures called Approximate Membership Query Filters (AMQ Filters).\\nA relatively recent addition to this class is the Cuckoo filter [1]. Cuckoo filters share many similarities with Bloom filters, especially Counting Bloom filters.\\n\\nThey are space-efficient and can be used for approximate set membership queries. Cuckoo filters also support the operations `insert,` `contains,` and `remove,` and have configurable false positive rates. \\n\\nCuckoo filters are based on Cuckoo hash tables [2] and leverage an optimization called partial-key cuckoo hashing. A basic Cuckoo hash table consists of an array of buckets.\\nWe determine two candidate buckets for each element using two different hash functions, h1 and h2. \\n\\nThe `contains` operation will check if either bucket contains the element.\\nFor insertion, if either bucket is empty, the element will be inserted into the empty bucket.\\n\\nIf neither bucket is empty, one of the buckets is selected, and the existing element is removed and inserted into its alternate location.\\nThis may trigger another relocation if the alternate location is not empty. \\n\\nAlthough the insertion operation may perform a sequence of relocations, the amortized runtime is O(1). \\n\\nMost implementations of Cuckoo hash tables and, consequently, Cuckoo filters will use buckets that can hold multiple elements, as proposed in [3].\\n\\nFor Cuckoo filters, the hash table size is reduced by only storing fingerprints - a bit string calculated from an element\'s hash - rather than key-value pairs.\\n\\nThe fingerprint size is derived from the desired false positive rate. \\nA problem that arises is that, to relocate existing fingerprints using the Cuckoo hashing approach described above, we need the original hash from which the fingerprint was derived.\\n\\nOf course, we could store this hash somewhere, but the whole point of using fingerprints is to reduce the memory footprint of the filter.\\n\\nThe solution to this predicament is the aforementioned partial-key cuckoo hashing, a technique for determining an element\'s alternate location using only its fingerprint. \\nFor a given element x, the two candidate buckets are computed as follows: \\n\\n\\n\x3c!-- \\nTODO: Install math forms renderer, till then use img\\n\\n$h_1(x) = \\\\text{hash}(x)$\\n\\n$h_2(x) = h_1(x) \\\\oplus \\\\text{hash}(\\\\text{fingerprint}(x))$\\n--\x3e\\n\\n![](./assets/bloom-cuckoo/math-formul.png?202301181528)\\n\\nAn important property of this technique is that h1(x) can also be computed from h2(x) and the fingerprint.\\n\\n## Benchmarking\\n\\nAs this post mentioned, we are not aiming for a general comparison of Counting Bloom and Cuckoo filters.\\n\\nInstead, we want to determine which filter suits our specific use case better. The two main properties we are looking for are space efficiency and lookup performance. \\n\\nSpace efficiency is important because nodes frequently update their cache and have to communicate these changes with their peers. These messages should take up as little bandwidth as possible.\\n\\nLookup speed is also important because Fleek Network aims to serve user requests as quickly as possible. Checking whether a peer has some content stored in their cache summary should not be a bottleneck. \\n\\n## Experimental Setup\\n\\nWe are using our own Counting Bloom filter [implementation](https://github.com/fleek-network/ursa/blob/483f4d56cbaa5e83182454d2c1db6f6af7c54912/crates/ursa-network/src/utils/bloom_filter.rs#L11) and \\n[this](https://github.com/sile/scalable_cuckoo_filter) Cuckoo filter implementation in Rust (the [original](https://github.com/efficient/cuckoofilter) implementation is in C++). All experiments\\nwere performed on a Linux machine with 16 GB RAM and an Intel Core i7 (10th Gen). Whenever the experiment is probabilistic, we repeat the experiment 20 times and report the mean and standard deviation.\\n\\n## Memory Footprint\\n\\nFor both Counting Bloom filters and Cuckoo filters, the memory footprint is determined by two factors: the filter\'s capacity and the desired false positive rate. In the first experiment, we examine the impact that\\nthese factors have on the memory footprint. \\n\\nTo this end, we fix the false positive rate and initialize the filters with capacities ranging from 100K to 1M. The result is shown in Fig. 1. \\nThe size of Bloom filters scales linearly with the capacity. Cuckoo filters are more space-efficient. This result is consistent with the experiments reported in [1].\\n\\n![](./assets/bloom-cuckoo/capacity-size.png?202301121718)\\n\\n> Figure 1: We fix the false positive rate and initialize the filters with capacities ranging from 100K to 1M. The y-axis shows the size of the filters in Megabytes.\\n\\nNext, we fix the capacity and initialize the filters with false positive rates ranging from 0.0001 to 0.5. Fig. 2 shows that Cuckoo filters are more space-efficient.\\n\\nThe gap between Counting Bloom filters and Cuckoo filters grows as the false positive rate decreases. This is also consistent with experiments in [1].\\n\\n![](./assets/bloom-cuckoo/fp-rate-size.png?202301121718)\\n\\n> Figure 2: We fix the capacity and initialize the filters with false positive rates ranging from 0.0001 to 0.5. The y-axis shows the size of the filters in Megabytes.\\n\\n## Lookup Performance\\n\\nWe first add elements to both filters until the capacity is reached. We then measure the lookup performance for different ratios of positive and negative lookups.\\n\\nA positive lookup is for an existing element, and a negative lookup is for an element not contained in the filter. We perform 100K lookups for each ratio and report the average lookup duration and standard deviation. \\n\\nFig. 3 shows the results. Bloom filters perform slightly better on average than Cuckoo filters. This result is inconsistent with [1],\\nwhere Cuckoo filters were reported to have a better lookup performance than Bloom filters. It should be noted here that the authors in [1] use the original C++ Cuckoo filter implementation and their own unreleased Bloom filter implementation. In contrast, we use a Rust Cuckoo filter implementation and our Bloom filter implementation. We cannot easily determine the reason for this discrepancy.\\n\\nHowever, the performance difference is negligible.\\n\\n![](./assets/bloom-cuckoo/lookup.png?202301121718)\\n\\n> Figure 3: Lookup performance for different ratios of positive and negative lookups. For example, ratio 0.25 indicates that 25% of lookups are positive and 75% are negative.\\nThe shaded region indicates the standard deviation.\\n\\n## Insertion Performance\\n\\nLess critical than lookup performance but still important for our purposes is insertion performance. We measure how the insertion performance varies for different occupancy levels.\\nFig. 4 shows the results. The insertion performance is constant across all levels of occupancy for Bloom filters.\\n\\nFor Cuckoo filters, the performance decreases as the filter becomes fuller because more relocations are required. In Fig. 4, the performance for Bloom filters is not constant. It quickly increases and then remains constant. This can be explained by CPU caching. \\n\\n![](./assets/bloom-cuckoo/insert.png?202301121718)\\n\\n> Figure 4: Insertion performance for different occupancy levels. The shaded region indicates the standard deviation.\\n\\n## Capacity and Scaling\\n\\nWe have mentioned the capacity of a filter several times now. An interesting case is what happens when a filter\'s capacity is exceeded.\\nBloom filters and Cuckoo filters behave differently in this scenario.\\n\\nFor Bloom filters, the `insertion` operation always succeeds. However, the false positive rate will rapidly increase as we exceed the filter\'s capacity. While Bloom filters fail silently, Cuckoo filters are more explicit. Most implementations have a maximum number of\\nrelocations that will be performed for an insertion. The `insertion` operation will return an error if more relocations are required. \\n\\nFor both filters, we can avoid this problem by simply initializing the filter with a sufficiently large capacity. However, this will increase the memory footprint of the filter.\\n\\nFurthermore, it is difficult to predict how many elements a node on Fleek Network will cache. It is also likely that the number of cached elements will greatly vary for different nodes. \\n\\nFortunately, a variant of Bloom filters called Scalable Bloom Filters [4] can adapt dynamically to the number of elements stored while guaranteeing a maximum false positive rate.\\n\\nThe proposed technique is also applicable to Cuckoo filters.\\n\\n## Other Filters\\n\\nWhile we only looked at Bloom filters and Cuckoo filters, there are other AMQ filters that we want to mention here briefly:\\n\\n* Quotient filters [5, 6]: Compact hash tables that support insertion, lookup, and deletion. Less space-efficient than Bloom filters and Cuckoo filters. \\n\\n* XOR filters [7]: More space-efficient than Bloom filters and Cuckoo filters. However, they are static, meaning the filter has to be rebuilt if additional elements are added. \\n\\n## Conclusion\\n\\nWe examined whether Counting Bloom filters or Cuckoo filters are more suitable for summarizing caches on Fleek Network. Cuckoo filters are more space-efficient, especially for lower false positive rates. Bloom filters have a slightly better insertion and lookup performance for the implementations we tested.\\n\\nBoth filters can be adapted to grow and shrink in size dynamically. Since the difference in insertion and lookup performance is negligible while Cuckoo filters are significantly more space-efficient, we favor Cuckoo filters for our use case. \\n\\n### References\\n\\n[1] Bin Fan, Dave G. Andersen, Michael Kaminsky, and Michael D. Mitzenmacher. Cuckoo Filter: Practically Better Than Bloom.\\nIn Proceedings of the 10th ACM International Conference on emerging Networking Experiments and Technologies (CoNEXT 14). Association for Computing Machinery, New York, NY, USA, pp. 75-88, 2014. \\n\\n[2] Rasmus Pagha and Flemming Friche Rodler. Cuckoo hashing. Journal of Algorithms, 51(2), pp. 122-144, 2004. \\n\\n[3] Martin Dietzfelbinger and Christoph Weidling. Balanced Allocation and Dictionaries with Tightly Packed Constant Size Bins. Theoretical Computer Science, 380(1), pp. 47-68, 2007. \\n\\n[4] Paulo S. Almeida, Carlos Baquero, Nuno Pregui\xe7a, and David Hutchison. Scalable Bloom Filters. Information Processing Letters, 101(6), pp. 255-261, 2007. \\n\\n[5] John G. Cleary. Compact hash tables using bidirectional linear probing. IEEE Transactions on Computers. 33(9), pp. 828-834, 1984. \\n\\n[6] Anna Pagh, Rasmus Pagh, and S. Srinivasa Rao. An optimal Bloom filter replacement. Proceedings of the Sixteenth Annual ACM-SIAM Symposium on Discrete Algorithms, pp. 823-829, 2005. \\n \\n[7] Thomas Mueller Graf and Daniel Lemire. Xor Filters: Faster and Smaller Than Bloom and Cuckoo Filters. ACM Journal of Experimental Algorithmics. 25, pp. 1-16, 2020."}]}')}}]); \ No newline at end of file diff --git a/assets/js/b35f1b7f.a7607421.js b/assets/js/b35f1b7f.d88ea614.js similarity index 99% rename from assets/js/b35f1b7f.a7607421.js rename to assets/js/b35f1b7f.d88ea614.js index 5839dce44..8e30fd214 100644 --- a/assets/js/b35f1b7f.a7607421.js +++ b/assets/js/b35f1b7f.d88ea614.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[7706],{3905:(e,t,r)=>{r.d(t,{Zo:()=>c,kt:()=>h});var s=r(7294);function n(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);t&&(s=s.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,s)}return r}function l(e){for(var t=1;t=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(s=0;s=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var o=s.createContext({}),u=function(e){var t=s.useContext(o),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},c=function(e){var t=u(e.components);return s.createElement(o.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return s.createElement(s.Fragment,{},t)}},d=s.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,o=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),p=u(r),d=n,h=p["".concat(o,".").concat(d)]||p[d]||m[d]||a;return r?s.createElement(h,l(l({ref:t},c),{},{components:r})):s.createElement(h,l({ref:t},c))}));function h(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,l=new Array(a);l[0]=d;var i={};for(var o in t)hasOwnProperty.call(t,o)&&(i[o]=t[o]);i.originalType=e,i[p]="string"==typeof e?e:n,l[1]=i;for(var u=2;u{r.r(t),r.d(t,{assets:()=>u,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var s=r(7462),n=(r(7294),r(3905)),a=r(3872);const l={title:"User service",slug:"user-service",hide_title:!0,tags:["references","help","user service","unit","systemctl","systemd"]},i=void 0,o={unversionedId:"Systemd/user-service",id:"Systemd/user-service",title:"User service",description:"A user should have the ability to run a Systemd user service unit without having to use sudo to control it.",source:"@site/references/Systemd/user-service.md",sourceDirName:"Systemd",slug:"/Systemd/user-service",permalink:"/references/Systemd/user-service",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Systemd/user-service.md",tags:[{label:"references",permalink:"/references/tags/references"},{label:"help",permalink:"/references/tags/help"},{label:"user service",permalink:"/references/tags/user-service"},{label:"unit",permalink:"/references/tags/unit"},{label:"systemctl",permalink:"/references/tags/systemctl"},{label:"systemd",permalink:"/references/tags/systemd"}],version:"current",lastUpdatedAt:1694784773,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"User service",slug:"user-service",hide_title:!0,tags:["references","help","user service","unit","systemctl","systemd"]},sidebar:"defaultSidebar",previous:{title:"Shutting down persistance",permalink:"/references/Systemd/shutting-down-persistance"}},u={},c=[{value:"Check --user support",id:"check---user-support",level:2},{value:"Put the service unit in the user service",id:"put-the-service-unit-in-the-user-service",level:2},{value:"Systemd service control as --user",id:"systemd-service-control-as---user",level:2},{value:"Problem statement",id:"problem-statement",level:2}],p={toc:c},m="wrapper";function d(e){let{components:t,...r}=e;return(0,n.kt)(m,(0,s.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("p",null,"A user should have the ability to run a Systemd user service unit without having to use ",(0,n.kt)("inlineCode",{parentName:"p"},"sudo")," to control it."),(0,n.kt)("h2",{id:"check---user-support"},"Check ",(0,n.kt)("inlineCode",{parentName:"h2"},"--user")," support"),(0,n.kt)("p",null,"Use the ",(0,n.kt)("inlineCode",{parentName:"p"},"--user")," flag when getting the list of unit files."),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user list-unit-files\n")),(0,n.kt)("p",null,"It should return a list of unit files."),(0,n.kt)("h2",{id:"put-the-service-unit-in-the-user-service"},"Put the service unit in the user service"),(0,n.kt)("p",null,"Create the Systemd user units directory:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"sudo mkdir -p /etc/systemd/system/user\n")),(0,n.kt)("p",null,"Move the ",(0,n.kt)("inlineCode",{parentName:"p"},"lightning.service")," to the system user unit service directory:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"mv /etc/systemd/system/lightning.service /etc/systemd/system/user/lightning.service\n")),(0,n.kt)("p",null,"Check the ",(0,n.kt)("strong",{parentName:"p"},"Load path when running in user mode (--user)")," in ",(0,n.kt)("a",{parentName:"p",href:"https://www.freedesktop.org/software/systemd/man/systemd.unit.html"},"Systemd unit")," for other alternative user paths, or to understand how it works to customize your server accordingly."),(0,n.kt)("p",null,"##\xa0Reload daemon"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl daemon-reload\n")),(0,n.kt)("h2",{id:"systemd-service-control-as---user"},"Systemd service control as ",(0,n.kt)("inlineCode",{parentName:"h2"},"--user")),(0,n.kt)("p",null,"Reload the Systemctl daemon by executing the command:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user daemon-reload\n")),(0,n.kt)("p",null,"Enable the service for starting up on system boot:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user enable lightning.service\n")),(0,n.kt)("p",null,"Start the service by:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user start lightning\n")),(0,n.kt)("p",null,"Stop the service by:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user stop lightning\n")),(0,n.kt)("p",null,"Restart the service by:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user restart lightning\n")),(0,n.kt)("p",null,"Check the service status by:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user status lightning.service\n")),(0,n.kt)("h2",{id:"problem-statement"},"Problem statement"),(0,n.kt)("p",null,"On tests done in a DigitalOcean Ubuntu 22.x, we had setup user-level services which were operated with ",(0,n.kt)("inlineCode",{parentName:"p"},"--user"),". When the commands were executed as ",(0,n.kt)("inlineCode",{parentName:"p"},"--user")," it failed with:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"Failed to connect to bus: Operation not permitted (consider using --machine=@.host --user to connect to bus of other user)\n")),(0,n.kt)("p",null,"The user should be able to operate as user, it shouldn't be required to connect on behalf of other users. This means that even for a simple command, such as to retrieve the list of unit files:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user list-unit-files\n")),(0,n.kt)("p",null,"We'd get the error:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"Failed to connect to bus: Operation not permitted (consider using --machine=@.host --user to connect to bus of other user)\n")),(0,n.kt)("p",null,"For any of the supported user unit locations e.g. $HOME/.config/systemd/user as documented in ",(0,n.kt)("a",{parentName:"p",href:"https://www.freedesktop.org/software/systemd/man/systemd.unit.html"},"Systemd unit documentation"),", the result is the error above."),(0,n.kt)("p",null,"This is related to the load paths when running in user mode (--user), as described in the discussion ",(0,n.kt)("a",{parentName:"p",href:"https://unix.stackexchange.com/questions/224992/where-do-i-put-my-systemd-unit-file/367237#367237"},"here"),"."),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"User-dependent")),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"$XDG_CONFIG_HOME/systemd/user")," User configuration (only used when $XDG_CONFIG_HOME is set)"),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"$HOME/.config/systemd/user")," User configuration (only used when $XDG_CONFIG_HOME is not set)"),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"$XDG_RUNTIME_DIR/systemd/user")," Runtime units (only used when $XDG_RUNTIME_DIR is set)"),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"$XDG_DATA_HOME/systemd/user")," Units of packages that have been installed in the home directory (only used when $XDG_DATA_HOME is set)"),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"$HOME/.local/share/systemd/user")," Units of packages that have been installed in the home directory (only used when $XDG_DATA_HOME is not set)"),(0,n.kt)("p",null,"For example, if we check the ",(0,n.kt)("inlineCode",{parentName:"p"},"$XDG_RUNTIME_DIR")," in a DigitalOcean box, we get the following output:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"/run/user/0\n")),(0,n.kt)("p",null,"For this reason and to provide support for a wider audience of users and systems, we've stuck to sudo to execute the service, but this should not be a requirement and is not recommended."),(0,n.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}d.isMDXComponent=!0},3872:(e,t,r)=>{r.d(t,{Z:()=>n});var s=r(7294);const n=e=>{let{image:t,name:r,title:n,url:a,communityMember:l=!1}=e;return s.createElement("section",{className:"author_card"},s.createElement("div",null,s.createElement("span",{className:"avatar"},s.createElement("a",{href:a,target:"_blank",alt:r},s.createElement("img",{src:t,alt:r}))),s.createElement("div",null,s.createElement("span",{className:"name"},s.createElement("a",{href:a,target:"_blank",alt:r},r)),s.createElement("span",{className:"title"},n),s.createElement("span",{className:"discord"},l?"Join our community on":"Got questions? Find us on"," ",s.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[7706],{3905:(e,t,r)=>{r.d(t,{Zo:()=>c,kt:()=>h});var s=r(7294);function n(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);t&&(s=s.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,s)}return r}function l(e){for(var t=1;t=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(s=0;s=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var o=s.createContext({}),u=function(e){var t=s.useContext(o),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},c=function(e){var t=u(e.components);return s.createElement(o.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return s.createElement(s.Fragment,{},t)}},d=s.forwardRef((function(e,t){var r=e.components,n=e.mdxType,a=e.originalType,o=e.parentName,c=i(e,["components","mdxType","originalType","parentName"]),p=u(r),d=n,h=p["".concat(o,".").concat(d)]||p[d]||m[d]||a;return r?s.createElement(h,l(l({ref:t},c),{},{components:r})):s.createElement(h,l({ref:t},c))}));function h(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var a=r.length,l=new Array(a);l[0]=d;var i={};for(var o in t)hasOwnProperty.call(t,o)&&(i[o]=t[o]);i.originalType=e,i[p]="string"==typeof e?e:n,l[1]=i;for(var u=2;u{r.r(t),r.d(t,{assets:()=>u,contentTitle:()=>i,default:()=>d,frontMatter:()=>l,metadata:()=>o,toc:()=>c});var s=r(7462),n=(r(7294),r(3905)),a=r(3872);const l={title:"User service",slug:"user-service",hide_title:!0,tags:["references","help","user service","unit","systemctl","systemd"]},i=void 0,o={unversionedId:"Systemd/user-service",id:"Systemd/user-service",title:"User service",description:"A user should have the ability to run a Systemd user service unit without having to use sudo to control it.",source:"@site/references/Systemd/user-service.md",sourceDirName:"Systemd",slug:"/Systemd/user-service",permalink:"/references/Systemd/user-service",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Systemd/user-service.md",tags:[{label:"references",permalink:"/references/tags/references"},{label:"help",permalink:"/references/tags/help"},{label:"user service",permalink:"/references/tags/user-service"},{label:"unit",permalink:"/references/tags/unit"},{label:"systemctl",permalink:"/references/tags/systemctl"},{label:"systemd",permalink:"/references/tags/systemd"}],version:"current",lastUpdatedAt:1694785242,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"User service",slug:"user-service",hide_title:!0,tags:["references","help","user service","unit","systemctl","systemd"]},sidebar:"defaultSidebar",previous:{title:"Shutting down persistance",permalink:"/references/Systemd/shutting-down-persistance"}},u={},c=[{value:"Check --user support",id:"check---user-support",level:2},{value:"Put the service unit in the user service",id:"put-the-service-unit-in-the-user-service",level:2},{value:"Systemd service control as --user",id:"systemd-service-control-as---user",level:2},{value:"Problem statement",id:"problem-statement",level:2}],p={toc:c},m="wrapper";function d(e){let{components:t,...r}=e;return(0,n.kt)(m,(0,s.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("p",null,"A user should have the ability to run a Systemd user service unit without having to use ",(0,n.kt)("inlineCode",{parentName:"p"},"sudo")," to control it."),(0,n.kt)("h2",{id:"check---user-support"},"Check ",(0,n.kt)("inlineCode",{parentName:"h2"},"--user")," support"),(0,n.kt)("p",null,"Use the ",(0,n.kt)("inlineCode",{parentName:"p"},"--user")," flag when getting the list of unit files."),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user list-unit-files\n")),(0,n.kt)("p",null,"It should return a list of unit files."),(0,n.kt)("h2",{id:"put-the-service-unit-in-the-user-service"},"Put the service unit in the user service"),(0,n.kt)("p",null,"Create the Systemd user units directory:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"sudo mkdir -p /etc/systemd/system/user\n")),(0,n.kt)("p",null,"Move the ",(0,n.kt)("inlineCode",{parentName:"p"},"lightning.service")," to the system user unit service directory:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"mv /etc/systemd/system/lightning.service /etc/systemd/system/user/lightning.service\n")),(0,n.kt)("p",null,"Check the ",(0,n.kt)("strong",{parentName:"p"},"Load path when running in user mode (--user)")," in ",(0,n.kt)("a",{parentName:"p",href:"https://www.freedesktop.org/software/systemd/man/systemd.unit.html"},"Systemd unit")," for other alternative user paths, or to understand how it works to customize your server accordingly."),(0,n.kt)("p",null,"##\xa0Reload daemon"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl daemon-reload\n")),(0,n.kt)("h2",{id:"systemd-service-control-as---user"},"Systemd service control as ",(0,n.kt)("inlineCode",{parentName:"h2"},"--user")),(0,n.kt)("p",null,"Reload the Systemctl daemon by executing the command:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user daemon-reload\n")),(0,n.kt)("p",null,"Enable the service for starting up on system boot:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user enable lightning.service\n")),(0,n.kt)("p",null,"Start the service by:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user start lightning\n")),(0,n.kt)("p",null,"Stop the service by:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user stop lightning\n")),(0,n.kt)("p",null,"Restart the service by:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user restart lightning\n")),(0,n.kt)("p",null,"Check the service status by:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user status lightning.service\n")),(0,n.kt)("h2",{id:"problem-statement"},"Problem statement"),(0,n.kt)("p",null,"On tests done in a DigitalOcean Ubuntu 22.x, we had setup user-level services which were operated with ",(0,n.kt)("inlineCode",{parentName:"p"},"--user"),". When the commands were executed as ",(0,n.kt)("inlineCode",{parentName:"p"},"--user")," it failed with:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"Failed to connect to bus: Operation not permitted (consider using --machine=@.host --user to connect to bus of other user)\n")),(0,n.kt)("p",null,"The user should be able to operate as user, it shouldn't be required to connect on behalf of other users. This means that even for a simple command, such as to retrieve the list of unit files:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"systemctl --user list-unit-files\n")),(0,n.kt)("p",null,"We'd get the error:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"Failed to connect to bus: Operation not permitted (consider using --machine=@.host --user to connect to bus of other user)\n")),(0,n.kt)("p",null,"For any of the supported user unit locations e.g. $HOME/.config/systemd/user as documented in ",(0,n.kt)("a",{parentName:"p",href:"https://www.freedesktop.org/software/systemd/man/systemd.unit.html"},"Systemd unit documentation"),", the result is the error above."),(0,n.kt)("p",null,"This is related to the load paths when running in user mode (--user), as described in the discussion ",(0,n.kt)("a",{parentName:"p",href:"https://unix.stackexchange.com/questions/224992/where-do-i-put-my-systemd-unit-file/367237#367237"},"here"),"."),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"User-dependent")),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"$XDG_CONFIG_HOME/systemd/user")," User configuration (only used when $XDG_CONFIG_HOME is set)"),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"$HOME/.config/systemd/user")," User configuration (only used when $XDG_CONFIG_HOME is not set)"),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"$XDG_RUNTIME_DIR/systemd/user")," Runtime units (only used when $XDG_RUNTIME_DIR is set)"),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"$XDG_DATA_HOME/systemd/user")," Units of packages that have been installed in the home directory (only used when $XDG_DATA_HOME is set)"),(0,n.kt)("p",null,(0,n.kt)("strong",{parentName:"p"},"$HOME/.local/share/systemd/user")," Units of packages that have been installed in the home directory (only used when $XDG_DATA_HOME is not set)"),(0,n.kt)("p",null,"For example, if we check the ",(0,n.kt)("inlineCode",{parentName:"p"},"$XDG_RUNTIME_DIR")," in a DigitalOcean box, we get the following output:"),(0,n.kt)("pre",null,(0,n.kt)("code",{parentName:"pre",className:"language-sh"},"/run/user/0\n")),(0,n.kt)("p",null,"For this reason and to provide support for a wider audience of users and systems, we've stuck to sudo to execute the service, but this should not be a requirement and is not recommended."),(0,n.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}d.isMDXComponent=!0},3872:(e,t,r)=>{r.d(t,{Z:()=>n});var s=r(7294);const n=e=>{let{image:t,name:r,title:n,url:a,communityMember:l=!1}=e;return s.createElement("section",{className:"author_card"},s.createElement("div",null,s.createElement("span",{className:"avatar"},s.createElement("a",{href:a,target:"_blank",alt:r},s.createElement("img",{src:t,alt:r}))),s.createElement("div",null,s.createElement("span",{className:"name"},s.createElement("a",{href:a,target:"_blank",alt:r},r)),s.createElement("span",{className:"title"},n),s.createElement("span",{className:"discord"},l?"Join our community on":"Got questions? Find us on"," ",s.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file diff --git a/assets/js/d1b78a4d.20386ce8.js b/assets/js/d1b78a4d.67eb704a.js similarity index 98% rename from assets/js/d1b78a4d.20386ce8.js rename to assets/js/d1b78a4d.67eb704a.js index 2f749e24b..97d092768 100644 --- a/assets/js/d1b78a4d.20386ce8.js +++ b/assets/js/d1b78a4d.67eb704a.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[3023],{3905:(e,t,r)=>{r.d(t,{Zo:()=>m,kt:()=>f});var o=r(7294);function n(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,o)}return r}function a(e){for(var t=1;t=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var c=o.createContext({}),s=function(e){var t=o.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},m=function(e){var t=s(e.components);return o.createElement(c.Provider,{value:t},e.children)},u="mdxType",g={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},p=o.forwardRef((function(e,t){var r=e.components,n=e.mdxType,i=e.originalType,c=e.parentName,m=l(e,["components","mdxType","originalType","parentName"]),u=s(r),p=n,f=u["".concat(c,".").concat(p)]||u[p]||g[p]||i;return r?o.createElement(f,a(a({ref:t},m),{},{components:r})):o.createElement(f,a({ref:t},m))}));function f(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=r.length,a=new Array(i);a[0]=p;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[u]="string"==typeof e?e:n,a[1]=l;for(var s=2;s{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>g,frontMatter:()=>i,metadata:()=>l,toc:()=>s});var o=r(7462),n=(r(7294),r(3905));const i={title:"Bloom Filters and Cuckoo Filters for Cache Summarization",description:"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.",slug:"bloom-and-cuckoo-filters-for-cache-summarization",image:"./assets/bloom-cuckoo/bloom.png?202301181528",authors:{name:"Matthias Wright",title:"Software Engineer",url:"https://github.com/matthias-wright",image_url:"https://github.com/matthias-wright.png"},tags:["fleek network","blog","engineering","content routing"]},a=void 0,l={permalink:"/blog/bloom-and-cuckoo-filters-for-cache-summarization",source:"@site/blog/bloom-and-cuckoo-filters-for-cache-summarization.md",title:"Bloom Filters and Cuckoo Filters for Cache Summarization",description:"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.",date:"2023-09-15T13:32:53.000Z",formattedDate:"September 15, 2023",tags:[{label:"fleek network",permalink:"/blog/tags/fleek-network"},{label:"blog",permalink:"/blog/tags/blog"},{label:"engineering",permalink:"/blog/tags/engineering"},{label:"content routing",permalink:"/blog/tags/content-routing"}],readingTime:10.355,hasTruncateMarker:!0,authors:[{name:"Matthias Wright",title:"Software Engineer",url:"https://github.com/matthias-wright",image_url:"https://github.com/matthias-wright.png",imageURL:"https://github.com/matthias-wright.png"}],frontMatter:{title:"Bloom Filters and Cuckoo Filters for Cache Summarization",description:"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.",slug:"bloom-and-cuckoo-filters-for-cache-summarization",image:"./assets/bloom-cuckoo/bloom.png?202301181528",authors:{name:"Matthias Wright",title:"Software Engineer",url:"https://github.com/matthias-wright",image_url:"https://github.com/matthias-wright.png",imageURL:"https://github.com/matthias-wright.png"},tags:["fleek network","blog","engineering","content routing"]}},c={image:r(4221).Z,authorsImageUrls:[void 0]},s=[],m={toc:s},u="wrapper";function g(e){let{components:t,...r}=e;return(0,n.kt)(u,(0,o.Z)({},m,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("p",null,"Disclaimer: This is not a general comparison between Bloom filters and Cuckoo filters. This blog post summarizes some of the experiments we conducted to decide whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters, for a specific use case."))}g.isMDXComponent=!0},4221:(e,t,r)=>{r.d(t,{Z:()=>o});const o=r.p+"assets/images/bloom-79da0db687b4fb2060758838b9c44513.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[3023],{3905:(e,t,r)=>{r.d(t,{Zo:()=>m,kt:()=>f});var o=r(7294);function n(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);t&&(o=o.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,o)}return r}function a(e){for(var t=1;t=0||(n[r]=e[r]);return n}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(o=0;o=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(n[r]=e[r])}return n}var c=o.createContext({}),s=function(e){var t=o.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},m=function(e){var t=s(e.components);return o.createElement(c.Provider,{value:t},e.children)},u="mdxType",g={inlineCode:"code",wrapper:function(e){var t=e.children;return o.createElement(o.Fragment,{},t)}},p=o.forwardRef((function(e,t){var r=e.components,n=e.mdxType,i=e.originalType,c=e.parentName,m=l(e,["components","mdxType","originalType","parentName"]),u=s(r),p=n,f=u["".concat(c,".").concat(p)]||u[p]||g[p]||i;return r?o.createElement(f,a(a({ref:t},m),{},{components:r})):o.createElement(f,a({ref:t},m))}));function f(e,t){var r=arguments,n=t&&t.mdxType;if("string"==typeof e||n){var i=r.length,a=new Array(i);a[0]=p;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[u]="string"==typeof e?e:n,a[1]=l;for(var s=2;s{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>g,frontMatter:()=>i,metadata:()=>l,toc:()=>s});var o=r(7462),n=(r(7294),r(3905));const i={title:"Bloom Filters and Cuckoo Filters for Cache Summarization",description:"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.",slug:"bloom-and-cuckoo-filters-for-cache-summarization",image:"./assets/bloom-cuckoo/bloom.png?202301181528",authors:{name:"Matthias Wright",title:"Software Engineer",url:"https://github.com/matthias-wright",image_url:"https://github.com/matthias-wright.png"},tags:["fleek network","blog","engineering","content routing"]},a=void 0,l={permalink:"/blog/bloom-and-cuckoo-filters-for-cache-summarization",source:"@site/blog/bloom-and-cuckoo-filters-for-cache-summarization.md",title:"Bloom Filters and Cuckoo Filters for Cache Summarization",description:"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.",date:"2023-09-15T13:40:42.000Z",formattedDate:"September 15, 2023",tags:[{label:"fleek network",permalink:"/blog/tags/fleek-network"},{label:"blog",permalink:"/blog/tags/blog"},{label:"engineering",permalink:"/blog/tags/engineering"},{label:"content routing",permalink:"/blog/tags/content-routing"}],readingTime:10.355,hasTruncateMarker:!0,authors:[{name:"Matthias Wright",title:"Software Engineer",url:"https://github.com/matthias-wright",image_url:"https://github.com/matthias-wright.png",imageURL:"https://github.com/matthias-wright.png"}],frontMatter:{title:"Bloom Filters and Cuckoo Filters for Cache Summarization",description:"Summary of our experiment informing whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters.",slug:"bloom-and-cuckoo-filters-for-cache-summarization",image:"./assets/bloom-cuckoo/bloom.png?202301181528",authors:{name:"Matthias Wright",title:"Software Engineer",url:"https://github.com/matthias-wright",image_url:"https://github.com/matthias-wright.png",imageURL:"https://github.com/matthias-wright.png"},tags:["fleek network","blog","engineering","content routing"]}},c={image:r(4221).Z,authorsImageUrls:[void 0]},s=[],m={toc:s},u="wrapper";function g(e){let{components:t,...r}=e;return(0,n.kt)(u,(0,o.Z)({},m,r,{components:t,mdxType:"MDXLayout"}),(0,n.kt)("p",null,"Disclaimer: This is not a general comparison between Bloom filters and Cuckoo filters. This blog post summarizes some of the experiments we conducted to decide whether or not we should replace our implementation of Counting Bloom filters with Cuckoo filters, for a specific use case."))}g.isMDXComponent=!0},4221:(e,t,r)=>{r.d(t,{Z:()=>o});const o=r.p+"assets/images/bloom-79da0db687b4fb2060758838b9c44513.png"}}]); \ No newline at end of file diff --git a/assets/js/d7d81bf6.e5a40be3.js b/assets/js/d7d81bf6.eaf52dff.js similarity index 99% rename from assets/js/d7d81bf6.e5a40be3.js rename to assets/js/d7d81bf6.eaf52dff.js index 83ffda97f..d370a8001 100644 --- a/assets/js/d7d81bf6.e5a40be3.js +++ b/assets/js/d7d81bf6.eaf52dff.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[2918],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>g});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=c(e.components);return r.createElement(s.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,l=e.originalType,s=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),p=c(n),d=a,g=p["".concat(s,".").concat(d)]||p[d]||m[d]||l;return n?r.createElement(g,i(i({ref:t},u),{},{components:n})):r.createElement(g,i({ref:t},u))}));function g(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=n.length,i=new Array(l);i[0]=d;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o[p]="string"==typeof e?e:a,i[1]=o;for(var c=2;c{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>d,frontMatter:()=>i,metadata:()=>s,toc:()=>u});var r=n(7462),a=(n(7294),n(3905)),l=n(3872);const i={title:"Error building on ARM64",slug:"error-building-on-arm64",hide_title:!0,tags:["references","help","fix"]},o=void 0,s={unversionedId:"Lightning CLI/error-building-on-arm64",id:"Lightning CLI/error-building-on-arm64",title:"Error building on ARM64",description:"Building on the ARM64 (aarch64)",source:"@site/references/Lightning CLI/error-building-on-arm64.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/error-building-on-arm64",permalink:"/references/Lightning CLI/error-building-on-arm64",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/error-building-on-arm64.md",tags:[{label:"references",permalink:"/references/tags/references"},{label:"help",permalink:"/references/tags/help"},{label:"fix",permalink:"/references/tags/fix"}],version:"current",lastUpdatedAt:1694784773,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Error building on ARM64",slug:"error-building-on-arm64",hide_title:!0,tags:["references","help","fix"]},sidebar:"defaultSidebar",previous:{title:"About references",permalink:"/references/"},next:{title:"Error linking with cc",permalink:"/references/Lightning CLI/error-linking-with-cc-failed-exist-status-1"}},c={},u=[{value:"Building on the ARM64 (aarch64)",id:"building-on-the-arm64-aarch64",level:2}],p={toc:u},m="wrapper";function d(e){let{components:t,...n}=e;return(0,a.kt)(m,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"building-on-the-arm64-aarch64"},"Building on the ARM64 (aarch64)"),(0,a.kt)("p",null,"ARM64 platform has its own specifics, and currently consists of requiring ",(0,a.kt)("inlineCode",{parentName:"p"},"gcc"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"sudo apt install gcc\n")),(0,a.kt)("p",null,"On cargo build, the error ",(0,a.kt)("inlineCode",{parentName:"p"},"error: linking with "),"cc",(0,a.kt)("inlineCode",{parentName:"p"}," failed: exit status: 1")," occurs, as demonstrated in the output below:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"error: linking with `cc` failed: exit status: 1\n# ... wall of text\n# ... the key error is \u21b4\n= note: /usr/bin/ld: /home/ubuntu/fleek-network/lightning/target/release/deps/libblake3-a927e9b36d695ff0.rlib(blake3-a927e9b36d695ff0.blake3.91a53ea05847a7a5-cgu.0.rcgu.o): in function `blake3_compress_in_place_portable':\n /home/ubuntu/.cargo/registry/src/index.crates.io-6f17d22bba15001f/blake3-1.4.1/src/ffi_neon.rs:45: multiple definition of `blake3_compress_in_place_portable'; /home/ubuntu/fleek-network/lightning/target/release/deps/libfleek_blake3-990c4c0cfb4eaa87.rlib(fleek_blake3-990c4c0cfb4eaa87.fleek_blake3.4f11e9370af31773-cgu.0.rcgu.o):/home/ubuntu/.cargo/registry/src/index.crates.io-6f17d22bba15001f/fleek-blake3-1.4.1/src/ffi_neon.rs:45: first defined here\n")),(0,a.kt)("p",null,"As a result of the ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/ryssroad/fleek-aarch64-build"},"research")," by the community member ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/ryssroad"},"ryssroad"),", the following solution was shared."),(0,a.kt)("p",null,"Open the ",(0,a.kt)("inlineCode",{parentName:"p"},"cargo.toml")," file in ",(0,a.kt)("inlineCode",{parentName:"p"},"~/fleek-network/lightning/Cargo.toml")," and find the ",(0,a.kt)("inlineCode",{parentName:"p"},"lto")," key."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lto = true\n")),(0,a.kt)("p",null,"Change the ",(0,a.kt)("inlineCode",{parentName:"p"},"lto")," key value from ",(0,a.kt)("inlineCode",{parentName:"p"},"true")," to ",(0,a.kt)("inlineCode",{parentName:"p"},"thin"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'...\n[profile.release]\n# currently enabled, may increase build time, but runtime faster, can set to `"thin"`.\nlto = "thin"\n')),(0,a.kt)("p",null,"Set ",(0,a.kt)("inlineCode",{parentName:"p"},"RUSTFLAGS")," on build, as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},'RUSTFLAGS="-Clink-arg=-Wl,--allow-multiple-definition" cargo +stable build --release \n')),(0,a.kt)("p",null,"Once the build completes, you should find the generated binary ",(0,a.kt)("inlineCode",{parentName:"p"},"lightning-node")," under the directory ",(0,a.kt)("inlineCode",{parentName:"p"},"~/fleek-network/lightning/target/release/lightning-node"),"."),(0,a.kt)("p",null,"As an example, execute:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"~/fleek-network/lightning/target/release/lightning-node help\n")),(0,a.kt)("p",null,"To find the help output:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"Usage: lightning-node [OPTIONS] \n\nCommands:\n run Start the node\n keys Handle keys\n print-config Print the loaded configuration\n help Print this message or the help of the given subcommand(s)\n\nOptions:\n -c, --config Path to the toml configuration file [default: ~/.lightning/config.toml]\n --with-mock-consensus Determines that we should be using the mock consensus backend\n -v... Increases the level of verbosity (the max level is -vvv)\n --log-location Print code location on console logs\n -h, --help Print help\n -V, --version Print version\n")),(0,a.kt)(l.Z,{name:"Road aka @road",image:"https://github.com/ryssroad.png",title:"Community member",url:"https://github.com/ryssroad",communityMember:"true",mdxType:"Author"}))}d.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>a});var r=n(7294);const a=e=>{let{image:t,name:n,title:a,url:l,communityMember:i=!1}=e;return r.createElement("section",{className:"author_card"},r.createElement("div",null,r.createElement("span",{className:"avatar"},r.createElement("a",{href:l,target:"_blank",alt:n},r.createElement("img",{src:t,alt:n}))),r.createElement("div",null,r.createElement("span",{className:"name"},r.createElement("a",{href:l,target:"_blank",alt:n},n)),r.createElement("span",{className:"title"},a),r.createElement("span",{className:"discord"},i?"Join our community on":"Got questions? Find us on"," ",r.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[2918],{3905:(e,t,n)=>{n.d(t,{Zo:()=>u,kt:()=>g});var r=n(7294);function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function l(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var l=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},u=function(e){var t=c(e.components);return r.createElement(s.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},d=r.forwardRef((function(e,t){var n=e.components,a=e.mdxType,l=e.originalType,s=e.parentName,u=o(e,["components","mdxType","originalType","parentName"]),p=c(n),d=a,g=p["".concat(s,".").concat(d)]||p[d]||m[d]||l;return n?r.createElement(g,i(i({ref:t},u),{},{components:n})):r.createElement(g,i({ref:t},u))}));function g(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var l=n.length,i=new Array(l);i[0]=d;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o[p]="string"==typeof e?e:a,i[1]=o;for(var c=2;c{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>d,frontMatter:()=>i,metadata:()=>s,toc:()=>u});var r=n(7462),a=(n(7294),n(3905)),l=n(3872);const i={title:"Error building on ARM64",slug:"error-building-on-arm64",hide_title:!0,tags:["references","help","fix"]},o=void 0,s={unversionedId:"Lightning CLI/error-building-on-arm64",id:"Lightning CLI/error-building-on-arm64",title:"Error building on ARM64",description:"Building on the ARM64 (aarch64)",source:"@site/references/Lightning CLI/error-building-on-arm64.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/error-building-on-arm64",permalink:"/references/Lightning CLI/error-building-on-arm64",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/error-building-on-arm64.md",tags:[{label:"references",permalink:"/references/tags/references"},{label:"help",permalink:"/references/tags/help"},{label:"fix",permalink:"/references/tags/fix"}],version:"current",lastUpdatedAt:1694785242,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Error building on ARM64",slug:"error-building-on-arm64",hide_title:!0,tags:["references","help","fix"]},sidebar:"defaultSidebar",previous:{title:"About references",permalink:"/references/"},next:{title:"Error linking with cc",permalink:"/references/Lightning CLI/error-linking-with-cc-failed-exist-status-1"}},c={},u=[{value:"Building on the ARM64 (aarch64)",id:"building-on-the-arm64-aarch64",level:2}],p={toc:u},m="wrapper";function d(e){let{components:t,...n}=e;return(0,a.kt)(m,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,a.kt)("h2",{id:"building-on-the-arm64-aarch64"},"Building on the ARM64 (aarch64)"),(0,a.kt)("p",null,"ARM64 platform has its own specifics, and currently consists of requiring ",(0,a.kt)("inlineCode",{parentName:"p"},"gcc"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},"sudo apt install gcc\n")),(0,a.kt)("p",null,"On cargo build, the error ",(0,a.kt)("inlineCode",{parentName:"p"},"error: linking with "),"cc",(0,a.kt)("inlineCode",{parentName:"p"}," failed: exit status: 1")," occurs, as demonstrated in the output below:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"error: linking with `cc` failed: exit status: 1\n# ... wall of text\n# ... the key error is \u21b4\n= note: /usr/bin/ld: /home/ubuntu/fleek-network/lightning/target/release/deps/libblake3-a927e9b36d695ff0.rlib(blake3-a927e9b36d695ff0.blake3.91a53ea05847a7a5-cgu.0.rcgu.o): in function `blake3_compress_in_place_portable':\n /home/ubuntu/.cargo/registry/src/index.crates.io-6f17d22bba15001f/blake3-1.4.1/src/ffi_neon.rs:45: multiple definition of `blake3_compress_in_place_portable'; /home/ubuntu/fleek-network/lightning/target/release/deps/libfleek_blake3-990c4c0cfb4eaa87.rlib(fleek_blake3-990c4c0cfb4eaa87.fleek_blake3.4f11e9370af31773-cgu.0.rcgu.o):/home/ubuntu/.cargo/registry/src/index.crates.io-6f17d22bba15001f/fleek-blake3-1.4.1/src/ffi_neon.rs:45: first defined here\n")),(0,a.kt)("p",null,"As a result of the ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/ryssroad/fleek-aarch64-build"},"research")," by the community member ",(0,a.kt)("a",{parentName:"p",href:"https://github.com/ryssroad"},"ryssroad"),", the following solution was shared."),(0,a.kt)("p",null,"Open the ",(0,a.kt)("inlineCode",{parentName:"p"},"cargo.toml")," file in ",(0,a.kt)("inlineCode",{parentName:"p"},"~/fleek-network/lightning/Cargo.toml")," and find the ",(0,a.kt)("inlineCode",{parentName:"p"},"lto")," key."),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"lto = true\n")),(0,a.kt)("p",null,"Change the ",(0,a.kt)("inlineCode",{parentName:"p"},"lto")," key value from ",(0,a.kt)("inlineCode",{parentName:"p"},"true")," to ",(0,a.kt)("inlineCode",{parentName:"p"},"thin"),":"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},'...\n[profile.release]\n# currently enabled, may increase build time, but runtime faster, can set to `"thin"`.\nlto = "thin"\n')),(0,a.kt)("p",null,"Set ",(0,a.kt)("inlineCode",{parentName:"p"},"RUSTFLAGS")," on build, as follows:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-bash"},'RUSTFLAGS="-Clink-arg=-Wl,--allow-multiple-definition" cargo +stable build --release \n')),(0,a.kt)("p",null,"Once the build completes, you should find the generated binary ",(0,a.kt)("inlineCode",{parentName:"p"},"lightning-node")," under the directory ",(0,a.kt)("inlineCode",{parentName:"p"},"~/fleek-network/lightning/target/release/lightning-node"),"."),(0,a.kt)("p",null,"As an example, execute:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"~/fleek-network/lightning/target/release/lightning-node help\n")),(0,a.kt)("p",null,"To find the help output:"),(0,a.kt)("pre",null,(0,a.kt)("code",{parentName:"pre",className:"language-sh"},"Usage: lightning-node [OPTIONS] \n\nCommands:\n run Start the node\n keys Handle keys\n print-config Print the loaded configuration\n help Print this message or the help of the given subcommand(s)\n\nOptions:\n -c, --config Path to the toml configuration file [default: ~/.lightning/config.toml]\n --with-mock-consensus Determines that we should be using the mock consensus backend\n -v... Increases the level of verbosity (the max level is -vvv)\n --log-location Print code location on console logs\n -h, --help Print help\n -V, --version Print version\n")),(0,a.kt)(l.Z,{name:"Road aka @road",image:"https://github.com/ryssroad.png",title:"Community member",url:"https://github.com/ryssroad",communityMember:"true",mdxType:"Author"}))}d.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>a});var r=n(7294);const a=e=>{let{image:t,name:n,title:a,url:l,communityMember:i=!1}=e;return r.createElement("section",{className:"author_card"},r.createElement("div",null,r.createElement("span",{className:"avatar"},r.createElement("a",{href:l,target:"_blank",alt:n},r.createElement("img",{src:t,alt:n}))),r.createElement("div",null,r.createElement("span",{className:"name"},r.createElement("a",{href:l,target:"_blank",alt:n},n)),r.createElement("span",{className:"title"},a),r.createElement("span",{className:"discord"},i?"Join our community on":"Got questions? Find us on"," ",r.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file diff --git a/assets/js/d8be0e5a.a9d96359.js b/assets/js/d8be0e5a.6326dcd2.js similarity index 99% rename from assets/js/d8be0e5a.a9d96359.js rename to assets/js/d8be0e5a.6326dcd2.js index 0bf42308e..401f6b7a2 100644 --- a/assets/js/d8be0e5a.a9d96359.js +++ b/assets/js/d8be0e5a.6326dcd2.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[1706],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>f});var n=r(7294);function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),u=c(r),m=i,f=u["".concat(s,".").concat(m)]||u[m]||d[m]||a;return r?n.createElement(f,l(l({ref:t},p),{},{components:r})):n.createElement(f,l({ref:t},p))}));function f(e,t){var r=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=r.length,l=new Array(a);l[0]=m;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o[u]="string"==typeof e?e:i,l[1]=o;for(var c=2;c{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>m,frontMatter:()=>l,metadata:()=>s,toc:()=>p});var n=r(7462),i=(r(7294),r(3905)),a=r(3872);const l={title:"Error linking with cc",slug:"error-linking-with-cc-failed-exist-status-1",hide_title:!0,tags:["references","help","update","upgrade","fix"]},o=void 0,s={unversionedId:"Lightning CLI/error-linking-with-cc-failed",id:"Lightning CLI/error-linking-with-cc-failed",title:"Error linking with cc",description:"Check if CPU is supported",source:"@site/references/Lightning CLI/error-linking-with-cc-failed.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/error-linking-with-cc-failed-exist-status-1",permalink:"/references/Lightning CLI/error-linking-with-cc-failed-exist-status-1",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/error-linking-with-cc-failed.md",tags:[{label:"references",permalink:"/references/tags/references"},{label:"help",permalink:"/references/tags/help"},{label:"update",permalink:"/references/tags/update"},{label:"upgrade",permalink:"/references/tags/upgrade"},{label:"fix",permalink:"/references/tags/fix"}],version:"current",lastUpdatedAt:1694784773,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Error linking with cc",slug:"error-linking-with-cc-failed-exist-status-1",hide_title:!0,tags:["references","help","update","upgrade","fix"]},sidebar:"defaultSidebar",previous:{title:"Error building on ARM64",permalink:"/references/Lightning CLI/error-building-on-arm64"},next:{title:"File permissions and Ownership",permalink:"/references/Lightning CLI/file-permissions-and-ownership"}},c={},p=[{value:"Check if CPU is supported",id:"check-if-cpu-is-supported",level:2},{value:"Linking with cc error",id:"linking-with-cc-error",level:2},{value:"Update",id:"update",level:2},{value:"Install gcc:",id:"install-gcc",level:2},{value:"Remove previous installation files",id:"remove-previous-installation-files",level:2},{value:"Run the installation script",id:"run-the-installation-script",level:2}],u={toc:p},d="wrapper";function m(e){let{components:t,...r}=e;return(0,i.kt)(d,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"check-if-cpu-is-supported"},"Check if CPU is supported"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"uname -i\n")),(0,i.kt)("admonition",{title:"WARNING",type:"caution"},(0,i.kt)("p",{parentName:"admonition"},"Given the ",(0,i.kt)("a",{parentName:"p",href:"https://docs.fleek.network/docs/node/requirements/#specs"},"CPU requirements"),", currently we're mainly supporting ",(0,i.kt)("inlineCode",{parentName:"p"},"GenuineIntel")," and there have been reports of failure to build the binary on ",(0,i.kt)("inlineCode",{parentName:"p"},"AMD"),". The ",(0,i.kt)("inlineCode",{parentName:"p"},"ARM64")," is a different architecture, thus not supported, but there has been some community contributions in that regard, find it in the reference ",(0,i.kt)("a",{parentName:"p",href:"/references/Lightning%20CLI/error-building-on-arm64"},"error building on ARM64"),"."),(0,i.kt)("p",{parentName:"admonition"},"Any contribution or feedback to provide support is appreciated. Feel free to let us know on our ",(0,i.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"Discord channel"),".")),(0,i.kt)("h2",{id:"linking-with-cc-error"},"Linking with cc error"),(0,i.kt)("p",null,"A user who finds the error ",(0,i.kt)("inlineCode",{parentName:"p"},"linking with cc failed"),", will have to install the required dependencies."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"error: linking with `cc` failed: exit status: 1\nerror: could not compile `fleek-service-ping-example` (lib) due to previous error\n")),(0,i.kt)("h2",{id:"update"},"Update"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"sudo apt-get update\n")),(0,i.kt)("h2",{id:"install-gcc"},"Install ",(0,i.kt)("inlineCode",{parentName:"h2"},"gcc"),":"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"sudo apt-get install gcc\n")),(0,i.kt)("h2",{id:"remove-previous-installation-files"},"Remove previous installation files"),(0,i.kt)("p",null,"You can re-run the installation process. If you are using the assisted installer, it'll complain that the source code directory already exists. Since you've probably cloned the source code repository locally, you'll have to remove it manually. If you need help, find the instructions in the ",(0,i.kt)("a",{parentName:"p",href:"/references/Lightning%20CLI/uninstall-lightning-cli"},"reference"),"."),(0,i.kt)("h2",{id:"run-the-installation-script"},"Run the installation script"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"curl https://get.fleek.network | bash\n")),(0,i.kt)("p",null,"Alternatively, read the ",(0,i.kt)("a",{parentName:"p",href:"/docs/node/install#manual-installation"},"manual installation instructions")," for more information."),(0,i.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}m.isMDXComponent=!0},3872:(e,t,r)=>{r.d(t,{Z:()=>i});var n=r(7294);const i=e=>{let{image:t,name:r,title:i,url:a,communityMember:l=!1}=e;return n.createElement("section",{className:"author_card"},n.createElement("div",null,n.createElement("span",{className:"avatar"},n.createElement("a",{href:a,target:"_blank",alt:r},n.createElement("img",{src:t,alt:r}))),n.createElement("div",null,n.createElement("span",{className:"name"},n.createElement("a",{href:a,target:"_blank",alt:r},r)),n.createElement("span",{className:"title"},i),n.createElement("span",{className:"discord"},l?"Join our community on":"Got questions? Find us on"," ",n.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[1706],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>f});var n=r(7294);function i(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t=0||(i[r]=e[r]);return i}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(i[r]=e[r])}return i}var s=n.createContext({}),c=function(e){var t=n.useContext(s),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},p=function(e){var t=c(e.components);return n.createElement(s.Provider,{value:t},e.children)},u="mdxType",d={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,i=e.mdxType,a=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),u=c(r),m=i,f=u["".concat(s,".").concat(m)]||u[m]||d[m]||a;return r?n.createElement(f,l(l({ref:t},p),{},{components:r})):n.createElement(f,l({ref:t},p))}));function f(e,t){var r=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var a=r.length,l=new Array(a);l[0]=m;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o[u]="string"==typeof e?e:i,l[1]=o;for(var c=2;c{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>m,frontMatter:()=>l,metadata:()=>s,toc:()=>p});var n=r(7462),i=(r(7294),r(3905)),a=r(3872);const l={title:"Error linking with cc",slug:"error-linking-with-cc-failed-exist-status-1",hide_title:!0,tags:["references","help","update","upgrade","fix"]},o=void 0,s={unversionedId:"Lightning CLI/error-linking-with-cc-failed",id:"Lightning CLI/error-linking-with-cc-failed",title:"Error linking with cc",description:"Check if CPU is supported",source:"@site/references/Lightning CLI/error-linking-with-cc-failed.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/error-linking-with-cc-failed-exist-status-1",permalink:"/references/Lightning CLI/error-linking-with-cc-failed-exist-status-1",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/error-linking-with-cc-failed.md",tags:[{label:"references",permalink:"/references/tags/references"},{label:"help",permalink:"/references/tags/help"},{label:"update",permalink:"/references/tags/update"},{label:"upgrade",permalink:"/references/tags/upgrade"},{label:"fix",permalink:"/references/tags/fix"}],version:"current",lastUpdatedAt:1694785242,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Error linking with cc",slug:"error-linking-with-cc-failed-exist-status-1",hide_title:!0,tags:["references","help","update","upgrade","fix"]},sidebar:"defaultSidebar",previous:{title:"Error building on ARM64",permalink:"/references/Lightning CLI/error-building-on-arm64"},next:{title:"File permissions and Ownership",permalink:"/references/Lightning CLI/file-permissions-and-ownership"}},c={},p=[{value:"Check if CPU is supported",id:"check-if-cpu-is-supported",level:2},{value:"Linking with cc error",id:"linking-with-cc-error",level:2},{value:"Update",id:"update",level:2},{value:"Install gcc:",id:"install-gcc",level:2},{value:"Remove previous installation files",id:"remove-previous-installation-files",level:2},{value:"Run the installation script",id:"run-the-installation-script",level:2}],u={toc:p},d="wrapper";function m(e){let{components:t,...r}=e;return(0,i.kt)(d,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"check-if-cpu-is-supported"},"Check if CPU is supported"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"uname -i\n")),(0,i.kt)("admonition",{title:"WARNING",type:"caution"},(0,i.kt)("p",{parentName:"admonition"},"Given the ",(0,i.kt)("a",{parentName:"p",href:"https://docs.fleek.network/docs/node/requirements/#specs"},"CPU requirements"),", currently we're mainly supporting ",(0,i.kt)("inlineCode",{parentName:"p"},"GenuineIntel")," and there have been reports of failure to build the binary on ",(0,i.kt)("inlineCode",{parentName:"p"},"AMD"),". The ",(0,i.kt)("inlineCode",{parentName:"p"},"ARM64")," is a different architecture, thus not supported, but there has been some community contributions in that regard, find it in the reference ",(0,i.kt)("a",{parentName:"p",href:"/references/Lightning%20CLI/error-building-on-arm64"},"error building on ARM64"),"."),(0,i.kt)("p",{parentName:"admonition"},"Any contribution or feedback to provide support is appreciated. Feel free to let us know on our ",(0,i.kt)("a",{parentName:"p",href:"https://discord.gg/fleekxyz"},"Discord channel"),".")),(0,i.kt)("h2",{id:"linking-with-cc-error"},"Linking with cc error"),(0,i.kt)("p",null,"A user who finds the error ",(0,i.kt)("inlineCode",{parentName:"p"},"linking with cc failed"),", will have to install the required dependencies."),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"error: linking with `cc` failed: exit status: 1\nerror: could not compile `fleek-service-ping-example` (lib) due to previous error\n")),(0,i.kt)("h2",{id:"update"},"Update"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"sudo apt-get update\n")),(0,i.kt)("h2",{id:"install-gcc"},"Install ",(0,i.kt)("inlineCode",{parentName:"h2"},"gcc"),":"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"sudo apt-get install gcc\n")),(0,i.kt)("h2",{id:"remove-previous-installation-files"},"Remove previous installation files"),(0,i.kt)("p",null,"You can re-run the installation process. If you are using the assisted installer, it'll complain that the source code directory already exists. Since you've probably cloned the source code repository locally, you'll have to remove it manually. If you need help, find the instructions in the ",(0,i.kt)("a",{parentName:"p",href:"/references/Lightning%20CLI/uninstall-lightning-cli"},"reference"),"."),(0,i.kt)("h2",{id:"run-the-installation-script"},"Run the installation script"),(0,i.kt)("pre",null,(0,i.kt)("code",{parentName:"pre",className:"language-sh"},"curl https://get.fleek.network | bash\n")),(0,i.kt)("p",null,"Alternatively, read the ",(0,i.kt)("a",{parentName:"p",href:"/docs/node/install#manual-installation"},"manual installation instructions")," for more information."),(0,i.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}m.isMDXComponent=!0},3872:(e,t,r)=>{r.d(t,{Z:()=>i});var n=r(7294);const i=e=>{let{image:t,name:r,title:i,url:a,communityMember:l=!1}=e;return n.createElement("section",{className:"author_card"},n.createElement("div",null,n.createElement("span",{className:"avatar"},n.createElement("a",{href:a,target:"_blank",alt:r},n.createElement("img",{src:t,alt:r}))),n.createElement("div",null,n.createElement("span",{className:"name"},n.createElement("a",{href:a,target:"_blank",alt:r},r)),n.createElement("span",{className:"title"},i),n.createElement("span",{className:"discord"},l?"Join our community on":"Got questions? Find us on"," ",n.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file diff --git a/assets/js/e1f64676.dc609c05.js b/assets/js/e1f64676.89f417d8.js similarity index 98% rename from assets/js/e1f64676.dc609c05.js rename to assets/js/e1f64676.89f417d8.js index 8d760ecfc..fd3004df5 100644 --- a/assets/js/e1f64676.dc609c05.js +++ b/assets/js/e1f64676.89f417d8.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[3120],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>d});var r=n(7294);function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(l[n]=e[n]);return l}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(l[n]=e[n])}return l}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return r.createElement(s.Provider,{value:t},e.children)},m="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},g=r.forwardRef((function(e,t){var n=e.components,l=e.mdxType,a=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),m=c(n),g=l,d=m["".concat(s,".").concat(g)]||m[g]||u[g]||a;return n?r.createElement(d,i(i({ref:t},p),{},{components:n})):r.createElement(d,i({ref:t},p))}));function d(e,t){var n=arguments,l=t&&t.mdxType;if("string"==typeof e||l){var a=n.length,i=new Array(a);i[0]=g;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o[m]="string"==typeof e?e:l,i[1]=o;for(var c=2;c{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>g,frontMatter:()=>i,metadata:()=>s,toc:()=>p});var r=n(7462),l=(n(7294),n(3905)),a=n(3872);const i={title:"Uninstall Lightning CLI",slug:"uninstall-lightning-cli",hide_title:!0,tags:["References","Help","Uninstall","Remove","Delete","Clear","Clean"]},o=void 0,s={unversionedId:"Lightning CLI/uninstall-lightning-cli",id:"Lightning CLI/uninstall-lightning-cli",title:"Uninstall Lightning CLI",description:"Remove symLink",source:"@site/references/Lightning CLI/uninstall-lightning-cli.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/uninstall-lightning-cli",permalink:"/references/Lightning CLI/uninstall-lightning-cli",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/uninstall-lightning-cli.md",tags:[{label:"References",permalink:"/references/tags/references"},{label:"Help",permalink:"/references/tags/help"},{label:"Uninstall",permalink:"/references/tags/uninstall"},{label:"Remove",permalink:"/references/tags/remove"},{label:"Delete",permalink:"/references/tags/delete"},{label:"Clear",permalink:"/references/tags/clear"},{label:"Clean",permalink:"/references/tags/clean"}],version:"current",lastUpdatedAt:1694784773,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Uninstall Lightning CLI",slug:"uninstall-lightning-cli",hide_title:!0,tags:["References","Help","Uninstall","Remove","Delete","Clear","Clean"]},sidebar:"defaultSidebar",previous:{title:"Permission denied (os error 13)",permalink:"/references/Lightning CLI/permission-denied-os-error-13"},next:{title:"Update CLI from source code",permalink:"/references/Lightning CLI/update-cli-from-source-code"}},c={},p=[{value:"Remove symLink",id:"remove-symlink",level:2},{value:"Delete the local source code",id:"delete-the-local-source-code",level:2},{value:"Disable the systemd service",id:"disable-the-systemd-service",level:2},{value:"Clear the lightning config directory",id:"clear-the-lightning-config-directory",level:2},{value:"Uninstall Cargo and Rust",id:"uninstall-cargo-and-rust",level:2}],m={toc:p},u="wrapper";function g(e){let{components:t,...n}=e;return(0,l.kt)(u,(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,l.kt)("h2",{id:"remove-symlink"},"Remove symLink"),(0,l.kt)("p",null,"To remove a symbolic link, use either the rm or unlink command followed by the name of the symlink as an argument. Here's an example with ",(0,l.kt)("inlineCode",{parentName:"p"},"unlink"),":"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"unlink /usr/local/bin/lgtn\n")),(0,l.kt)("h2",{id:"delete-the-local-source-code"},"Delete the local source code"),(0,l.kt)("p",null,"Delete the local source code which was copied from the remote ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/lightning"},"repository"),". You can delete it recursively by:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"rm -r ~/fleek-network/lightning\n")),(0,l.kt)("p",null,"\ud83d\udca1 Use the flag ",(0,l.kt)("inlineCode",{parentName:"p"},"f")," to force remove by skipping any prompts, e.g. ",(0,l.kt)("inlineCode",{parentName:"p"},"rm -rf ")),(0,l.kt)("admonition",{type:"note"},(0,l.kt)("p",{parentName:"admonition"},"The default install location is ",(0,l.kt)("inlineCode",{parentName:"p"},"$HOME/fleek-network/lightning"),". If you have selected a different location to store the repository, change the target path.")),(0,l.kt)("h2",{id:"disable-the-systemd-service"},"Disable the systemd service"),(0,l.kt)("p",null,"To disable the Fleek Network Lightning Systemd's service, start by stopping the service."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl stop lightning.service\n")),(0,l.kt)("admonition",{type:"tip"},(0,l.kt)("p",{parentName:"admonition"},"You can replace ",(0,l.kt)("inlineCode",{parentName:"p"},"lightning.service")," by ",(0,l.kt)("inlineCode",{parentName:"p"},"lightning"),".")),(0,l.kt)("p",null,"Disable the lightning service"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl disable lightning.service\n")),(0,l.kt)("p",null,"If you have used the recommended procedures in the ",(0,l.kt)("a",{parentName:"p",href:"/docs/node/install"},"install")," documentation you'll have to remove the Systemd unit (file that defines the service)."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"rm /etc/systemd/system/lightning.service\n")),(0,l.kt)("p",null,"Reload the Systemd service daemon"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl daemon-reload\n")),(0,l.kt)("h2",{id:"clear-the-lightning-config-directory"},"Clear the lightning config directory"),(0,l.kt)("p",null,"The Fleek Network lightning config directory is where the configuration, keystore\u2013the location where your private key is hosted\u2013and other system files are stored."),(0,l.kt)("admonition",{title:"WARNING",type:"caution"},(0,l.kt)("p",{parentName:"admonition"},"Make sure to backup any sensitive data, such as the keystore (private keys), as you won't be able to recover the keys by any other means. If you have any funds associated with it, it'll be lost forever. The Fleek Network team or anyone else will not be able to help recover keys. Your keys, your responsibility.")),(0,l.kt)("p",null,"Alternatively, instead of deleting you can move the files to a custom directory name such as",(0,l.kt)("inlineCode",{parentName:"p"},".lightning.backupDATESTAMP"),", e.g. the example below we've used the date ",(0,l.kt)("inlineCode",{parentName:"p"},"2023-09-06-1205")," as that was the time this text was written:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"mv ~/.lightning ~/.lightning.backup202309061205\n")),(0,l.kt)("p",null,"To clear the lightning config directory remove any files recursively by running the following command:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"rm -r ~/.lightning/*\n")),(0,l.kt)("p",null,"\ud83d\udca1 Use the flag ",(0,l.kt)("inlineCode",{parentName:"p"},"f")," to force remove by skipping any prompts, e.g. ",(0,l.kt)("inlineCode",{parentName:"p"},"rm -rf /*")),(0,l.kt)("p",null,"Alternatively, delete the ",(0,l.kt)("inlineCode",{parentName:"p"},"~/.lightning")," directory:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"rm -r ~/.lightning\n")),(0,l.kt)("h2",{id:"uninstall-cargo-and-rust"},"Uninstall Cargo and Rust"),(0,l.kt)("p",null,"To uninstall rustc, rustup and cargo run the following command:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"rustup self uninstall\n")),(0,l.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}g.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>l});var r=n(7294);const l=e=>{let{image:t,name:n,title:l,url:a,communityMember:i=!1}=e;return r.createElement("section",{className:"author_card"},r.createElement("div",null,r.createElement("span",{className:"avatar"},r.createElement("a",{href:a,target:"_blank",alt:n},r.createElement("img",{src:t,alt:n}))),r.createElement("div",null,r.createElement("span",{className:"name"},r.createElement("a",{href:a,target:"_blank",alt:n},n)),r.createElement("span",{className:"title"},l),r.createElement("span",{className:"discord"},i?"Join our community on":"Got questions? Find us on"," ",r.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[3120],{3905:(e,t,n)=>{n.d(t,{Zo:()=>p,kt:()=>d});var r=n(7294);function l(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function i(e){for(var t=1;t=0||(l[n]=e[n]);return l}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(l[n]=e[n])}return l}var s=r.createContext({}),c=function(e){var t=r.useContext(s),n=t;return e&&(n="function"==typeof e?e(t):i(i({},t),e)),n},p=function(e){var t=c(e.components);return r.createElement(s.Provider,{value:t},e.children)},m="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},g=r.forwardRef((function(e,t){var n=e.components,l=e.mdxType,a=e.originalType,s=e.parentName,p=o(e,["components","mdxType","originalType","parentName"]),m=c(n),g=l,d=m["".concat(s,".").concat(g)]||m[g]||u[g]||a;return n?r.createElement(d,i(i({ref:t},p),{},{components:n})):r.createElement(d,i({ref:t},p))}));function d(e,t){var n=arguments,l=t&&t.mdxType;if("string"==typeof e||l){var a=n.length,i=new Array(a);i[0]=g;var o={};for(var s in t)hasOwnProperty.call(t,s)&&(o[s]=t[s]);o.originalType=e,o[m]="string"==typeof e?e:l,i[1]=o;for(var c=2;c{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>o,default:()=>g,frontMatter:()=>i,metadata:()=>s,toc:()=>p});var r=n(7462),l=(n(7294),n(3905)),a=n(3872);const i={title:"Uninstall Lightning CLI",slug:"uninstall-lightning-cli",hide_title:!0,tags:["References","Help","Uninstall","Remove","Delete","Clear","Clean"]},o=void 0,s={unversionedId:"Lightning CLI/uninstall-lightning-cli",id:"Lightning CLI/uninstall-lightning-cli",title:"Uninstall Lightning CLI",description:"Remove symLink",source:"@site/references/Lightning CLI/uninstall-lightning-cli.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/uninstall-lightning-cli",permalink:"/references/Lightning CLI/uninstall-lightning-cli",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/uninstall-lightning-cli.md",tags:[{label:"References",permalink:"/references/tags/references"},{label:"Help",permalink:"/references/tags/help"},{label:"Uninstall",permalink:"/references/tags/uninstall"},{label:"Remove",permalink:"/references/tags/remove"},{label:"Delete",permalink:"/references/tags/delete"},{label:"Clear",permalink:"/references/tags/clear"},{label:"Clean",permalink:"/references/tags/clean"}],version:"current",lastUpdatedAt:1694785242,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Uninstall Lightning CLI",slug:"uninstall-lightning-cli",hide_title:!0,tags:["References","Help","Uninstall","Remove","Delete","Clear","Clean"]},sidebar:"defaultSidebar",previous:{title:"Permission denied (os error 13)",permalink:"/references/Lightning CLI/permission-denied-os-error-13"},next:{title:"Update CLI from source code",permalink:"/references/Lightning CLI/update-cli-from-source-code"}},c={},p=[{value:"Remove symLink",id:"remove-symlink",level:2},{value:"Delete the local source code",id:"delete-the-local-source-code",level:2},{value:"Disable the systemd service",id:"disable-the-systemd-service",level:2},{value:"Clear the lightning config directory",id:"clear-the-lightning-config-directory",level:2},{value:"Uninstall Cargo and Rust",id:"uninstall-cargo-and-rust",level:2}],m={toc:p},u="wrapper";function g(e){let{components:t,...n}=e;return(0,l.kt)(u,(0,r.Z)({},m,n,{components:t,mdxType:"MDXLayout"}),(0,l.kt)("h2",{id:"remove-symlink"},"Remove symLink"),(0,l.kt)("p",null,"To remove a symbolic link, use either the rm or unlink command followed by the name of the symlink as an argument. Here's an example with ",(0,l.kt)("inlineCode",{parentName:"p"},"unlink"),":"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"unlink /usr/local/bin/lgtn\n")),(0,l.kt)("h2",{id:"delete-the-local-source-code"},"Delete the local source code"),(0,l.kt)("p",null,"Delete the local source code which was copied from the remote ",(0,l.kt)("a",{parentName:"p",href:"https://github.com/fleek-network/lightning"},"repository"),". You can delete it recursively by:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"rm -r ~/fleek-network/lightning\n")),(0,l.kt)("p",null,"\ud83d\udca1 Use the flag ",(0,l.kt)("inlineCode",{parentName:"p"},"f")," to force remove by skipping any prompts, e.g. ",(0,l.kt)("inlineCode",{parentName:"p"},"rm -rf ")),(0,l.kt)("admonition",{type:"note"},(0,l.kt)("p",{parentName:"admonition"},"The default install location is ",(0,l.kt)("inlineCode",{parentName:"p"},"$HOME/fleek-network/lightning"),". If you have selected a different location to store the repository, change the target path.")),(0,l.kt)("h2",{id:"disable-the-systemd-service"},"Disable the systemd service"),(0,l.kt)("p",null,"To disable the Fleek Network Lightning Systemd's service, start by stopping the service."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl stop lightning.service\n")),(0,l.kt)("admonition",{type:"tip"},(0,l.kt)("p",{parentName:"admonition"},"You can replace ",(0,l.kt)("inlineCode",{parentName:"p"},"lightning.service")," by ",(0,l.kt)("inlineCode",{parentName:"p"},"lightning"),".")),(0,l.kt)("p",null,"Disable the lightning service"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl disable lightning.service\n")),(0,l.kt)("p",null,"If you have used the recommended procedures in the ",(0,l.kt)("a",{parentName:"p",href:"/docs/node/install"},"install")," documentation you'll have to remove the Systemd unit (file that defines the service)."),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"rm /etc/systemd/system/lightning.service\n")),(0,l.kt)("p",null,"Reload the Systemd service daemon"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"sudo systemctl daemon-reload\n")),(0,l.kt)("h2",{id:"clear-the-lightning-config-directory"},"Clear the lightning config directory"),(0,l.kt)("p",null,"The Fleek Network lightning config directory is where the configuration, keystore\u2013the location where your private key is hosted\u2013and other system files are stored."),(0,l.kt)("admonition",{title:"WARNING",type:"caution"},(0,l.kt)("p",{parentName:"admonition"},"Make sure to backup any sensitive data, such as the keystore (private keys), as you won't be able to recover the keys by any other means. If you have any funds associated with it, it'll be lost forever. The Fleek Network team or anyone else will not be able to help recover keys. Your keys, your responsibility.")),(0,l.kt)("p",null,"Alternatively, instead of deleting you can move the files to a custom directory name such as",(0,l.kt)("inlineCode",{parentName:"p"},".lightning.backupDATESTAMP"),", e.g. the example below we've used the date ",(0,l.kt)("inlineCode",{parentName:"p"},"2023-09-06-1205")," as that was the time this text was written:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"mv ~/.lightning ~/.lightning.backup202309061205\n")),(0,l.kt)("p",null,"To clear the lightning config directory remove any files recursively by running the following command:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"rm -r ~/.lightning/*\n")),(0,l.kt)("p",null,"\ud83d\udca1 Use the flag ",(0,l.kt)("inlineCode",{parentName:"p"},"f")," to force remove by skipping any prompts, e.g. ",(0,l.kt)("inlineCode",{parentName:"p"},"rm -rf /*")),(0,l.kt)("p",null,"Alternatively, delete the ",(0,l.kt)("inlineCode",{parentName:"p"},"~/.lightning")," directory:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"rm -r ~/.lightning\n")),(0,l.kt)("h2",{id:"uninstall-cargo-and-rust"},"Uninstall Cargo and Rust"),(0,l.kt)("p",null,"To uninstall rustc, rustup and cargo run the following command:"),(0,l.kt)("pre",null,(0,l.kt)("code",{parentName:"pre",className:"language-sh"},"rustup self uninstall\n")),(0,l.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}g.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>l});var r=n(7294);const l=e=>{let{image:t,name:n,title:l,url:a,communityMember:i=!1}=e;return r.createElement("section",{className:"author_card"},r.createElement("div",null,r.createElement("span",{className:"avatar"},r.createElement("a",{href:a,target:"_blank",alt:n},r.createElement("img",{src:t,alt:n}))),r.createElement("div",null,r.createElement("span",{className:"name"},r.createElement("a",{href:a,target:"_blank",alt:n},n)),r.createElement("span",{className:"title"},l),r.createElement("span",{className:"discord"},i?"Join our community on":"Got questions? Find us on"," ",r.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file diff --git a/assets/js/fd2b74dc.23f54082.js b/assets/js/fd2b74dc.9cd43391.js similarity index 98% rename from assets/js/fd2b74dc.23f54082.js rename to assets/js/fd2b74dc.9cd43391.js index 952017891..6ffdaac4a 100644 --- a/assets/js/fd2b74dc.23f54082.js +++ b/assets/js/fd2b74dc.9cd43391.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[4846],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>f});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function s(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},d=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},p="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),p=c(n),m=o,f=p["".concat(l,".").concat(m)]||p[m]||u[m]||a;return n?r.createElement(f,s(s({ref:t},d),{},{components:n})):r.createElement(f,s({ref:t},d))}));function f(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,s=new Array(a);s[0]=m;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[p]="string"==typeof e?e:o,s[1]=i;for(var c=2;c{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>s,metadata:()=>l,toc:()=>d});var r=n(7462),o=(n(7294),n(3905)),a=n(3872);const s={title:"Keys not found",slug:"keys-not-found",hide_title:!0,tags:["keystore","lost keys","ownership","file permissions"]},i=void 0,l={unversionedId:"Lightning CLI/keys-not-found",id:"Lightning CLI/keys-not-found",title:"Keys not found",description:"Node key does not exist",source:"@site/references/Lightning CLI/keys-not-found.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/keys-not-found",permalink:"/references/Lightning CLI/keys-not-found",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/keys-not-found.md",tags:[{label:"keystore",permalink:"/references/tags/keystore"},{label:"lost keys",permalink:"/references/tags/lost-keys"},{label:"ownership",permalink:"/references/tags/ownership"},{label:"file permissions",permalink:"/references/tags/file-permissions"}],version:"current",lastUpdatedAt:1694784773,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Keys not found",slug:"keys-not-found",hide_title:!0,tags:["keystore","lost keys","ownership","file permissions"]},sidebar:"defaultSidebar",previous:{title:"File permissions and Ownership",permalink:"/references/Lightning CLI/file-permissions-and-ownership"},next:{title:"Backing up the keystore",permalink:"/references/Lightning CLI/backing-up-the-keystore"}},c={},d=[{value:"Node key does not exist",id:"node-key-does-not-exist",level:2}],p={toc:d},u="wrapper";function m(e){let{components:t,...n}=e;return(0,o.kt)(u,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"node-key-does-not-exist"},"Node key does not exist"),(0,o.kt)("p",null,'When watching the Fleek Network Lightning service log output, you find the "Node key does not exist" message placed recursively. As follows:'),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"thread 'main' panicked at 'Node key does not exist. Use CLI to generate keys.', core/node/src/testnet_sync.rs:126:9\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\nthread 'main' panicked at 'Node key does not exist. Use CLI to generate keys.', core/node/src/testnet_sync.rs:126:9\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n")),(0,o.kt)("p",null,"If you haven't deleted the keystore and can locate it, it's due to how the service is being run. As a user can delegate (sudo) the execution of the process to ",(0,o.kt)("strong",{parentName:"p"},"root"),", the location of the keystore differs on runtime."),(0,o.kt)("p",null,"To learn more about how file permissions and ownership work, you're advised to read the reference document ",(0,o.kt)("a",{parentName:"p",href:"/references/Lightning%20CLI/file-permissions-and-ownership"},"here"),"."),(0,o.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}m.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>o});var r=n(7294);const o=e=>{let{image:t,name:n,title:o,url:a,communityMember:s=!1}=e;return r.createElement("section",{className:"author_card"},r.createElement("div",null,r.createElement("span",{className:"avatar"},r.createElement("a",{href:a,target:"_blank",alt:n},r.createElement("img",{src:t,alt:n}))),r.createElement("div",null,r.createElement("span",{className:"name"},r.createElement("a",{href:a,target:"_blank",alt:n},n)),r.createElement("span",{className:"title"},o),r.createElement("span",{className:"discord"},s?"Join our community on":"Got questions? Find us on"," ",r.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[4846],{3905:(e,t,n)=>{n.d(t,{Zo:()=>d,kt:()=>f});var r=n(7294);function o(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function a(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function s(e){for(var t=1;t=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=r.createContext({}),c=function(e){var t=r.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},d=function(e){var t=c(e.components);return r.createElement(l.Provider,{value:t},e.children)},p="mdxType",u={inlineCode:"code",wrapper:function(e){var t=e.children;return r.createElement(r.Fragment,{},t)}},m=r.forwardRef((function(e,t){var n=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,d=i(e,["components","mdxType","originalType","parentName"]),p=c(n),m=o,f=p["".concat(l,".").concat(m)]||p[m]||u[m]||a;return n?r.createElement(f,s(s({ref:t},d),{},{components:n})):r.createElement(f,s({ref:t},d))}));function f(e,t){var n=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=n.length,s=new Array(a);s[0]=m;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[p]="string"==typeof e?e:o,s[1]=i;for(var c=2;c{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>s,metadata:()=>l,toc:()=>d});var r=n(7462),o=(n(7294),n(3905)),a=n(3872);const s={title:"Keys not found",slug:"keys-not-found",hide_title:!0,tags:["keystore","lost keys","ownership","file permissions"]},i=void 0,l={unversionedId:"Lightning CLI/keys-not-found",id:"Lightning CLI/keys-not-found",title:"Keys not found",description:"Node key does not exist",source:"@site/references/Lightning CLI/keys-not-found.md",sourceDirName:"Lightning CLI",slug:"/Lightning CLI/keys-not-found",permalink:"/references/Lightning CLI/keys-not-found",draft:!1,editUrl:"https://github.com/fleek-network/fleek-network-docs/edit/main/references/Lightning CLI/keys-not-found.md",tags:[{label:"keystore",permalink:"/references/tags/keystore"},{label:"lost keys",permalink:"/references/tags/lost-keys"},{label:"ownership",permalink:"/references/tags/ownership"},{label:"file permissions",permalink:"/references/tags/file-permissions"}],version:"current",lastUpdatedAt:1694785242,formattedLastUpdatedAt:"Sep 15, 2023",frontMatter:{title:"Keys not found",slug:"keys-not-found",hide_title:!0,tags:["keystore","lost keys","ownership","file permissions"]},sidebar:"defaultSidebar",previous:{title:"File permissions and Ownership",permalink:"/references/Lightning CLI/file-permissions-and-ownership"},next:{title:"Backing up the keystore",permalink:"/references/Lightning CLI/backing-up-the-keystore"}},c={},d=[{value:"Node key does not exist",id:"node-key-does-not-exist",level:2}],p={toc:d},u="wrapper";function m(e){let{components:t,...n}=e;return(0,o.kt)(u,(0,r.Z)({},p,n,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("h2",{id:"node-key-does-not-exist"},"Node key does not exist"),(0,o.kt)("p",null,'When watching the Fleek Network Lightning service log output, you find the "Node key does not exist" message placed recursively. As follows:'),(0,o.kt)("pre",null,(0,o.kt)("code",{parentName:"pre",className:"language-sh"},"thread 'main' panicked at 'Node key does not exist. Use CLI to generate keys.', core/node/src/testnet_sync.rs:126:9\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\nthread 'main' panicked at 'Node key does not exist. Use CLI to generate keys.', core/node/src/testnet_sync.rs:126:9\nnote: run with `RUST_BACKTRACE=1` environment variable to display a backtrace\n")),(0,o.kt)("p",null,"If you haven't deleted the keystore and can locate it, it's due to how the service is being run. As a user can delegate (sudo) the execution of the process to ",(0,o.kt)("strong",{parentName:"p"},"root"),", the location of the keystore differs on runtime."),(0,o.kt)("p",null,"To learn more about how file permissions and ownership work, you're advised to read the reference document ",(0,o.kt)("a",{parentName:"p",href:"/references/Lightning%20CLI/file-permissions-and-ownership"},"here"),"."),(0,o.kt)(a.Z,{name:"Helder Oliveira",image:"https://github.com/heldrida.png",title:"Software Developer + DX",url:"https://github.com/heldrida",mdxType:"Author"}))}m.isMDXComponent=!0},3872:(e,t,n)=>{n.d(t,{Z:()=>o});var r=n(7294);const o=e=>{let{image:t,name:n,title:o,url:a,communityMember:s=!1}=e;return r.createElement("section",{className:"author_card"},r.createElement("div",null,r.createElement("span",{className:"avatar"},r.createElement("a",{href:a,target:"_blank",alt:n},r.createElement("img",{src:t,alt:n}))),r.createElement("div",null,r.createElement("span",{className:"name"},r.createElement("a",{href:a,target:"_blank",alt:n},n)),r.createElement("span",{className:"title"},o),r.createElement("span",{className:"discord"},s?"Join our community on":"Got questions? Find us on"," ",r.createElement("a",{href:"https://discord.gg/fleekxyz",target:"_blank"},"discord!")))))}}}]); \ No newline at end of file diff --git a/assets/js/main.83b58bcf.js b/assets/js/main.8779011a.js similarity index 98% rename from assets/js/main.83b58bcf.js rename to assets/js/main.8779011a.js index ae3d7c7c9..4d8399f92 100644 --- a/assets/js/main.83b58bcf.js +++ b/assets/js/main.8779011a.js @@ -1,2 +1,2 @@ -/*! For license information please see main.83b58bcf.js.LICENSE.txt */ -(self.webpackChunkdocta=self.webpackChunkdocta||[]).push([[179],{830:(e,t,n)=>{"use strict";n.d(t,{W:()=>a});var r=n(7294);function a(){return r.createElement("svg",{width:"20",height:"20",className:"DocSearch-Search-Icon",viewBox:"0 0 20 20"},r.createElement("path",{d:"M14.386 14.386l4.0877 4.0877-4.0877-4.0877c-2.9418 2.9419-7.7115 2.9419-10.6533 0-2.9419-2.9418-2.9419-7.7115 0-10.6533 2.9418-2.9419 7.7115-2.9419 10.6533 0 2.9419 2.9418 2.9419 7.7115 0 10.6533z",stroke:"currentColor",fill:"none",fillRule:"evenodd",strokeLinecap:"round",strokeLinejoin:"round"}))}},723:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});var r=n(7294),a=n(7462),o=n(8356),i=n.n(o),s=n(6887);const l={"00309d1b":[()=>n.e(9335).then(n.t.bind(n,5219,19)),"~docs/default/tag-docs-tags-fleek-network-206.json",5219],"01a85c17":[()=>Promise.all([n.e(532),n.e(4013)]).then(n.bind(n,4524)),"@theme/BlogTagsListPage",4524],"02f62b30":[()=>n.e(2170).then(n.t.bind(n,6037,19)),"/home/runner/work/fleek-network-docs/fleek-network-docs/.docusaurus/docusaurus-plugin-content-docs/guides/plugin-route-context-module-100.json",6037],"0359c679":[()=>n.e(7649).then(n.t.bind(n,8511,19)),"~docs/references/tag-references-tags-sudoer-94d.json",8511],"07f20919":[()=>n.e(4327).then(n.t.bind(n,6444,19)),"~docs/references/tag-references-tags-root-1d1.json",6444],"08dd5264":[()=>n.e(9267).then(n.t.bind(n,9692,19)),"~docs/default/tag-docs-tags-snarks-8e6.json",9692],"09ac38f0":[()=>n.e(3343).then(n.t.bind(n,4764,19)),"~docs/references/tag-references-tags-delete-f8c.json",4764],"0db90029":[()=>n.e(6174).then(n.t.bind(n,2392,19)),"~docs/default/tag-docs-tags-cryptoeconomics-50b.json",2392],"0dffb83e":[()=>n.e(5075).then(n.bind(n,3208)),"@site/docs/roadmap.md",3208],"0e3f509c":[()=>n.e(7154).then(n.bind(n,4102)),"@site/docs/Core/services.md",4102],"0ea1f268":[()=>n.e(663).then(n.t.bind(n,454,19)),"~docs/references/tag-references-tags-restore-2d4.json",454],"0fbdd4ac":[()=>n.e(8934).then(n.t.bind(n,8944,19)),"~docs/guides/tag-guides-tags-ownership-c29.json",8944],"143de299":[()=>n.e(8427).then(n.t.bind(n,9162,19)),"~docs/default/tag-docs-tags-algorithms-8a4.json",9162],"153c226b":[()=>n.e(7249).then(n.t.bind(n,9141,19)),"~docs/default/tag-docs-tags-compile-66b.json",9141],"155c1e74":[()=>n.e(747).then(n.t.bind(n,8095,19)),"~docs/references/tag-references-tags-reference-379.json",8095],17896441:[()=>Promise.all([n.e(532),n.e(8105),n.e(7918)]).then(n.bind(n,8945)),"@theme/DocItem",8945],"179183ba":[()=>n.e(6601).then(n.t.bind(n,655,19)),"~docs/default/tag-docs-tags-protocol-8a8.json",655],"187c6361":[()=>n.e(6788).then(n.t.bind(n,1461,19)),"~docs/default/tag-docs-tags-edge-network-189.json",1461],"1a4e3797":[()=>Promise.all([n.e(532),n.e(7920)]).then(n.bind(n,9172)),"@theme/SearchPage",9172],"1be78505":[()=>Promise.all([n.e(532),n.e(9514)]).then(n.bind(n,9963)),"@theme/DocPage",9963],"1c14429f":[()=>n.e(2702).then(n.bind(n,9587)),"@site/guides/Node Operators/getting-started-guide.md",9587],"1d8a5d15":[()=>n.e(9854).then(n.bind(n,469)),"@site/guides/Node Operators/transfering-setup-ownership.md",469],"1df93b7f":[()=>n.e(3237).then(n.bind(n,9754)),"@site/src/pages/index.tsx",9754],"21f2cabf":[()=>n.e(4537).then(n.t.bind(n,724,19)),"~docs/references/tag-references-tags-backup-7d5.json",724],"2218035b":[()=>n.e(4530).then(n.t.bind(n,3769,19)),"/home/runner/work/fleek-network-docs/fleek-network-docs/.docusaurus/docusaurus-plugin-content-docs/default/plugin-route-context-module-100.json",3769],"2730e145":[()=>n.e(7147).then(n.bind(n,9184)),"@site/references/Lightning CLI/permission-denied-os-error-13.md",9184],27528755:[()=>n.e(6926).then(n.t.bind(n,2578,19)),"~docs/references/tag-references-tags-uninstall-aa8.json",2578],"29b62a39":[()=>n.e(1498).then(n.bind(n,3129)),"@site/guides/index.md",3129],"29b83576":[()=>n.e(1510).then(n.bind(n,1409)),"@site/references/Lightning CLI/keystore-backup.md",1409],"2adfdcac":[()=>n.e(3189).then(n.t.bind(n,4723,19)),"~docs/default/tag-docs-tags-token-d9b.json",4723],"2baa5a9a":[()=>n.e(9021).then(n.t.bind(n,8704,19)),"~docs/guides/tag-guides-tags-configuration-48b.json",8704],"2e0a4d25":[()=>n.e(8132).then(n.t.bind(n,9073,19)),"~docs/references/tag-references-tags-systemctl-aa5.json",9073],"3290fbc2":[()=>n.e(2235).then(n.bind(n,1379)),"@site/docs/develop/client.md",1379],35230925:[()=>n.e(5602).then(n.bind(n,904)),"@site/docs/learn/developers.md",904],"35a7e2bf":[()=>n.e(4508).then(n.t.bind(n,8581,19)),"~docs/default/tag-docs-tags-contribute-7e0.json",8581],"3720c009":[()=>Promise.all([n.e(532),n.e(3751)]).then(n.bind(n,727)),"@theme/DocTagsListPage",727],"39574d2e":[()=>n.e(8747).then(n.t.bind(n,8270,19)),"~docs/default/tag-docs-tags-decentralization-674.json",8270],"399f21a8":[()=>n.e(2214).then(n.t.bind(n,2281,19)),"~docs/default/tag-docs-tags-rpc-9da.json",2281],"39e94577":[()=>n.e(1563).then(n.t.bind(n,3199,19)),"~docs/default/tag-docs-tags-build-2a2.json",3199],"3a6297ac":[()=>n.e(11).then(n.t.bind(n,2511,19)),"~docs/default/tag-docs-tags-sdk-70c.json",2511],"3b168dbd":[()=>n.e(469).then(n.t.bind(n,2832,19)),"~docs/guides/tag-guides-tags-edge-computing-c27.json",2832],"3f0cec70":[()=>n.e(9336).then(n.t.bind(n,4776,19)),"~docs/guides/tag-guides-tags-help-63e.json",4776],"3f3a03c1":[()=>n.e(4451).then(n.t.bind(n,1721,19)),"~blog/default/blog-tags-blog-476-list.json",1721],"3f90f51b":[()=>n.e(6669).then(n.bind(n,3726)),"@site/docs/learn/services.md",3726],"4035650f":[()=>n.e(2260).then(n.t.bind(n,9438,19)),"~blog/default/blog-tags-engineering-6ae.json",9438],"4061bfd3":[()=>n.e(3116).then(n.t.bind(n,7085,19)),"/home/runner/work/fleek-network-docs/fleek-network-docs/.docusaurus/docusaurus-theme-search-algolia/default/plugin-route-context-module-100.json",7085],"40aeb86f":[()=>n.e(4402).then(n.bind(n,1054)),"@site/references/Lightning CLI/update-cli-from-source-code.md",1054],"41bffad9":[()=>n.e(7948).then(n.bind(n,9287)),"@site/docs/learn/ports.md",9287],"4247aede":[()=>n.e(2800).then(n.t.bind(n,4948,19)),"~docs/default/tag-docs-tags-consensus-a3b.json",4948],"433ff3d6":[()=>n.e(555).then(n.t.bind(n,2787,19)),"~docs/default/tag-docs-tags-rewards-1bb.json",2787],"43ee1886":[()=>n.e(5466).then(n.t.bind(n,653,19)),"~docs/references/tag-references-tags-idle-b08.json",653],"44969bae":[()=>n.e(4063).then(n.bind(n,7159)),"@site/docs/node/requirements.md",7159],"45c86e35":[()=>n.e(9847).then(n.t.bind(n,2316,19)),"~docs/default/tag-docs-tags-about-3bc.json",2316],"45e1a117":[()=>n.e(6696).then(n.t.bind(n,5382,19)),"~docs/references/tag-references-tags-frozen-e7d.json",5382],"469c924f":[()=>n.e(2240).then(n.t.bind(n,342,19)),"~docs/default/tag-docs-tags-roadmap-bd4.json",342],"48857ff6":[()=>n.e(2908).then(n.t.bind(n,1014,19)),"~docs/default/tag-docs-tags-open-source-3c0.json",1014],"48e81e49":[()=>n.e(173).then(n.t.bind(n,5121,19)),"~docs/default/tag-docs-tags-incentives-3eb.json",5121],"49b5e83d":[()=>n.e(402).then(n.t.bind(n,3969,19)),"~docs/default/tag-docs-tags-manual-b97.json",3969],"4a821728":[()=>n.e(9513).then(n.t.bind(n,9748,19)),"~docs/default/tag-docs-tags-whitepaper-2ec.json",9748],"4ba7e5a3":[()=>n.e(9735).then(n.bind(n,5380)),"@site/docs/contribute.md",5380],"4beaa780":[()=>n.e(5081).then(n.t.bind(n,380,19)),"~docs/default/tag-docs-tags-reputation-c14.json",380],"4c027320":[()=>n.e(9511).then(n.t.bind(n,2564,19)),"~docs/guides/tag-guides-tags-getting-started-812.json",2564],"4d7007b2":[()=>n.e(6272).then(n.bind(n,5926)),"@site/references/index.md",5926],"4ecc0a29":[()=>n.e(5280).then(n.t.bind(n,9577,19)),"~docs/default/tag-docs-tags-development-ba6.json",9577],"50f02954":[()=>n.e(4826).then(n.t.bind(n,3900,19)),"~docs/references/tag-references-tags-systemd-aff.json",3900],"514cab6e":[()=>n.e(6410).then(n.bind(n,3474)),"@site/docs/Open-source/code-of-conduct.md",3474],"51d5b592":[()=>n.e(1984).then(n.bind(n,7183)),"@site/docs/node/install.md",7183],"51f2bfad":[()=>n.e(71).then(n.t.bind(n,3386,19)),"~docs/default/tag-docs-tags-server-240.json",3386],"53ca291c":[()=>n.e(3863).then(n.t.bind(n,4586,19)),"~docs/default/tag-docs-tags-economics-342.json",4586],"5437f376":[()=>n.e(909).then(n.bind(n,3529)),"@site/guides/Node Operators/managing-the-keystore.md",3529],"55960ee5":[()=>n.e(4121).then(n.t.bind(n,8070,19)),"~docs/default/tags-list-current-prop-15a.json",8070],"564044f9":[()=>n.e(1771).then(n.t.bind(n,4283,19)),"~docs/guides/tag-guides-tags-public-keys-1f7.json",4283],"581d5240":[()=>n.e(5318).then(n.bind(n,3941)),"@site/docs/node/health-check.md",3941],"5a9491fe":[()=>n.e(6476).then(n.t.bind(n,5751,19)),"~docs/guides/tag-guides-tags-keystore-6f8.json",5751],"5b6134d1":[()=>n.e(9752).then(n.bind(n,5852)),"@site/references/Lightning CLI/file-permissions-and-ownership.md",5852],"5d08f08d":[()=>n.e(659).then(n.t.bind(n,340,19)),"~docs/guides/tag-guides-tags-guide-f01.json",340],"5d38c936":[()=>n.e(9804).then(n.t.bind(n,9797,19)),"~docs/default/tag-docs-tags-rust-dependencies-0a8.json",9797],"5e9f5e1a":[()=>Promise.resolve().then(n.bind(n,6809)),"@generated/docusaurus.config",6809],"5ec90731":[()=>n.e(8942).then(n.t.bind(n,5440,19)),"~docs/guides/tag-guides-tags-transfer-246.json",5440],"5ef0bdde":[()=>n.e(8567).then(n.t.bind(n,7778,19)),"~blog/default/blog-tags-content-routing-b90.json",7778],"616ee580":[()=>n.e(4749).then(n.t.bind(n,5736,19)),"~docs/references/tag-references-tags-remove-c35.json",5736],"631037e5":[()=>n.e(801).then(n.t.bind(n,7064,19)),"~blog/default/blog-tags-blog-476.json",7064],"64d03520":[()=>n.e(1138).then(n.t.bind(n,2217,19)),"~docs/default/tag-docs-tags-requirements-a99.json",2217],"665f164c":[()=>n.e(9320).then(n.bind(n,2760)),"@site/docs/node/testnet-onboarding.md",2760],"6875c492":[()=>Promise.all([n.e(532),n.e(8105),n.e(6048),n.e(8610)]).then(n.bind(n,1714)),"@theme/BlogTagsPostsPage",1714],"68b99ecd":[()=>n.e(4556).then(n.t.bind(n,1407,19)),"~docs/default/tag-docs-tags-standards-f96.json",1407],"6be32138":[()=>n.e(3396).then(n.bind(n,8198)),"@site/blog/bloom-and-cuckoo-filters-for-cache-summarization.md",8198],"6cbb3cde":[()=>n.e(5136).then(n.t.bind(n,3860,19)),"~blog/default/blog-tags-engineering-6ae-list.json",3860],"6ccb158e":[()=>n.e(3218).then(n.t.bind(n,4391,19)),"~docs/references/tag-references-tags-keystore-d50.json",4391],"6e965365":[()=>n.e(4679).then(n.t.bind(n,8472,19)),"~docs/references/tag-references-tags-references-2ec.json",8472],"6f8964f3":[()=>n.e(7536).then(n.t.bind(n,9430,19)),"~docs/guides/tag-guides-tags-fleek-network-dce.json",9430],"719c0fd7":[()=>n.e(706).then(n.t.bind(n,6419,19)),"~docs/references/tag-references-tags-permissions-2fe.json",6419],"749619b5":[()=>n.e(6362).then(n.t.bind(n,5294,19)),"~docs/references/tag-references-tags-ownership-96b.json",5294],"74ec46b4":[()=>n.e(1263).then(n.t.bind(n,1337,19)),"~docs/default/tag-docs-tags-wizard-38b.json",1337],"763344b9":[()=>n.e(5094).then(n.t.bind(n,5772,19)),"~docs/default/tag-docs-tags-toolkit-735.json",5772],"779cc1e8":[()=>n.e(4).then(n.t.bind(n,761,19)),"~docs/references/tag-references-tags-update-c18.json",761],"7aba1839":[()=>n.e(554).then(n.t.bind(n,7177,19)),"~docs/default/tag-docs-tags-ports-99f.json",7177],"7b667a7f":[()=>n.e(5649).then(n.t.bind(n,5274,19)),"~docs/default/tag-docs-tags-git-514.json",5274],"7b788087":[()=>n.e(9062).then(n.t.bind(n,6149,19)),"~docs/guides/tag-guides-tags-keys-31a.json",6149],"7b9de75f":[()=>n.e(6353).then(n.t.bind(n,6378,19)),"~docs/default/tag-docs-tags-healthcheck-28a.json",6378],"7ddc4283":[()=>n.e(807).then(n.t.bind(n,5287,19)),"~docs/default/tag-docs-tags-contributing-315.json",5287],"814f3328":[()=>n.e(2535).then(n.t.bind(n,5641,19)),"~blog/default/blog-post-list-prop-default.json",5641],82893666:[()=>n.e(8005).then(n.t.bind(n,2220,19)),"~docs/default/tag-docs-tags-develop-1cf.json",2220],"8428fe34":[()=>n.e(5522).then(n.bind(n,6729)),"@site/docs/node/diagnostics.md",6729],"84cbd6c9":[()=>n.e(3336).then(n.t.bind(n,4793,19)),"~docs/guides/tags-list-current-prop-15a.json",4793],"84e08f43":[()=>n.e(8059).then(n.t.bind(n,3290,19)),"~docs/references/tag-references-tags-file-permissions-d5d.json",3290],"85d6e74d":[()=>n.e(4819).then(n.t.bind(n,5745,19)),"/home/runner/work/fleek-network-docs/fleek-network-docs/.docusaurus/docusaurus-plugin-content-pages/default/plugin-route-context-module-100.json",5745],"86c3bd1d":[()=>n.e(2421).then(n.t.bind(n,813,19)),"~docs/references/tag-references-tags-user-service-d6a.json",813],"8a92e787":[()=>n.e(2517).then(n.bind(n,2087)),"@site/references/Systemd/shutting-down-persistance.md",2087],"8cf21e85":[()=>n.e(6854).then(n.t.bind(n,90,19)),"~docs/default/tag-docs-tags-client-ceb.json",90],"8def2dd5":[()=>n.e(382).then(n.bind(n,8242)),"@site/docs/learn/index.md",8242],"8fe41007":[()=>n.e(1129).then(n.t.bind(n,9852,19)),"~docs/default/tag-docs-tags-snar-ks-885.json",9852],"90decb6d":[()=>n.e(9649).then(n.t.bind(n,2570,19)),"~docs/guides/tag-guides-tags-private-keys-b97.json",2570],"933a69d3":[()=>n.e(7813).then(n.t.bind(n,1853,19)),"~docs/default/tag-docs-tags-getting-started-980.json",1853],"935f2afb":[()=>n.e(53).then(n.t.bind(n,1109,19)),"~docs/default/version-current-metadata-prop-751.json",1109],"93df2695":[()=>n.e(2386).then(n.bind(n,1569)),"@site/docs/learn/delivery-acknowledgements.md",1569],"94e6476d":[()=>n.e(6223).then(n.bind(n,5290)),"@site/docs/learn/network.md",5290],"95f4d37c":[()=>n.e(814).then(n.bind(n,9553)),"@site/docs/develop/index.md",9553],"9bca08cf":[()=>n.e(8318).then(n.t.bind(n,7618,19)),"~docs/references/tag-references-tags-upgrade-b60.json",7618],"9bd69ffc":[()=>n.e(6699).then(n.t.bind(n,9790,19)),"~docs/default/tag-docs-tags-node-status-a43.json",9790],"9cc140f3":[()=>n.e(5049).then(n.t.bind(n,429,19)),"~docs/default/tag-docs-tags-repository-b8c.json",429],"9e4087bc":[()=>n.e(3608).then(n.bind(n,3169)),"@theme/BlogArchivePage",3169],"9f1c3232":[()=>n.e(373).then(n.bind(n,3477)),"@site/docs/node/index.md",3477],a13e0645:[()=>n.e(7136).then(n.t.bind(n,3120,19)),"~docs/default/tag-docs-tags-codebase-878.json",3120],a50e2e4f:[()=>n.e(7796).then(n.t.bind(n,2752,19)),"~docs/default/tag-docs-tags-awards-c13.json",2752],a6aa9e1f:[()=>Promise.all([n.e(532),n.e(8105),n.e(6048),n.e(3089)]).then(n.bind(n,3402)),"@theme/BlogListPage",3402],a7023ddc:[()=>n.e(1713).then(n.t.bind(n,3457,19)),"~blog/default/blog-tags-tags-4c2.json",3457],a9a76bf7:[()=>n.e(4356).then(n.t.bind(n,8826,19)),"~docs/default/tag-docs-tags-onboarding-2eb.json",8826],aa81941d:[()=>n.e(3012).then(n.t.bind(n,4350,19)),"~docs/default/tag-docs-tags-edge-platform-754.json",4350],af6a11bf:[()=>n.e(3503).then(n.t.bind(n,5296,19)),"~docs/references/tag-references-tags-help-9a8.json",5296],b02525a9:[()=>n.e(6980).then(n.t.bind(n,3993,19)),"~docs/guides/tag-guides-tags-guides-141.json",3993],b03a0ac1:[()=>n.e(4785).then(n.t.bind(n,2312,19)),"~docs/default/tag-docs-tags-cdn-fa9.json",2312],b2b675dd:[()=>n.e(533).then(n.t.bind(n,8017,19)),"~blog/default/blog-c06.json",8017],b2f554cd:[()=>n.e(1477).then(n.t.bind(n,10,19)),"~blog/default/blog-archive-80c.json",10],b35f1b7f:[()=>n.e(7706).then(n.bind(n,5733)),"@site/references/Systemd/user-service.md",5733],b40daf0f:[()=>n.e(2126).then(n.bind(n,6332)),"@site/docs/node/configuration.md",6332],b4f44b9b:[()=>n.e(551).then(n.t.bind(n,2960,19)),"/home/runner/work/fleek-network-docs/fleek-network-docs/.docusaurus/docusaurus-plugin-content-docs/references/plugin-route-context-module-100.json",2960],b5954e33:[()=>n.e(2114).then(n.bind(n,4692)),"@site/docs/learn/token-and-economics.md",4692],b696d13b:[()=>n.e(327).then(n.t.bind(n,5212,19)),"~docs/default/tag-docs-tags-verification-caa.json",5212],b8466c91:[()=>n.e(4939).then(n.t.bind(n,942,19)),"~docs/guides/tag-guides-tags-setup-8ad.json",942],b8c37621:[()=>n.e(920).then(n.t.bind(n,3908,19)),"~docs/default/tag-docs-tags-guide-a32.json",3908],bd59af11:[()=>n.e(9188).then(n.t.bind(n,7522,19)),"~docs/default/tag-docs-tags-diagnostics-265.json",7522],bea6e15b:[()=>n.e(8754).then(n.t.bind(n,815,19)),"~docs/references/tag-references-tags-fix-c13.json",815],c222de09:[()=>n.e(7563).then(n.bind(n,5534)),"@site/docs/whitepaper.md",5534],c377a04b:[()=>n.e(6971).then(n.bind(n,6453)),"@site/docs/index.md",6453],c3f5dd14:[()=>n.e(1345).then(n.t.bind(n,9826,19)),"~docs/references/tag-references-tags-clean-55b.json",9826],c7bd8086:[()=>n.e(441).then(n.bind(n,990)),"@site/docs/Core/edge-nodes.md",990],caaedc90:[()=>n.e(572).then(n.t.bind(n,8988,19)),"~docs/references/tag-references-tags-unit-0cd.json",8988],cc8e0b88:[()=>n.e(6310).then(n.t.bind(n,2560,19)),"~docs/default/tag-docs-tags-pledge-e5c.json",2560],cc9d5bf1:[()=>n.e(3236).then(n.t.bind(n,300,19)),"~blog/default/blog-tags-fleek-network-995-list.json",300],ccc49370:[()=>Promise.all([n.e(532),n.e(8105),n.e(6048),n.e(6103)]).then(n.bind(n,5203)),"@theme/BlogPostPage",5203],ce321ae3:[()=>n.e(1837).then(n.t.bind(n,2141,19)),"~docs/default/tag-docs-tags-configuration-143.json",2141],ce4635d7:[()=>n.e(9395).then(n.t.bind(n,6062,19)),"~docs/references/tag-references-tags-lost-keys-940.json",6062],d16f6fc6:[()=>n.e(5530).then(n.t.bind(n,8316,19)),"~docs/references/tag-references-tags-clear-34f.json",8316],d1b78a4d:[()=>n.e(3023).then(n.bind(n,1850)),"@site/blog/bloom-and-cuckoo-filters-for-cache-summarization.md?truncated=true",1850],d1d29319:[()=>n.e(2027).then(n.t.bind(n,9887,19)),"~docs/references/tag-references-tags-service-error-f6a.json",9887],d464210a:[()=>n.e(2023).then(n.t.bind(n,4075,19)),"~docs/default/tag-docs-tags-code-of-conduct-379.json",4075],d7d81bf6:[()=>n.e(2918).then(n.bind(n,9760)),"@site/references/Lightning CLI/error-building-on-arm64.md",9760],d8be0e5a:[()=>n.e(1706).then(n.bind(n,4458)),"@site/references/Lightning CLI/error-linking-with-cc-failed.md",4458],da002ab0:[()=>n.e(5888).then(n.t.bind(n,831,19)),"~blog/default/blog-tags-fleek-network-995.json",831],da8f35c6:[()=>n.e(4541).then(n.t.bind(n,4257,19)),"~blog/default/blog-tags-content-routing-b90-list.json",4257],dc2776f2:[()=>n.e(8644).then(n.bind(n,93)),"@site/docs/Open-source/repositories.md",93],df203c0f:[()=>n.e(9924).then(n.bind(n,491)),"@theme/DocTagDocListPage",491],e10957d6:[()=>n.e(4708).then(n.t.bind(n,4469,19)),"/home/runner/work/fleek-network-docs/fleek-network-docs/.docusaurus/docusaurus-plugin-content-blog/default/plugin-route-context-module-100.json",4469],e1f64676:[()=>n.e(3120).then(n.bind(n,1933)),"@site/references/Lightning CLI/uninstall-lightning-cli.md",1933],e26f0bf0:[()=>n.e(4534).then(n.bind(n,757)),"@site/docs/Core/developers.md",757],e331fbd7:[()=>n.e(9995).then(n.t.bind(n,7568,19)),"~docs/default/tag-docs-tags-permissionless-576.json",7568],ec98ad91:[()=>n.e(4034).then(n.t.bind(n,1323,19)),"~docs/default/tag-docs-tags-testnet-9cf.json",1323],ecfddbd4:[()=>n.e(7804).then(n.bind(n,3317)),"@site/docs/Open-source.md",3317],f02c0d6e:[()=>n.e(3707).then(n.t.bind(n,3422,19)),"~docs/default/tag-docs-tags-tokenomics-43c.json",3422],f3d7f34e:[()=>n.e(982).then(n.t.bind(n,9299,19)),"~docs/references/version-current-metadata-prop-751.json",9299],f3f8ecb0:[()=>n.e(6939).then(n.bind(n,2854)),"@site/docs/develop/service-development.md",2854],f4fd4511:[()=>n.e(6461).then(n.t.bind(n,6514,19)),"~docs/default/tag-docs-tags-phases-f9f.json",6514],f50a4147:[()=>n.e(4888).then(n.bind(n,260)),"@site/docs/Open-source/contributing.md",260],f6807fb4:[()=>n.e(4788).then(n.t.bind(n,9836,19)),"~docs/default/tag-docs-tags-architecture-68d.json",9836],f6a16de6:[()=>n.e(4371).then(n.t.bind(n,5293,19)),"~docs/default/tag-docs-tags-contributor-267.json",5293],f9537533:[()=>n.e(5347).then(n.t.bind(n,881,19)),"~docs/references/tags-list-current-prop-15a.json",881],fa69a7f4:[()=>n.e(6798).then(n.t.bind(n,2469,19)),"~docs/guides/version-current-metadata-prop-751.json",2469],fa7546af:[()=>n.e(1611).then(n.t.bind(n,7327,19)),"~docs/references/tag-references-tags-shutdown-0e6.json",7327],fcc63351:[()=>n.e(9743).then(n.t.bind(n,7495,19)),"~docs/default/tag-docs-tags-services-754.json",7495],fd2b74dc:[()=>n.e(4846).then(n.bind(n,6578)),"@site/references/Lightning CLI/keys-not-found.md",6578],ff80750d:[()=>n.e(2931).then(n.t.bind(n,8807,19)),"~docs/default/tag-docs-tags-repositories-c88.json",8807],ffc337e7:[()=>n.e(7310).then(n.t.bind(n,2110,19)),"~docs/default/tag-docs-tags-learn-579.json",2110],ffcb1b32:[()=>n.e(5120).then(n.bind(n,8730)),"@site/docs/develop/json-rpc.md",8730]};function c(e){let{error:t,retry:n,pastDelay:a}=e;return t?r.createElement("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"}},r.createElement("p",null,String(t)),r.createElement("div",null,r.createElement("button",{type:"button",onClick:n},"Retry"))):a?r.createElement("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"}},r.createElement("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb"},r.createElement("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2"},r.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},r.createElement("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),r.createElement("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0"},r.createElement("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),r.createElement("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})),r.createElement("circle",{cx:"22",cy:"22",r:"8"},r.createElement("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"}))))):null}var u=n(9670),d=n(226);function f(e,t){if("*"===e)return i()({loading:c,loader:()=>n.e(4972).then(n.bind(n,4972)),modules:["@theme/NotFound"],webpack:()=>[4972],render(e,t){const n=e.default;return r.createElement(d.z,{value:{plugin:{name:"native",id:"default"}}},r.createElement(n,t))}});const o=s[`${e}-${t}`],f={},p=[],g=[],m=(0,u.Z)(o);return Object.entries(m).forEach((e=>{let[t,n]=e;const r=l[n];r&&(f[t]=r[0],p.push(r[1]),g.push(r[2]))})),i().Map({loading:c,loader:f,modules:p,webpack:()=>g,render(t,n){const i=JSON.parse(JSON.stringify(o));Object.entries(t).forEach((t=>{let[n,r]=t;const a=r.default;if(!a)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof a&&"function"!=typeof a||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{a[e]=r[e]}));let o=i;const s=n.split(".");s.slice(0,-1).forEach((e=>{o=o[e]})),o[s[s.length-1]]=a}));const s=i.__comp;delete i.__comp;const l=i.__context;return delete i.__context,r.createElement(d.z,{value:l},r.createElement(s,(0,a.Z)({},i,n)))}})}const p=[{path:"/blog/",component:f("/blog/","951"),exact:!0},{path:"/blog/archive/",component:f("/blog/archive/","d54"),exact:!0},{path:"/blog/bloom-and-cuckoo-filters-for-cache-summarization/",component:f("/blog/bloom-and-cuckoo-filters-for-cache-summarization/","5a5"),exact:!0},{path:"/blog/tags/",component:f("/blog/tags/","f8d"),exact:!0},{path:"/blog/tags/blog/",component:f("/blog/tags/blog/","dc0"),exact:!0},{path:"/blog/tags/content-routing/",component:f("/blog/tags/content-routing/","f84"),exact:!0},{path:"/blog/tags/engineering/",component:f("/blog/tags/engineering/","6c6"),exact:!0},{path:"/blog/tags/fleek-network/",component:f("/blog/tags/fleek-network/","490"),exact:!0},{path:"/docs/tags/",component:f("/docs/tags/","070"),exact:!0},{path:"/docs/tags/about/",component:f("/docs/tags/about/","dcd"),exact:!0},{path:"/docs/tags/algorithms/",component:f("/docs/tags/algorithms/","cf8"),exact:!0},{path:"/docs/tags/architecture/",component:f("/docs/tags/architecture/","4de"),exact:!0},{path:"/docs/tags/awards/",component:f("/docs/tags/awards/","ef9"),exact:!0},{path:"/docs/tags/build/",component:f("/docs/tags/build/","cb8"),exact:!0},{path:"/docs/tags/cdn/",component:f("/docs/tags/cdn/","f22"),exact:!0},{path:"/docs/tags/client/",component:f("/docs/tags/client/","e82"),exact:!0},{path:"/docs/tags/code-of-conduct/",component:f("/docs/tags/code-of-conduct/","574"),exact:!0},{path:"/docs/tags/codebase/",component:f("/docs/tags/codebase/","73d"),exact:!0},{path:"/docs/tags/compile/",component:f("/docs/tags/compile/","610"),exact:!0},{path:"/docs/tags/configuration/",component:f("/docs/tags/configuration/","2ee"),exact:!0},{path:"/docs/tags/consensus/",component:f("/docs/tags/consensus/","f81"),exact:!0},{path:"/docs/tags/contribute/",component:f("/docs/tags/contribute/","daa"),exact:!0},{path:"/docs/tags/contributing/",component:f("/docs/tags/contributing/","78f"),exact:!0},{path:"/docs/tags/contributor/",component:f("/docs/tags/contributor/","f8e"),exact:!0},{path:"/docs/tags/cryptoeconomics/",component:f("/docs/tags/cryptoeconomics/","841"),exact:!0},{path:"/docs/tags/decentralization/",component:f("/docs/tags/decentralization/","d8a"),exact:!0},{path:"/docs/tags/develop/",component:f("/docs/tags/develop/","df2"),exact:!0},{path:"/docs/tags/development/",component:f("/docs/tags/development/","549"),exact:!0},{path:"/docs/tags/diagnostics/",component:f("/docs/tags/diagnostics/","354"),exact:!0},{path:"/docs/tags/economics/",component:f("/docs/tags/economics/","35c"),exact:!0},{path:"/docs/tags/edge-network/",component:f("/docs/tags/edge-network/","9a2"),exact:!0},{path:"/docs/tags/edge-platform/",component:f("/docs/tags/edge-platform/","3ff"),exact:!0},{path:"/docs/tags/fleek-network/",component:f("/docs/tags/fleek-network/","ed7"),exact:!0},{path:"/docs/tags/getting-started/",component:f("/docs/tags/getting-started/","5c5"),exact:!0},{path:"/docs/tags/git/",component:f("/docs/tags/git/","36d"),exact:!0},{path:"/docs/tags/guide/",component:f("/docs/tags/guide/","cdc"),exact:!0},{path:"/docs/tags/healthcheck/",component:f("/docs/tags/healthcheck/","b81"),exact:!0},{path:"/docs/tags/incentives/",component:f("/docs/tags/incentives/","8ff"),exact:!0},{path:"/docs/tags/learn/",component:f("/docs/tags/learn/","e71"),exact:!0},{path:"/docs/tags/manual/",component:f("/docs/tags/manual/","02d"),exact:!0},{path:"/docs/tags/node-status/",component:f("/docs/tags/node-status/","5b1"),exact:!0},{path:"/docs/tags/onboarding/",component:f("/docs/tags/onboarding/","140"),exact:!0},{path:"/docs/tags/open-source/",component:f("/docs/tags/open-source/","864"),exact:!0},{path:"/docs/tags/permissionless/",component:f("/docs/tags/permissionless/","86e"),exact:!0},{path:"/docs/tags/phases/",component:f("/docs/tags/phases/","743"),exact:!0},{path:"/docs/tags/pledge/",component:f("/docs/tags/pledge/","ec7"),exact:!0},{path:"/docs/tags/ports/",component:f("/docs/tags/ports/","fad"),exact:!0},{path:"/docs/tags/protocol/",component:f("/docs/tags/protocol/","5c7"),exact:!0},{path:"/docs/tags/repositories/",component:f("/docs/tags/repositories/","ba6"),exact:!0},{path:"/docs/tags/repository/",component:f("/docs/tags/repository/","835"),exact:!0},{path:"/docs/tags/reputation/",component:f("/docs/tags/reputation/","013"),exact:!0},{path:"/docs/tags/requirements/",component:f("/docs/tags/requirements/","7cb"),exact:!0},{path:"/docs/tags/rewards/",component:f("/docs/tags/rewards/","80e"),exact:!0},{path:"/docs/tags/roadmap/",component:f("/docs/tags/roadmap/","d25"),exact:!0},{path:"/docs/tags/rpc/",component:f("/docs/tags/rpc/","f75"),exact:!0},{path:"/docs/tags/rust-dependencies/",component:f("/docs/tags/rust-dependencies/","a0f"),exact:!0},{path:"/docs/tags/sdk/",component:f("/docs/tags/sdk/","b2b"),exact:!0},{path:"/docs/tags/server/",component:f("/docs/tags/server/","534"),exact:!0},{path:"/docs/tags/services/",component:f("/docs/tags/services/","f12"),exact:!0},{path:"/docs/tags/snar-ks/",component:f("/docs/tags/snar-ks/","4fa"),exact:!0},{path:"/docs/tags/snarks/",component:f("/docs/tags/snarks/","933"),exact:!0},{path:"/docs/tags/standards/",component:f("/docs/tags/standards/","440"),exact:!0},{path:"/docs/tags/testnet/",component:f("/docs/tags/testnet/","bc6"),exact:!0},{path:"/docs/tags/token/",component:f("/docs/tags/token/","e7b"),exact:!0},{path:"/docs/tags/tokenomics/",component:f("/docs/tags/tokenomics/","2b9"),exact:!0},{path:"/docs/tags/toolkit/",component:f("/docs/tags/toolkit/","e12"),exact:!0},{path:"/docs/tags/verification/",component:f("/docs/tags/verification/","c34"),exact:!0},{path:"/docs/tags/whitepaper/",component:f("/docs/tags/whitepaper/","798"),exact:!0},{path:"/docs/tags/wizard/",component:f("/docs/tags/wizard/","2b1"),exact:!0},{path:"/guides/tags/",component:f("/guides/tags/","f51"),exact:!0},{path:"/guides/tags/configuration/",component:f("/guides/tags/configuration/","84f"),exact:!0},{path:"/guides/tags/edge-computing/",component:f("/guides/tags/edge-computing/","cc1"),exact:!0},{path:"/guides/tags/fleek-network/",component:f("/guides/tags/fleek-network/","c44"),exact:!0},{path:"/guides/tags/getting-started/",component:f("/guides/tags/getting-started/","d87"),exact:!0},{path:"/guides/tags/guide/",component:f("/guides/tags/guide/","3ed"),exact:!0},{path:"/guides/tags/guides/",component:f("/guides/tags/guides/","597"),exact:!0},{path:"/guides/tags/help/",component:f("/guides/tags/help/","903"),exact:!0},{path:"/guides/tags/keys/",component:f("/guides/tags/keys/","035"),exact:!0},{path:"/guides/tags/keystore/",component:f("/guides/tags/keystore/","b73"),exact:!0},{path:"/guides/tags/ownership/",component:f("/guides/tags/ownership/","599"),exact:!0},{path:"/guides/tags/private-keys/",component:f("/guides/tags/private-keys/","91d"),exact:!0},{path:"/guides/tags/public-keys/",component:f("/guides/tags/public-keys/","e31"),exact:!0},{path:"/guides/tags/setup/",component:f("/guides/tags/setup/","cc1"),exact:!0},{path:"/guides/tags/transfer/",component:f("/guides/tags/transfer/","e54"),exact:!0},{path:"/references/tags/",component:f("/references/tags/","bb6"),exact:!0},{path:"/references/tags/backup/",component:f("/references/tags/backup/","738"),exact:!0},{path:"/references/tags/clean/",component:f("/references/tags/clean/","84f"),exact:!0},{path:"/references/tags/clear/",component:f("/references/tags/clear/","2a0"),exact:!0},{path:"/references/tags/delete/",component:f("/references/tags/delete/","0a8"),exact:!0},{path:"/references/tags/file-permissions/",component:f("/references/tags/file-permissions/","f21"),exact:!0},{path:"/references/tags/fix/",component:f("/references/tags/fix/","ae4"),exact:!0},{path:"/references/tags/frozen/",component:f("/references/tags/frozen/","b33"),exact:!0},{path:"/references/tags/help/",component:f("/references/tags/help/","46c"),exact:!0},{path:"/references/tags/idle/",component:f("/references/tags/idle/","d4a"),exact:!0},{path:"/references/tags/keystore/",component:f("/references/tags/keystore/","160"),exact:!0},{path:"/references/tags/lost-keys/",component:f("/references/tags/lost-keys/","60c"),exact:!0},{path:"/references/tags/ownership/",component:f("/references/tags/ownership/","58e"),exact:!0},{path:"/references/tags/permissions/",component:f("/references/tags/permissions/","34d"),exact:!0},{path:"/references/tags/reference/",component:f("/references/tags/reference/","b27"),exact:!0},{path:"/references/tags/references/",component:f("/references/tags/references/","91e"),exact:!0},{path:"/references/tags/remove/",component:f("/references/tags/remove/","b0b"),exact:!0},{path:"/references/tags/restore/",component:f("/references/tags/restore/","80d"),exact:!0},{path:"/references/tags/root/",component:f("/references/tags/root/","9c4"),exact:!0},{path:"/references/tags/service-error/",component:f("/references/tags/service-error/","8d0"),exact:!0},{path:"/references/tags/shutdown/",component:f("/references/tags/shutdown/","193"),exact:!0},{path:"/references/tags/sudoer/",component:f("/references/tags/sudoer/","09d"),exact:!0},{path:"/references/tags/systemctl/",component:f("/references/tags/systemctl/","cdc"),exact:!0},{path:"/references/tags/systemd/",component:f("/references/tags/systemd/","0be"),exact:!0},{path:"/references/tags/uninstall/",component:f("/references/tags/uninstall/","019"),exact:!0},{path:"/references/tags/unit/",component:f("/references/tags/unit/","20e"),exact:!0},{path:"/references/tags/update/",component:f("/references/tags/update/","192"),exact:!0},{path:"/references/tags/upgrade/",component:f("/references/tags/upgrade/","ee8"),exact:!0},{path:"/references/tags/user-service/",component:f("/references/tags/user-service/","170"),exact:!0},{path:"/search/",component:f("/search/","2a3"),exact:!0},{path:"/docs/",component:f("/docs/","3c3"),routes:[{path:"/docs/",component:f("/docs/","e7a"),exact:!0,sidebar:"docs"},{path:"/docs/contribute/",component:f("/docs/contribute/","036"),exact:!0},{path:"/docs/Core/developers/",component:f("/docs/Core/developers/","9da"),exact:!0},{path:"/docs/Core/edge-nodes/",component:f("/docs/Core/edge-nodes/","326"),exact:!0},{path:"/docs/Core/services/",component:f("/docs/Core/services/","a77"),exact:!0},{path:"/docs/develop/client/",component:f("/docs/develop/client/","720"),exact:!0},{path:"/docs/develop/json-rpc/",component:f("/docs/develop/json-rpc/","3b0"),exact:!0},{path:"/docs/develop/overview/",component:f("/docs/develop/overview/","4ab"),exact:!0},{path:"/docs/develop/service-development/",component:f("/docs/develop/service-development/","a0d"),exact:!0},{path:"/docs/learn/delivery-acknowledgements/",component:f("/docs/learn/delivery-acknowledgements/","76f"),exact:!0,sidebar:"docs"},{path:"/docs/learn/developers/",component:f("/docs/learn/developers/","a5d"),exact:!0,sidebar:"docs"},{path:"/docs/learn/introduction/",component:f("/docs/learn/introduction/","0c9"),exact:!0,sidebar:"docs"},{path:"/docs/learn/ports/",component:f("/docs/learn/ports/","4c8"),exact:!0},{path:"/docs/learn/services/",component:f("/docs/learn/services/","095"),exact:!0,sidebar:"docs"},{path:"/docs/learn/the-network/",component:f("/docs/learn/the-network/","fe1"),exact:!0,sidebar:"docs"},{path:"/docs/learn/token-and-economics/",component:f("/docs/learn/token-and-economics/","ede"),exact:!0,sidebar:"docs"},{path:"/docs/node/configuration/",component:f("/docs/node/configuration/","191"),exact:!0},{path:"/docs/node/diagnostics/",component:f("/docs/node/diagnostics/","83b"),exact:!0},{path:"/docs/node/health-check/",component:f("/docs/node/health-check/","59e"),exact:!0,sidebar:"docs"},{path:"/docs/node/Install/",component:f("/docs/node/Install/","806"),exact:!0,sidebar:"docs"},{path:"/docs/node/overview/",component:f("/docs/node/overview/","603"),exact:!0,sidebar:"docs"},{path:"/docs/node/requirements/",component:f("/docs/node/requirements/","8ae"),exact:!0,sidebar:"docs"},{path:"/docs/node/testnet-onboarding/",component:f("/docs/node/testnet-onboarding/","2f1"),exact:!0,sidebar:"docs"},{path:"/docs/Open-source/",component:f("/docs/Open-source/","81b"),exact:!0},{path:"/docs/Open-source/code-of-conduct/",component:f("/docs/Open-source/code-of-conduct/","ff8"),exact:!0,sidebar:"docs"},{path:"/docs/Open-source/contributing/",component:f("/docs/Open-source/contributing/","27e"),exact:!0,sidebar:"docs"},{path:"/docs/Open-source/repositories/",component:f("/docs/Open-source/repositories/","93e"),exact:!0,sidebar:"docs"},{path:"/docs/roadmap/",component:f("/docs/roadmap/","532"),exact:!0,sidebar:"docs"},{path:"/docs/whitepaper/",component:f("/docs/whitepaper/","d8d"),exact:!0,sidebar:"docs"}]},{path:"/guides/",component:f("/guides/","78e"),routes:[{path:"/guides/",component:f("/guides/","ef7"),exact:!0,sidebar:"defaultSidebar"},{path:"/guides/Node Operators/getting-started/",component:f("/guides/Node Operators/getting-started/","a1f"),exact:!0,sidebar:"defaultSidebar"},{path:"/guides/Node Operators/managing-the-keystore/",component:f("/guides/Node Operators/managing-the-keystore/","176"),exact:!0,sidebar:"defaultSidebar"},{path:"/guides/Node Operators/transfering-setup-ownership/",component:f("/guides/Node Operators/transfering-setup-ownership/","2d8"),exact:!0,sidebar:"defaultSidebar"}]},{path:"/references/",component:f("/references/","9b6"),routes:[{path:"/references/",component:f("/references/","418"),exact:!0,sidebar:"defaultSidebar"},{path:"/references/Lightning CLI/backing-up-the-keystore/",component:f("/references/Lightning CLI/backing-up-the-keystore/","4c3"),exact:!0,sidebar:"defaultSidebar"},{path:"/references/Lightning CLI/error-building-on-arm64/",component:f("/references/Lightning CLI/error-building-on-arm64/","cb1"),exact:!0,sidebar:"defaultSidebar"},{path:"/references/Lightning CLI/error-linking-with-cc-failed-exist-status-1/",component:f("/references/Lightning CLI/error-linking-with-cc-failed-exist-status-1/","bb4"),exact:!0,sidebar:"defaultSidebar"},{path:"/references/Lightning CLI/file-permissions-and-ownership/",component:f("/references/Lightning CLI/file-permissions-and-ownership/","974"),exact:!0,sidebar:"defaultSidebar"},{path:"/references/Lightning CLI/keys-not-found/",component:f("/references/Lightning CLI/keys-not-found/","45f"),exact:!0,sidebar:"defaultSidebar"},{path:"/references/Lightning CLI/permission-denied-os-error-13/",component:f("/references/Lightning CLI/permission-denied-os-error-13/","eed"),exact:!0,sidebar:"defaultSidebar"},{path:"/references/Lightning CLI/uninstall-lightning-cli/",component:f("/references/Lightning CLI/uninstall-lightning-cli/","d12"),exact:!0,sidebar:"defaultSidebar"},{path:"/references/Lightning CLI/update-cli-from-source-code/",component:f("/references/Lightning CLI/update-cli-from-source-code/","6a3"),exact:!0,sidebar:"defaultSidebar"},{path:"/references/Systemd/shutting-down-persistance/",component:f("/references/Systemd/shutting-down-persistance/","27f"),exact:!0,sidebar:"defaultSidebar"},{path:"/references/Systemd/user-service/",component:f("/references/Systemd/user-service/","9d7"),exact:!0,sidebar:"defaultSidebar"}]},{path:"/",component:f("/","a33"),exact:!0},{path:"*",component:f("*")}]},8934:(e,t,n)=>{"use strict";n.d(t,{_:()=>a,t:()=>o});var r=n(7294);const a=r.createContext(!1);function o(e){let{children:t}=e;const[n,o]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{o(!0)}),[]),r.createElement(a.Provider,{value:n},t)}},9383:(e,t,n)=>{"use strict";var r=n(7294),a=n(3935),o=n(3727),i=n(405),s=n(412);const l=[n(2497),n(3310),n(8320),n(2295)];var c=n(723),u=n(6550),d=n(8790);function f(e){let{children:t}=e;return r.createElement(r.Fragment,null,t)}var p=n(7462),g=n(5742),m=n(2263),h=n(4996),b=n(6668),v=n(833),y=n(4711),w=n(9727),k=n(3320),E=n(197);function _(){const{i18n:{defaultLocale:e,localeConfigs:t}}=(0,m.Z)(),n=(0,y.l)();return r.createElement(g.Z,null,Object.entries(t).map((e=>{let[t,{htmlLang:a}]=e;return r.createElement("link",{key:t,rel:"alternate",href:n.createUrl({locale:t,fullyQualified:!0}),hrefLang:a})})),r.createElement("link",{rel:"alternate",href:n.createUrl({locale:e,fullyQualified:!0}),hrefLang:"x-default"}))}function S(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,m.Z)(),a=function(){const{siteConfig:{url:e}}=(0,m.Z)(),{pathname:t}=(0,u.TH)();return e+(0,h.Z)(t)}(),o=t?`${n}${t}`:a;return r.createElement(g.Z,null,r.createElement("meta",{property:"og:url",content:o}),r.createElement("link",{rel:"canonical",href:o}))}function x(){const{i18n:{currentLocale:e}}=(0,m.Z)(),{metadata:t,image:n}=(0,b.L)();return r.createElement(r.Fragment,null,r.createElement(g.Z,null,r.createElement("meta",{name:"twitter:card",content:"summary_large_image"}),r.createElement("body",{className:w.h})),n&&r.createElement(v.d,{image:n}),r.createElement(S,null),r.createElement(_,null),r.createElement(E.Z,{tag:k.HX,locale:e}),r.createElement(g.Z,null,t.map(((e,t)=>r.createElement("meta",(0,p.Z)({key:t},e))))))}const C=new Map;function T(e){if(C.has(e.pathname))return{...e,pathname:C.get(e.pathname)};if((0,d.f)(c.Z,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return C.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return C.set(e.pathname,t),{...e,pathname:t}}var L=n(8934),A=n(8940);function R(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r{const r=t.default?.[e]??t[e];return r?.(...n)}));return()=>a.forEach((e=>e?.()))}const O=function(e){let{children:t,location:n,previousLocation:a}=e;return(0,r.useLayoutEffect)((()=>{a!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,a=t.hash===n.hash,o=t.search===n.search;if(r&&a&&!o)return;const{hash:i}=t;if(i){const e=decodeURIComponent(i.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:a}),R("onRouteDidUpdate",{previousLocation:a,location:n}))}),[a,n]),t};function N(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.f)(c.Z,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class P extends r.Component{constructor(e){super(e),this.previousLocation=void 0,this.routeUpdateCleanupCb=void 0,this.previousLocation=null,this.routeUpdateCleanupCb=s.Z.canUseDOM?R("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=R("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),N(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return r.createElement(O,{previousLocation:this.previousLocation,location:t},r.createElement(u.AW,{location:t,render:()=>e}))}}const I=P,D="__docusaurus-base-url-issue-banner-container",M="__docusaurus-base-url-issue-banner",j="__docusaurus-base-url-issue-banner-suggestion-container",F="__DOCUSAURUS_INSERT_BASEURL_BANNER";function B(e){return`\nwindow['${F}'] = true;\n\ndocument.addEventListener('DOMContentLoaded', maybeInsertBanner);\n\nfunction maybeInsertBanner() {\n var shouldInsert = window['${F}'];\n shouldInsert && insertBanner();\n}\n\nfunction insertBanner() {\n var bannerContainer = document.getElementById('${D}');\n if (!bannerContainer) {\n return;\n }\n var bannerHtml = ${JSON.stringify(function(e){return`\n
\n

Your Docusaurus site did not load properly.

\n

A very common reason is a wrong site baseUrl configuration.

\n

Current configured baseUrl = ${e} ${"/"===e?" (default value)":""}

\n

We suggest trying baseUrl =

\n
\n`}(e)).replace(/{window[F]=!1}),[]),r.createElement(r.Fragment,null,!s.Z.canUseDOM&&r.createElement(g.Z,null,r.createElement("script",null,B(e))),r.createElement("div",{id:D}))}function U(){const{siteConfig:{baseUrl:e,baseUrlIssueBanner:t}}=(0,m.Z)(),{pathname:n}=(0,u.TH)();return t&&n===e?r.createElement(z,null):null}function $(){const{siteConfig:{favicon:e,title:t,noIndex:n},i18n:{currentLocale:a,localeConfigs:o}}=(0,m.Z)(),i=(0,h.Z)(e),{htmlLang:s,direction:l}=o[a];return r.createElement(g.Z,null,r.createElement("html",{lang:s,dir:l}),r.createElement("title",null,t),r.createElement("meta",{property:"og:title",content:t}),r.createElement("meta",{name:"viewport",content:"width=device-width, initial-scale=1.0"}),n&&r.createElement("meta",{name:"robots",content:"noindex, nofollow"}),e&&r.createElement("link",{rel:"icon",href:i}))}var q=n(4763);function H(){const e=(0,d.H)(c.Z),t=(0,u.TH)();return r.createElement(q.Z,null,r.createElement(A.M,null,r.createElement(L.t,null,r.createElement(f,null,r.createElement($,null),r.createElement(x,null),r.createElement(U,null),r.createElement(I,{location:T(t)},e)))))}var G=n(6887);const Z=function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise(((t,n)=>{if("undefined"==typeof document)return void n();const r=document.createElement("link");r.setAttribute("rel","prefetch"),r.setAttribute("href",e),r.onload=()=>t(),r.onerror=()=>n();const a=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;a?.appendChild(r)}))}:function(e){return new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)}))};var V=n(9670);const W=new Set,K=new Set,Y=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,Q={prefetch(e){if(!(e=>!Y()&&!K.has(e)&&!W.has(e))(e))return!1;W.add(e);const t=(0,d.f)(c.Z,e).flatMap((e=>{return t=e.route.path,Object.entries(G).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,V.Z)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?Z(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!Y()&&!K.has(e))(e)&&(K.add(e),N(e))},X=Object.freeze(Q);if(s.Z.canUseDOM){window.docusaurus=X;const e=a.hydrate;N(window.location.pathname).then((()=>{e(r.createElement(i.B6,null,r.createElement(o.VK,null,r.createElement(H,null))),document.getElementById("__docusaurus"))}))}},8940:(e,t,n)=>{"use strict";n.d(t,{_:()=>u,M:()=>d});var r=n(7294),a=n(6809);const o=JSON.parse('{"docusaurus-plugin-google-tag-manager":{"default":{"containerId":"GTM-PC422SF","id":"default"}},"docusaurus-plugin-content-docs":{"guides":{"path":"/guides","versions":[{"name":"current","label":"Next","isLast":true,"path":"/guides","mainDocId":"index","docs":[{"id":"index","path":"/guides/","sidebar":"defaultSidebar"},{"id":"Node Operators/getting-started-guide","path":"/guides/Node Operators/getting-started","sidebar":"defaultSidebar"},{"id":"Node Operators/managing-the-keystore","path":"/guides/Node Operators/managing-the-keystore","sidebar":"defaultSidebar"},{"id":"Node Operators/transfering-setup-ownership","path":"/guides/Node Operators/transfering-setup-ownership","sidebar":"defaultSidebar"}],"draftIds":[],"sidebars":{"defaultSidebar":{"link":{"path":"/guides/","label":"index"}}}}],"breadcrumbs":false},"references":{"path":"/references","versions":[{"name":"current","label":"Next","isLast":true,"path":"/references","mainDocId":"index","docs":[{"id":"index","path":"/references/","sidebar":"defaultSidebar"},{"id":"Lightning CLI/error-building-on-arm64","path":"/references/Lightning CLI/error-building-on-arm64","sidebar":"defaultSidebar"},{"id":"Lightning CLI/error-linking-with-cc-failed","path":"/references/Lightning CLI/error-linking-with-cc-failed-exist-status-1","sidebar":"defaultSidebar"},{"id":"Lightning CLI/file-permissions-and-ownership","path":"/references/Lightning CLI/file-permissions-and-ownership","sidebar":"defaultSidebar"},{"id":"Lightning CLI/keys-not-found","path":"/references/Lightning CLI/keys-not-found","sidebar":"defaultSidebar"},{"id":"Lightning CLI/keystore-backup","path":"/references/Lightning CLI/backing-up-the-keystore","sidebar":"defaultSidebar"},{"id":"Lightning CLI/permission-denied-os-error-13","path":"/references/Lightning CLI/permission-denied-os-error-13","sidebar":"defaultSidebar"},{"id":"Lightning CLI/uninstall-lightning-cli","path":"/references/Lightning CLI/uninstall-lightning-cli","sidebar":"defaultSidebar"},{"id":"Lightning CLI/update-cli-from-source-code","path":"/references/Lightning CLI/update-cli-from-source-code","sidebar":"defaultSidebar"},{"id":"Systemd/shutting-down-persistance","path":"/references/Systemd/shutting-down-persistance","sidebar":"defaultSidebar"},{"id":"Systemd/user-service","path":"/references/Systemd/user-service","sidebar":"defaultSidebar"}],"draftIds":[],"sidebars":{"defaultSidebar":{"link":{"path":"/references/","label":"index"}}}}],"breadcrumbs":false},"default":{"path":"/docs","versions":[{"name":"current","label":"Next","isLast":true,"path":"/docs","mainDocId":"index","docs":[{"id":"contribute","path":"/docs/contribute"},{"id":"Core/developers","path":"/docs/Core/developers"},{"id":"Core/edge-nodes","path":"/docs/Core/edge-nodes"},{"id":"Core/services","path":"/docs/Core/services"},{"id":"develop/client","path":"/docs/develop/client"},{"id":"develop/index","path":"/docs/develop/overview"},{"id":"develop/json-rpc","path":"/docs/develop/json-rpc"},{"id":"develop/service-development","path":"/docs/develop/service-development"},{"id":"index","path":"/docs/","sidebar":"docs"},{"id":"learn/delivery-acknowledgements","path":"/docs/learn/delivery-acknowledgements","sidebar":"docs"},{"id":"learn/developers","path":"/docs/learn/developers","sidebar":"docs"},{"id":"learn/index","path":"/docs/learn/introduction","sidebar":"docs"},{"id":"learn/network","path":"/docs/learn/the-network","sidebar":"docs"},{"id":"learn/ports","path":"/docs/learn/ports"},{"id":"learn/services","path":"/docs/learn/services","sidebar":"docs"},{"id":"learn/token-and-economics","path":"/docs/learn/token-and-economics","sidebar":"docs"},{"id":"node/configuration","path":"/docs/node/configuration"},{"id":"node/diagnostics","path":"/docs/node/diagnostics"},{"id":"node/health-check","path":"/docs/node/health-check","sidebar":"docs"},{"id":"node/index","path":"/docs/node/overview","sidebar":"docs"},{"id":"node/install","path":"/docs/node/Install","sidebar":"docs"},{"id":"node/requirements","path":"/docs/node/requirements","sidebar":"docs"},{"id":"node/testnet-onboarding","path":"/docs/node/testnet-onboarding","sidebar":"docs"},{"id":"Open-source","path":"/docs/Open-source"},{"id":"Open-source/code-of-conduct","path":"/docs/Open-source/code-of-conduct","sidebar":"docs"},{"id":"Open-source/contributing","path":"/docs/Open-source/contributing","sidebar":"docs"},{"id":"Open-source/repositories","path":"/docs/Open-source/repositories","sidebar":"docs"},{"id":"roadmap","path":"/docs/roadmap","sidebar":"docs"},{"id":"whitepaper","path":"/docs/whitepaper","sidebar":"docs"}],"draftIds":[],"sidebars":{"docs":{"link":{"path":"/docs/","label":"index"}}}}],"breadcrumbs":true}}}'),i=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var s=n(7529);const l=JSON.parse('{"docusaurusVersion":"2.4.1","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"2.4.1"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"2.4.1"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"2.4.1"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"2.4.1"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"2.4.1"},"docusaurus-theme-search-algolia":{"type":"package","name":"@docusaurus/theme-search-algolia","version":"2.4.1"},"docusaurus-plugin-google-tag-manager":{"type":"package","name":"@docusaurus/plugin-google-tag-manager","version":"2.4.1"}}}'),c={siteConfig:a.default,siteMetadata:l,globalData:o,i18n:i,codeTranslations:s},u=r.createContext(c);function d(e){let{children:t}=e;return r.createElement(u.Provider,{value:c},t)}},4763:(e,t,n)=>{"use strict";n.d(t,{Z:()=>f});var r=n(7294),a=n(412),o=n(5742),i=n(8780),s=n(8888);function l(e){let{error:t,tryAgain:n}=e;return r.createElement("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"}},r.createElement("h1",{style:{fontSize:"3rem"}},"This page crashed"),r.createElement("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"}},"Try again"),r.createElement(c,{error:t}))}function c(e){let{error:t}=e;const n=(0,i.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return r.createElement("p",{style:{whiteSpace:"pre-wrap"}},n)}function u(e){let{error:t,tryAgain:n}=e;return r.createElement(f,{fallback:()=>r.createElement(l,{error:t,tryAgain:n})},r.createElement(o.Z,null,r.createElement("title",null,"Page Error")),r.createElement(s.Z,null,r.createElement(l,{error:t,tryAgain:n})))}const d=e=>r.createElement(u,e);class f extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){a.Z.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??d)(e)}return e??null}}},412:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,a={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},5742:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(405);function o(e){return r.createElement(a.ql,e)}},9960:(e,t,n)=>{"use strict";n.d(t,{Z:()=>p});var r=n(7462),a=n(7294),o=n(3727),i=n(8780),s=n(2263),l=n(3919),c=n(412);const u=a.createContext({collectLink:()=>{}});var d=n(4996);function f(e,t){let{isNavLink:n,to:f,href:p,activeClassName:g,isActive:m,"data-noBrokenLinkCheck":h,autoAddBaseUrl:b=!0,...v}=e;const{siteConfig:{trailingSlash:y,baseUrl:w}}=(0,s.Z)(),{withBaseUrl:k}=(0,d.C)(),E=(0,a.useContext)(u),_=(0,a.useRef)(null);(0,a.useImperativeHandle)(t,(()=>_.current));const S=f||p;const x=(0,l.Z)(S),C=S?.replace("pathname://","");let T=void 0!==C?(L=C,b&&(e=>e.startsWith("/"))(L)?k(L):L):void 0;var L;T&&x&&(T=(0,i.applyTrailingSlash)(T,{trailingSlash:y,baseUrl:w}));const A=(0,a.useRef)(!1),R=n?o.OL:o.rU,O=c.Z.canUseIntersectionObserver,N=(0,a.useRef)(),P=()=>{A.current||null==T||(window.docusaurus.preload(T),A.current=!0)};(0,a.useEffect)((()=>(!O&&x&&null!=T&&window.docusaurus.prefetch(T),()=>{O&&N.current&&N.current.disconnect()})),[N,T,O,x]);const I=T?.startsWith("#")??!1,D=!T||!x||I;return D||h||E.collectLink(T),D?a.createElement("a",(0,r.Z)({ref:_,href:T},S&&!x&&{target:"_blank",rel:"noopener noreferrer"},v)):a.createElement(R,(0,r.Z)({},v,{onMouseEnter:P,onTouchStart:P,innerRef:e=>{_.current=e,O&&e&&x&&(N.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(N.current.unobserve(e),N.current.disconnect(),null!=T&&window.docusaurus.prefetch(T))}))})),N.current.observe(e))},to:T},n&&{isActive:m,activeClassName:g}))}const p=a.forwardRef(f)},5999:(e,t,n)=>{"use strict";n.d(t,{Z:()=>l,I:()=>s});var r=n(7294);function a(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,r.isValidElement)(e)))?n.map(((e,t)=>(0,r.isValidElement)(e)?r.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var o=n(7529);function i(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return o[t??n]??n??t}function s(e,t){let{message:n,id:r}=e;return a(i({message:n,id:r}),t)}function l(e){let{children:t,id:n,values:o}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal children",t),new Error("The Docusaurus component only accept simple string values");const s=i({message:t,id:n});return r.createElement(r.Fragment,null,a(s,o))}},9935:(e,t,n)=>{"use strict";n.d(t,{m:()=>r});const r="default"},3919:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function a(e){return void 0!==e&&!r(e)}n.d(t,{Z:()=>a,b:()=>r})},4996:(e,t,n)=>{"use strict";n.d(t,{C:()=>i,Z:()=>s});var r=n(7294),a=n(2263),o=n(3919);function i(){const{siteConfig:{baseUrl:e,url:t}}=(0,a.Z)(),n=(0,r.useCallback)(((n,r)=>function(e,t,n,r){let{forcePrependBaseUrl:a=!1,absolute:i=!1}=void 0===r?{}:r;if(!n||n.startsWith("#")||(0,o.b)(n))return n;if(a)return t+n.replace(/^\//,"");if(n===t.replace(/\/$/,""))return t;const s=n.startsWith(t)?n:t+n.replace(/^\//,"");return i?e+s:s}(t,e,n,r)),[t,e]);return{withBaseUrl:n}}function s(e,t){void 0===t&&(t={});const{withBaseUrl:n}=i();return n(e,t)}},2263:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8940);function o(){return(0,r.useContext)(a._)}},2389:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(8934);function o(){return(0,r.useContext)(a._)}},9670:(e,t,n)=>{"use strict";n.d(t,{Z:()=>a});const r=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function a(e){const t={};return function e(n,a){Object.entries(n).forEach((n=>{let[o,i]=n;const s=a?`${a}.${o}`:o;r(i)?e(i,s):t[s]=i}))}(e),t}},226:(e,t,n)=>{"use strict";n.d(t,{_:()=>a,z:()=>o});var r=n(7294);const a=r.createContext(null);function o(e){let{children:t,value:n}=e;const o=r.useContext(a),i=(0,r.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const r={...t.data,...n?.data};return{plugin:t.plugin,data:r}}({parent:o,value:n})),[o,n]);return r.createElement(a.Provider,{value:i},t)}},143:(e,t,n)=>{"use strict";n.d(t,{Iw:()=>b,gA:()=>p,WS:()=>g,_r:()=>d,Jo:()=>v,zh:()=>f,yW:()=>h,gB:()=>m});var r=n(6550),a=n(2263),o=n(9935);function i(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,a.Z)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}const s=e=>e.versions.find((e=>e.isLast));function l(e,t){const n=s(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,r.LX)(t,{path:e.path,exact:!1,strict:!1})))}function c(e,t){const n=l(e,t),a=n?.docs.find((e=>!!(0,r.LX)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:a,alternateDocVersions:a?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(a.id):{}}}const u={},d=()=>i("docusaurus-plugin-content-docs")??u,f=e=>function(e,t,n){void 0===t&&(t=o.m),void 0===n&&(n={});const r=i(e),a=r?.[t];if(!a&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return a}("docusaurus-plugin-content-docs",e,{failfast:!0});function p(e){void 0===e&&(e={});const t=d(),{pathname:n}=(0,r.TH)();return function(e,t,n){void 0===n&&(n={});const a=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.LX)(t,{path:n.path,exact:!1,strict:!1})})),o=a?{pluginId:a[0],pluginData:a[1]}:void 0;if(!o&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return o}(t,n,e)}function g(e){void 0===e&&(e={});const t=p(e),{pathname:n}=(0,r.TH)();if(!t)return;return{activePlugin:t,activeVersion:l(t.pluginData,n)}}function m(e){return f(e).versions}function h(e){const t=f(e);return s(t)}function b(e){const t=f(e),{pathname:n}=(0,r.TH)();return c(t,n)}function v(e){const t=f(e),{pathname:n}=(0,r.TH)();return function(e,t){const n=s(e);return{latestDocSuggestion:c(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},8320:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>o});var r=n(4865),a=n.n(r);a().configure({showSpinner:!1});const o={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{a().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){a().done()}}},3310:(e,t,n)=>{"use strict";n.r(t);var r=n(7410),a=n(6809);!function(e){const{themeConfig:{prism:t}}=a.default,{additionalLanguages:r}=t;globalThis.Prism=e,r.forEach((e=>{n(6726)(`./prism-${e}`)})),delete globalThis.Prism}(r.Z)},9471:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294);const a={iconExternalLink:"iconExternalLink_nPIU"};function o(e){let{width:t=13.5,height:n=13.5}=e;return r.createElement("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:a.iconExternalLink},r.createElement("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"}))}},8888:(e,t,n)=>{"use strict";n.d(t,{Z:()=>At});var r=n(7294),a=n(6010),o=n(4763),i=n(833),s=n(7462),l=n(6550),c=n(5999),u=n(5936);const d="__docusaurus_skipToContent_fallback";function f(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function p(){const e=(0,r.useRef)(null),{action:t}=(0,l.k6)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&f(t)}),[]);return(0,u.S)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&f(e.current)})),{containerRef:e,onClick:n}}const g=(0,c.I)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function m(e){const t=e.children??g,{containerRef:n,onClick:a}=p();return r.createElement("div",{ref:n,role:"region","aria-label":g},r.createElement("a",(0,s.Z)({},e,{href:`#${d}`,onClick:a}),t))}var h=n(5281),b=n(9727);const v={skipToContent:"skipToContent_fXgn"};function y(){return r.createElement(m,{className:v.skipToContent})}var w=n(6668),k=n(9689);function E(e){let{width:t=21,height:n=21,color:a="currentColor",strokeWidth:o=1.2,className:i,...l}=e;return r.createElement("svg",(0,s.Z)({viewBox:"0 0 15 15",width:t,height:n},l),r.createElement("g",{stroke:a,strokeWidth:o},r.createElement("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})))}const _={closeButton:"closeButton_CVFx"};function S(e){return r.createElement("button",(0,s.Z)({type:"button","aria-label":(0,c.I)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"})},e,{className:(0,a.Z)("clean-btn close",_.closeButton,e.className)}),r.createElement(E,{width:14,height:14,strokeWidth:3.1}))}const x={content:"content_knG7"};function C(e){const{announcementBar:t}=(0,w.L)(),{content:n}=t;return r.createElement("div",(0,s.Z)({},e,{className:(0,a.Z)(x.content,e.className),dangerouslySetInnerHTML:{__html:n}}))}const T={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function L(){const{announcementBar:e}=(0,w.L)(),{isActive:t,close:n}=(0,k.nT)();if(!t)return null;const{backgroundColor:a,textColor:o,isCloseable:i}=e;return r.createElement("div",{className:T.announcementBar,style:{backgroundColor:a,color:o},role:"banner"},i&&r.createElement("div",{className:T.announcementBarPlaceholder}),r.createElement(C,{className:T.announcementBarContent}),i&&r.createElement(S,{onClick:n,className:T.announcementBarClose}))}var A=n(3163),R=n(2466);var O=n(902),N=n(3102);const P=r.createContext(null);function I(e){let{children:t}=e;const n=function(){const e=(0,A.e)(),t=(0,N.HY)(),[n,a]=(0,r.useState)(!1),o=null!==t.component,i=(0,O.D9)(o);return(0,r.useEffect)((()=>{o&&!i&&a(!0)}),[o,i]),(0,r.useEffect)((()=>{o?e.shown||a(!0):a(!1)}),[e.shown,o]),(0,r.useMemo)((()=>[n,a]),[n])}();return r.createElement(P.Provider,{value:n},t)}function D(e){if(e.component){const t=e.component;return r.createElement(t,e.props)}}function M(){const e=(0,r.useContext)(P);if(!e)throw new O.i6("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,a=(0,r.useCallback)((()=>n(!1)),[n]),o=(0,N.HY)();return(0,r.useMemo)((()=>({shown:t,hide:a,content:D(o)})),[a,o,t])}function j(e){let{header:t,primaryMenu:n,secondaryMenu:o}=e;const{shown:i}=M();return r.createElement("div",{className:"navbar-sidebar"},t,r.createElement("div",{className:(0,a.Z)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":i})},r.createElement("div",{className:"navbar-sidebar__item menu"},n),r.createElement("div",{className:"navbar-sidebar__item menu"},o)))}var F=n(2949),B=n(2389);function z(e){return r.createElement("svg",(0,s.Z)({viewBox:"0 0 24 24",width:24,height:24},e),r.createElement("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"}))}function U(e){return r.createElement("svg",(0,s.Z)({viewBox:"0 0 24 24",width:24,height:24},e),r.createElement("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"}))}const $={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function q(e){let{className:t,buttonClassName:n,value:o,onChange:i}=e;const s=(0,B.Z)(),l=(0,c.I)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===o?(0,c.I)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,c.I)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return r.createElement("div",{className:(0,a.Z)($.toggle,t)},r.createElement("button",{className:(0,a.Z)("clean-btn",$.toggleButton,!s&&$.toggleButtonDisabled,n),type:"button",onClick:()=>i("dark"===o?"light":"dark"),disabled:!s,title:l,"aria-label":l,"aria-live":"polite"},r.createElement(z,{className:(0,a.Z)($.toggleIcon,$.lightToggleIcon)}),r.createElement(U,{className:(0,a.Z)($.toggleIcon,$.darkToggleIcon)})))}const H=r.memo(q),G={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function Z(e){let{className:t}=e;const n=(0,w.L)().navbar.style,a=(0,w.L)().colorMode.disableSwitch,{colorMode:o,setColorMode:i}=(0,F.I)();return a?null:r.createElement(H,{className:t,buttonClassName:"dark"===n?G.darkNavbarColorModeToggle:void 0,value:o,onChange:i})}var V=n(1327);function W(){return r.createElement(V.Z,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function K(){const e=(0,A.e)();return r.createElement("button",{type:"button","aria-label":(0,c.I)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle()},r.createElement(E,{color:"var(--ifm-color-emphasis-600)"}))}function Y(){return r.createElement("div",{className:"navbar-sidebar__brand"},r.createElement(W,null),r.createElement(Z,{className:"margin-right--md"}),r.createElement(K,null))}var Q=n(9960),X=n(4996),J=n(3919),ee=n(8022),te=n(9471);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:a,href:o,label:i,html:l,isDropdownLink:c,prependBaseUrlToHref:u,...d}=e;const f=(0,X.Z)(a),p=(0,X.Z)(t),g=(0,X.Z)(o,{forcePrependBaseUrl:!0}),m=i&&o&&!(0,J.Z)(o),h=l?{dangerouslySetInnerHTML:{__html:l}}:{children:r.createElement(r.Fragment,null,i,m&&r.createElement(te.Z,c&&{width:12,height:12}))};return o?r.createElement(Q.Z,(0,s.Z)({href:u?g:o},d,h)):r.createElement(Q.Z,(0,s.Z)({to:f,isNavLink:!0},(t||n)&&{isActive:(e,t)=>n?(0,ee.F)(n,t.pathname):t.pathname.startsWith(p)},d,h))}function re(e){let{className:t,isDropdownItem:n=!1,...o}=e;const i=r.createElement(ne,(0,s.Z)({className:(0,a.Z)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n},o));return n?r.createElement("li",null,i):i}function ae(e){let{className:t,isDropdownItem:n,...o}=e;return r.createElement("li",{className:"menu__list-item"},r.createElement(ne,(0,s.Z)({className:(0,a.Z)("menu__link",t)},o)))}function oe(e){let{mobile:t=!1,position:n,...a}=e;const o=t?ae:re;return r.createElement(o,(0,s.Z)({},a,{activeClassName:a.activeClassName??(t?"menu__link--active":"navbar__link--active")}))}var ie=n(6043),se=n(8596),le=n(2263);function ce(e,t){return e.some((e=>function(e,t){return!!(0,se.Mg)(e.to,t)||!!(0,ee.F)(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function ue(e){let{items:t,position:n,className:o,onClick:i,...l}=e;const c=(0,r.useRef)(null),[u,d]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{c.current&&!c.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[c]),r.createElement("div",{ref:c,className:(0,a.Z)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":u})},r.createElement(ne,(0,s.Z)({"aria-haspopup":"true","aria-expanded":u,role:"button",href:l.to?void 0:"#",className:(0,a.Z)("navbar__link",o)},l,{onClick:l.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!u))}}),l.children??l.label),r.createElement("ul",{className:"dropdown__menu"},t.map(((e,t)=>r.createElement(qe,(0,s.Z)({isDropdownItem:!0,activeClassName:"dropdown__link--active"},e,{key:t}))))))}function de(e){let{items:t,className:n,position:o,onClick:i,...c}=e;const u=function(){const{siteConfig:{baseUrl:e}}=(0,le.Z)(),{pathname:t}=(0,l.TH)();return t.replace(e,"/")}(),d=ce(t,u),{collapsed:f,toggleCollapsed:p,setCollapsed:g}=(0,ie.u)({initialState:()=>!d});return(0,r.useEffect)((()=>{d&&g(!d)}),[u,d,g]),r.createElement("li",{className:(0,a.Z)("menu__list-item",{"menu__list-item--collapsed":f})},r.createElement(ne,(0,s.Z)({role:"button",className:(0,a.Z)("menu__link menu__link--sublist menu__link--sublist-caret",n)},c,{onClick:e=>{e.preventDefault(),p()}}),c.children??c.label),r.createElement(ie.z,{lazy:!0,as:"ul",className:"menu__list",collapsed:f},t.map(((e,t)=>r.createElement(qe,(0,s.Z)({mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active"},e,{key:t}))))))}function fe(e){let{mobile:t=!1,...n}=e;const a=t?de:ue;return r.createElement(a,n)}var pe=n(4711);function ge(e){let{width:t=20,height:n=20,...a}=e;return r.createElement("svg",(0,s.Z)({viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0},a),r.createElement("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"}))}const me="iconLanguage_nlXk";function he(){return r.createElement("svg",{width:"15",height:"15",className:"DocSearch-Control-Key-Icon"},r.createElement("path",{d:"M4.505 4.496h2M5.505 5.496v5M8.216 4.496l.055 5.993M10 7.5c.333.333.5.667.5 1v2M12.326 4.5v5.996M8.384 4.496c1.674 0 2.116 0 2.116 1.5s-.442 1.5-2.116 1.5M3.205 9.303c-.09.448-.277 1.21-1.241 1.203C1 10.5.5 9.513.5 8V7c0-1.57.5-2.5 1.464-2.494.964.006 1.134.598 1.24 1.342M12.553 10.5h1.953",strokeWidth:"1.2",stroke:"currentColor",fill:"none",strokeLinecap:"square"}))}var be=n(830),ve=["translations"];function ye(){return ye=Object.assign||function(e){for(var t=1;te.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0||(a[n]=e[n]);return a}(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(r=0;r=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(a[n]=e[n])}return a}var _e="Ctrl";var Se=r.forwardRef((function(e,t){var n=e.translations,a=void 0===n?{}:n,o=Ee(e,ve),i=a.buttonText,s=void 0===i?"Search":i,l=a.buttonAriaLabel,c=void 0===l?"Search":l,u=we((0,r.useState)(null),2),d=u[0],f=u[1];return(0,r.useEffect)((function(){"undefined"!=typeof navigator&&(/(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)?f("\u2318"):f(_e))}),[]),r.createElement("button",ye({type:"button",className:"DocSearch DocSearch-Button","aria-label":c},o,{ref:t}),r.createElement("span",{className:"DocSearch-Button-Container"},r.createElement(be.W,null),r.createElement("span",{className:"DocSearch-Button-Placeholder"},s)),r.createElement("span",{className:"DocSearch-Button-Keys"},null!==d&&r.createElement(r.Fragment,null,r.createElement("kbd",{className:"DocSearch-Button-Key"},d===_e?r.createElement(he,null):d),r.createElement("kbd",{className:"DocSearch-Button-Key"},"K"))))})),xe=n(5742),Ce=n(6177),Te=n(239),Le=n(3320);var Ae=n(3935);const Re={button:{buttonText:(0,c.I)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"}),buttonAriaLabel:(0,c.I)({id:"theme.SearchBar.label",message:"Search",description:"The ARIA label and placeholder for search button"})},modal:{searchBox:{resetButtonTitle:(0,c.I)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),resetButtonAriaLabel:(0,c.I)({id:"theme.SearchModal.searchBox.resetButtonTitle",message:"Clear the query",description:"The label and ARIA label for search box reset button"}),cancelButtonText:(0,c.I)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"}),cancelButtonAriaLabel:(0,c.I)({id:"theme.SearchModal.searchBox.cancelButtonText",message:"Cancel",description:"The label and ARIA label for search box cancel button"})},startScreen:{recentSearchesTitle:(0,c.I)({id:"theme.SearchModal.startScreen.recentSearchesTitle",message:"Recent",description:"The title for recent searches"}),noRecentSearchesText:(0,c.I)({id:"theme.SearchModal.startScreen.noRecentSearchesText",message:"No recent searches",description:"The text when no recent searches"}),saveRecentSearchButtonTitle:(0,c.I)({id:"theme.SearchModal.startScreen.saveRecentSearchButtonTitle",message:"Save this search",description:"The label for save recent search button"}),removeRecentSearchButtonTitle:(0,c.I)({id:"theme.SearchModal.startScreen.removeRecentSearchButtonTitle",message:"Remove this search from history",description:"The label for remove recent search button"}),favoriteSearchesTitle:(0,c.I)({id:"theme.SearchModal.startScreen.favoriteSearchesTitle",message:"Favorite",description:"The title for favorite searches"}),removeFavoriteSearchButtonTitle:(0,c.I)({id:"theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle",message:"Remove this search from favorites",description:"The label for remove favorite search button"})},errorScreen:{titleText:(0,c.I)({id:"theme.SearchModal.errorScreen.titleText",message:"Unable to fetch results",description:"The title for error screen of search modal"}),helpText:(0,c.I)({id:"theme.SearchModal.errorScreen.helpText",message:"You might want to check your network connection.",description:"The help text for error screen of search modal"})},footer:{selectText:(0,c.I)({id:"theme.SearchModal.footer.selectText",message:"to select",description:"The explanatory text of the action for the enter key"}),selectKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.selectKeyAriaLabel",message:"Enter key",description:"The ARIA label for the Enter key button that makes the selection"}),navigateText:(0,c.I)({id:"theme.SearchModal.footer.navigateText",message:"to navigate",description:"The explanatory text of the action for the Arrow up and Arrow down key"}),navigateUpKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.navigateUpKeyAriaLabel",message:"Arrow up",description:"The ARIA label for the Arrow up key button that makes the navigation"}),navigateDownKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.navigateDownKeyAriaLabel",message:"Arrow down",description:"The ARIA label for the Arrow down key button that makes the navigation"}),closeText:(0,c.I)({id:"theme.SearchModal.footer.closeText",message:"to close",description:"The explanatory text of the action for Escape key"}),closeKeyAriaLabel:(0,c.I)({id:"theme.SearchModal.footer.closeKeyAriaLabel",message:"Escape key",description:"The ARIA label for the Escape key button that close the modal"}),searchByText:(0,c.I)({id:"theme.SearchModal.footer.searchByText",message:"Search by",description:"The text explain that the search is making by Algolia"})},noResultsScreen:{noResultsText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.noResultsText",message:"No results for",description:"The text explains that there are no results for the following search"}),suggestedQueryText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.suggestedQueryText",message:"Try searching for",description:"The text for the suggested query when no results are found for the following search"}),reportMissingResultsText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsText",message:"Believe this query should return results?",description:"The text for the question where the user thinks there are missing results"}),reportMissingResultsLinkText:(0,c.I)({id:"theme.SearchModal.noResultsScreen.reportMissingResultsLinkText",message:"Let us know.",description:"The text for the link to report missing results"})}},placeholder:(0,c.I)({id:"theme.SearchModal.placeholder",message:"Search docs",description:"The placeholder of the input of the DocSearch pop-up modal"})};let Oe=null;function Ne(e){let{hit:t,children:n}=e;return r.createElement(Q.Z,{to:t.url},n)}function Pe(e){let{state:t,onClose:n}=e;const a=(0,Ce.M)();return r.createElement(Q.Z,{to:a(t.query),onClick:n},r.createElement(c.Z,{id:"theme.SearchBar.seeAll",values:{count:t.context.nbHits}},"See all {count} results"))}function Ie(e){let{contextualSearch:t,externalUrlRegex:a,...o}=e;const{siteMetadata:i}=(0,le.Z)(),c=(0,Te.l)(),u=function(){const{locale:e,tags:t}=(0,Le._q)();return[`language:${e}`,t.map((e=>`docusaurus_tag:${e}`))]}(),d=o.searchParameters?.facetFilters??[],f=t?function(e,t){const n=e=>"string"==typeof e?[e]:e;return[...n(e),...n(t)]}(u,d):d,p={...o.searchParameters,facetFilters:f},g=(0,l.k6)(),m=(0,r.useRef)(null),h=(0,r.useRef)(null),[b,v]=(0,r.useState)(!1),[y,w]=(0,r.useState)(void 0),k=(0,r.useCallback)((()=>Oe?Promise.resolve():Promise.all([n.e(1426).then(n.bind(n,1426)),Promise.all([n.e(532),n.e(6945)]).then(n.bind(n,6945)),Promise.all([n.e(532),n.e(8894)]).then(n.bind(n,8894))]).then((e=>{let[{DocSearchModal:t}]=e;Oe=t}))),[]),E=(0,r.useCallback)((()=>{k().then((()=>{m.current=document.createElement("div"),document.body.insertBefore(m.current,document.body.firstChild),v(!0)}))}),[k,v]),_=(0,r.useCallback)((()=>{v(!1),m.current?.remove()}),[v]),S=(0,r.useCallback)((e=>{k().then((()=>{v(!0),w(e.key)}))}),[k,v,w]),x=(0,r.useRef)({navigate(e){let{itemUrl:t}=e;(0,ee.F)(a,t)?window.location.href=t:g.push(t)}}).current,C=(0,r.useRef)((e=>o.transformItems?o.transformItems(e):e.map((e=>({...e,url:c(e.url)}))))).current,T=(0,r.useMemo)((()=>e=>r.createElement(Pe,(0,s.Z)({},e,{onClose:_}))),[_]),L=(0,r.useCallback)((e=>(e.addAlgoliaAgent("docusaurus",i.docusaurusVersion),e)),[i.docusaurusVersion]);return function(e){var t=e.isOpen,n=e.onOpen,a=e.onClose,o=e.onInput,i=e.searchButtonRef;r.useEffect((function(){function e(e){var r;(27===e.keyCode&&t||"k"===(null===(r=e.key)||void 0===r?void 0:r.toLowerCase())&&(e.metaKey||e.ctrlKey)||!function(e){var t=e.target,n=t.tagName;return t.isContentEditable||"INPUT"===n||"SELECT"===n||"TEXTAREA"===n}(e)&&"/"===e.key&&!t)&&(e.preventDefault(),t?a():document.body.classList.contains("DocSearch--active")||document.body.classList.contains("DocSearch--active")||n()),i&&i.current===document.activeElement&&o&&/[a-zA-Z0-9]/.test(String.fromCharCode(e.keyCode))&&o(e)}return window.addEventListener("keydown",e),function(){window.removeEventListener("keydown",e)}}),[t,n,a,o,i])}({isOpen:b,onOpen:E,onClose:_,onInput:S,searchButtonRef:h}),r.createElement(r.Fragment,null,r.createElement(xe.Z,null,r.createElement("link",{rel:"preconnect",href:`https://${o.appId}-dsn.algolia.net`,crossOrigin:"anonymous"})),r.createElement(Se,{onTouchStart:k,onFocus:k,onMouseOver:k,onClick:E,ref:h,translations:Re.button}),b&&Oe&&m.current&&(0,Ae.createPortal)(r.createElement(Oe,(0,s.Z)({onClose:_,initialScrollY:window.scrollY,initialQuery:y,navigator:x,transformItems:C,hitComponent:Ne,transformSearchClient:L},o.searchPagePath&&{resultsFooterComponent:T},o,{searchParameters:p,placeholder:Re.placeholder,translations:Re.modal})),m.current))}function De(){const{siteConfig:e}=(0,le.Z)();return r.createElement(Ie,e.themeConfig.algolia)}const Me={searchBox:"searchBox_ZlJk"};function je(e){let{children:t,className:n}=e;return r.createElement("div",{className:(0,a.Z)(n,Me.searchBox)},t)}var Fe=n(143),Be=n(2802);var ze=n(373);const Ue=e=>e.docs.find((t=>t.id===e.mainDocId));const $e={default:oe,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:a,...o}=e;const{i18n:{currentLocale:i,locales:u,localeConfigs:d}}=(0,le.Z)(),f=(0,pe.l)(),{search:p,hash:g}=(0,l.TH)(),m=[...n,...u.map((e=>{const n=`${`pathname://${f.createUrl({locale:e,fullyQualified:!1})}`}${p}${g}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...a],h=t?(0,c.I)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return r.createElement(fe,(0,s.Z)({},o,{mobile:t,label:r.createElement(r.Fragment,null,r.createElement(ge,{className:me}),h),items:m}))},search:function(e){let{mobile:t,className:n}=e;return t?null:r.createElement(je,{className:n},r.createElement(De,null))},dropdown:fe,html:function(e){let{value:t,className:n,mobile:o=!1,isDropdownItem:i=!1}=e;const s=i?"li":"div";return r.createElement(s,{className:(0,a.Z)({navbar__item:!o&&!i,"menu__list-item":o},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:a,...o}=e;const{activeDoc:i}=(0,Fe.Iw)(a),l=(0,Be.vY)(t,a);return null===l?null:r.createElement(oe,(0,s.Z)({exact:!0},o,{isActive:()=>i?.path===l.path||!!i?.sidebar&&i.sidebar===l.sidebar,label:n??l.id,to:l.path}))},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:a,...o}=e;const{activeDoc:i}=(0,Fe.Iw)(a),l=(0,Be.oz)(t,a).link;if(!l)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return r.createElement(oe,(0,s.Z)({exact:!0},o,{isActive:()=>i?.sidebar===t,label:n??l.label,to:l.path}))},docsVersion:function(e){let{label:t,to:n,docsPluginId:a,...o}=e;const i=(0,Be.lO)(a)[0],l=t??i.label,c=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(i).path;return r.createElement(oe,(0,s.Z)({},o,{label:l,to:c}))},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:a,dropdownItemsBefore:o,dropdownItemsAfter:i,...u}=e;const{search:d,hash:f}=(0,l.TH)(),p=(0,Fe.Iw)(n),g=(0,Fe.gB)(n),{savePreferredVersionName:m}=(0,ze.J)(n),h=[...o,...g.map((e=>{const t=p.alternateDocVersions[e.name]??Ue(e);return{label:e.label,to:`${t.path}${d}${f}`,isActive:()=>e===p.activeVersion,onClick:()=>m(e.name)}})),...i],b=(0,Be.lO)(n)[0],v=t&&h.length>1?(0,c.I)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):b.label,y=t&&h.length>1?void 0:Ue(b).path;return h.length<=1?r.createElement(oe,(0,s.Z)({},u,{mobile:t,label:v,to:y,isActive:a?()=>!1:void 0})):r.createElement(fe,(0,s.Z)({},u,{mobile:t,label:v,to:y,items:h,isActive:a?()=>!1:void 0}))}};function qe(e){let{type:t,...n}=e;const a=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=$e[a];if(!o)throw new Error(`No NavbarItem component found for type "${t}".`);return r.createElement(o,n)}function He(){const e=(0,A.e)(),t=(0,w.L)().navbar.items;return r.createElement("ul",{className:"menu__list"},t.map(((t,n)=>r.createElement(qe,(0,s.Z)({mobile:!0},t,{onClick:()=>e.toggle(),key:n})))))}function Ge(e){return r.createElement("button",(0,s.Z)({},e,{type:"button",className:"clean-btn navbar-sidebar__back"}),r.createElement(c.Z,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)"},"\u2190 Back to main menu"))}function Ze(){const e=0===(0,w.L)().navbar.items.length,t=M();return r.createElement(r.Fragment,null,!e&&r.createElement(Ge,{onClick:()=>t.hide()}),t.content)}function Ve(){const e=(0,A.e)();var t;return void 0===(t=e.shown)&&(t=!0),(0,r.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?r.createElement(j,{header:r.createElement(Y,null),primaryMenu:r.createElement(He,null),secondaryMenu:r.createElement(Ze,null)}):null}const We={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function Ke(e){return r.createElement("div",(0,s.Z)({role:"presentation"},e,{className:(0,a.Z)("navbar-sidebar__backdrop",e.className)}))}function Ye(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:o}}=(0,w.L)(),i=(0,A.e)(),{navbarRef:s,isNavbarVisible:l}=function(e){const[t,n]=(0,r.useState)(e),a=(0,r.useRef)(!1),o=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(o.current=e.getBoundingClientRect().height)}),[]);return(0,R.RF)(((t,r)=>{let{scrollY:i}=t;if(!e)return;if(i=s?n(!1):i+c{if(!e)return;const r=t.location.hash;if(r?document.getElementById(r.substring(1)):void 0)return a.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return r.createElement("nav",{ref:s,"aria-label":(0,c.I)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,a.Z)("navbar","navbar--fixed-top",n&&[We.navbarHideable,!l&&We.navbarHidden],{"navbar--dark":"dark"===o,"navbar--primary":"primary"===o,"navbar-sidebar--show":i.shown})},t,r.createElement(Ke,{onClick:i.toggle}),r.createElement(Ve,null))}const Qe="right";function Xe(e){let{width:t=30,height:n=30,className:a,...o}=e;return r.createElement("svg",(0,s.Z)({className:a,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true"},o),r.createElement("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"}))}function Je(){const{toggle:e,shown:t}=(0,A.e)();return r.createElement("button",{onClick:e,"aria-label":(0,c.I)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button"},r.createElement(Xe,null))}const et={colorModeToggle:"colorModeToggle_x44X"};function tt(e){let{items:t}=e;return r.createElement(r.Fragment,null,t.map(((e,t)=>r.createElement(qe,(0,s.Z)({},e,{key:t})))))}function nt(e){let{left:t,right:n}=e;return r.createElement("div",{className:"navbar__inner"},r.createElement("div",{className:"navbar__items"},t),r.createElement("div",{className:"navbar__items navbar__items--right"},n))}function rt(){const e=(0,A.e)(),t=(0,w.L)().navbar.items,[n,a]=function(e){function t(e){return"left"===(e.position??Qe)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return r.createElement(nt,{left:r.createElement(r.Fragment,null,r.createElement("div",null,!e.disabled&&r.createElement(Je,null),r.createElement(W,null),r.createElement(tt,{items:n})),r.createElement("div",null,!o&&r.createElement(je,null,r.createElement(De,null)))),right:r.createElement(r.Fragment,null,r.createElement(tt,{items:a}),r.createElement(Z,{className:et.colorModeToggle}))})}function at(){return r.createElement(Ye,null,r.createElement(rt,null))}function ot(e){let{item:t}=e;const{to:n,href:a,label:o,prependBaseUrlToHref:i,...l}=t,c=(0,X.Z)(n),u=(0,X.Z)(a,{forcePrependBaseUrl:!0});return r.createElement(Q.Z,(0,s.Z)({className:"footer__link-item"},a?{href:i?u:a}:{to:c},l),o,a&&!(0,J.Z)(a)&&r.createElement(te.Z,null))}function it(e){let{item:t}=e;return t.html?r.createElement("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):r.createElement("li",{key:t.href??t.to,className:"footer__item"},r.createElement(ot,{item:t}))}function st(e){let{column:t}=e;return r.createElement("div",{className:"col footer__col"},r.createElement("div",{className:"footer__title"},t.title),r.createElement("ul",{className:"footer__items clean-list"},t.items.map(((e,t)=>r.createElement(it,{key:t,item:e})))))}function lt(e){let{columns:t}=e;return r.createElement("div",{className:"row footer__links"},t.map(((e,t)=>r.createElement(st,{key:t,column:e}))))}function ct(){return r.createElement("span",{className:"footer__link-separator"},"\xb7")}function ut(e){let{item:t}=e;return t.html?r.createElement("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):r.createElement(ot,{item:t})}function dt(e){let{links:t}=e;return r.createElement("div",{className:"footer__links text--center"},r.createElement("div",{className:"footer__links"},t.map(((e,n)=>r.createElement(r.Fragment,{key:n},r.createElement(ut,{item:e}),t.length!==n+1&&r.createElement(ct,null))))))}function ft(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?r.createElement(lt,{columns:t}):r.createElement(dt,{links:t})}var pt=n(941);const gt={footerLogoLink:"footerLogoLink_BH7S"};function mt(e){let{logo:t}=e;const{withBaseUrl:n}=(0,X.C)(),o={light:n(t.src),dark:n(t.srcDark??t.src)};return r.createElement(pt.Z,{className:(0,a.Z)("footer__logo",t.className),alt:t.alt,sources:o,width:t.width,height:t.height,style:t.style})}function ht(e){let{logo:t}=e;return t.href?r.createElement(Q.Z,{href:t.href,className:gt.footerLogoLink,target:t.target},r.createElement(mt,{logo:t})):r.createElement(mt,{logo:t})}function bt(e){let{copyright:t}=e;return r.createElement("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function vt(e){let{style:t,links:n,logo:o,copyright:i}=e;return r.createElement("footer",{className:(0,a.Z)("footer",{"footer--dark":"dark"===t})},r.createElement("div",{className:"container container-fluid"},n,(o||i)&&r.createElement("div",{className:"footer__bottom text--left"},o&&r.createElement("div",{className:"margin-bottom--sm"},o),i)))}function yt(){const{footer:e}=(0,w.L)();if(!e)return null;const{copyright:t,links:n,logo:a,style:o}=e;return r.createElement(vt,{style:o,links:n&&n.length>0&&r.createElement(ft,{links:n}),logo:a&&r.createElement(ht,{logo:a}),copyright:t&&r.createElement(bt,{copyright:t})})}const wt=r.memo(yt),kt=(0,O.Qc)([F.S,k.pl,R.OC,ze.L5,i.VC,function(e){let{children:t}=e;return r.createElement(N.n2,null,r.createElement(A.M,null,r.createElement(I,null,t)))}]);function Et(e){let{children:t}=e;return r.createElement(kt,null,t)}var _t=n(8780);const St={errorBoundaryError:"errorBoundaryError_a6uf"};function xt(e){return r.createElement("button",(0,s.Z)({type:"button"},e),r.createElement(c.Z,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error"},"Try again"))}function Ct(e){let{error:t}=e;const n=(0,_t.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return r.createElement("p",{className:St.errorBoundaryError},n)}r.Component;function Tt(e){let{error:t,tryAgain:n}=e;return r.createElement("main",{className:"container margin-vert--xl"},r.createElement("div",{className:"row"},r.createElement("div",{className:"col col--6 col--offset-3"},r.createElement("h1",{className:"hero__title"},r.createElement(c.Z,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed"},"This page crashed.")),r.createElement("div",{className:"margin-vert--lg"},r.createElement(xt,{onClick:n,className:"button button--primary shadow--lw"})),r.createElement("hr",null),r.createElement("div",{className:"margin-vert--md"},r.createElement(Ct,{error:t})))))}const Lt={mainWrapper:"mainWrapper_z2l0"};function At(e){const{children:t,noFooter:n,wrapperClassName:s,title:l,description:c}=e;return(0,b.t)(),r.createElement(Et,null,r.createElement(i.d,{title:l,description:c}),r.createElement(y,null),r.createElement(L,null),r.createElement(at,null),r.createElement("div",{id:d,className:(0,a.Z)(h.k.wrapper.main,Lt.mainWrapper,s)},r.createElement(o.Z,{fallback:e=>r.createElement(Tt,e)},t)),!n&&r.createElement(wt,null))}},1327:(e,t,n)=>{"use strict";n.d(t,{Z:()=>d});var r=n(7462),a=n(7294),o=n(9960),i=n(4996),s=n(2263),l=n(6668),c=n(941);function u(e){let{logo:t,alt:n,imageClassName:r}=e;const o={light:(0,i.Z)(t.src),dark:(0,i.Z)(t.srcDark||t.src)},s=a.createElement(c.Z,{className:t.className,sources:o,height:t.height,width:t.width,alt:n,style:t.style});return r?a.createElement("div",{className:r},s):s}function d(e){const{siteConfig:{title:t}}=(0,s.Z)(),{navbar:{title:n,logo:c}}=(0,l.L)(),{imageClassName:d,titleClassName:f,...p}=e,g=(0,i.Z)(c?.href||"/"),m=n?"":t,h=c?.alt??m;return a.createElement(o.Z,(0,r.Z)({to:g},p,c?.target&&{target:c.target}),c&&a.createElement(u,{logo:c,alt:h,imageClassName:d}),null!=n&&a.createElement("b",{className:f},n))}},197:(e,t,n)=>{"use strict";n.d(t,{Z:()=>o});var r=n(7294),a=n(5742);function o(e){let{locale:t,version:n,tag:o}=e;const i=t;return r.createElement(a.Z,null,t&&r.createElement("meta",{name:"docusaurus_locale",content:t}),n&&r.createElement("meta",{name:"docusaurus_version",content:n}),o&&r.createElement("meta",{name:"docusaurus_tag",content:o}),i&&r.createElement("meta",{name:"docsearch:language",content:i}),n&&r.createElement("meta",{name:"docsearch:version",content:n}),o&&r.createElement("meta",{name:"docsearch:docusaurus_tag",content:o}))}},941:(e,t,n)=>{"use strict";n.d(t,{Z:()=>c});var r=n(7462),a=n(7294),o=n(6010),i=n(2389),s=n(2949);const l={themedImage:"themedImage_ToTc","themedImage--light":"themedImage--light_HNdA","themedImage--dark":"themedImage--dark_i4oU"};function c(e){const t=(0,i.Z)(),{colorMode:n}=(0,s.I)(),{sources:c,className:u,alt:d,...f}=e,p=t?"dark"===n?["dark"]:["light"]:["light","dark"];return a.createElement(a.Fragment,null,p.map((e=>a.createElement("img",(0,r.Z)({key:e,src:c[e],alt:d,className:(0,o.Z)(l.themedImage,l[`themedImage--${e}`],u)},f)))))}},6043:(e,t,n)=>{"use strict";n.d(t,{u:()=>l,z:()=>h});var r=n(7462),a=n(7294),o=n(412),i=n(1442);const s="ease-in-out";function l(e){let{initialState:t}=e;const[n,r]=(0,a.useState)(t??!1),o=(0,a.useCallback)((()=>{r((e=>!e))}),[]);return{collapsed:n,setCollapsed:r,toggleCollapsed:o}}const c={display:"none",overflow:"hidden",height:"0px"},u={display:"block",overflow:"visible",height:"auto"};function d(e,t){const n=t?c:u;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function f(e){let{collapsibleRef:t,collapsed:n,animation:r}=e;const o=(0,a.useRef)(!1);(0,a.useEffect)((()=>{const e=t.current;function a(){const t=e.scrollHeight,n=r?.duration??function(e){if((0,i.n)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${r?.easing??s}`,height:`${t}px`}}function l(){const t=a();e.style.transition=t.transition,e.style.height=t.height}if(!o.current)return d(e,n),void(o.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(l(),requestAnimationFrame((()=>{e.style.height=c.height,e.style.overflow=c.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{l()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,r])}function p(e){if(!o.Z.canUseDOM)return e?c:u}function g(e){let{as:t="div",collapsed:n,children:r,animation:o,onCollapseTransitionEnd:i,className:s,disableSSRStyle:l}=e;const c=(0,a.useRef)(null);return f({collapsibleRef:c,collapsed:n,animation:o}),a.createElement(t,{ref:c,style:l?void 0:p(n),onTransitionEnd:e=>{"height"===e.propertyName&&(d(c.current,n),i?.(n))},className:s},r)}function m(e){let{collapsed:t,...n}=e;const[o,i]=(0,a.useState)(!t),[s,l]=(0,a.useState)(t);return(0,a.useLayoutEffect)((()=>{t||i(!0)}),[t]),(0,a.useLayoutEffect)((()=>{o&&l(t)}),[o,t]),o?a.createElement(g,(0,r.Z)({},n,{collapsed:s})):null}function h(e){let{lazy:t,...n}=e;const r=t?m:g;return a.createElement(r,n)}},9689:(e,t,n)=>{"use strict";n.d(t,{nT:()=>g,pl:()=>p});var r=n(7294),a=n(2389),o=n(12),i=n(902),s=n(6668);const l=(0,o.WA)("docusaurus.announcement.dismiss"),c=(0,o.WA)("docusaurus.announcement.id"),u=()=>"true"===l.get(),d=e=>l.set(String(e)),f=r.createContext(null);function p(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,s.L)(),t=(0,a.Z)(),[n,o]=(0,r.useState)((()=>!!t&&u()));(0,r.useEffect)((()=>{o(u())}),[]);const i=(0,r.useCallback)((()=>{d(!0),o(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=c.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;c.set(t),r&&d(!1),!r&&u()||o(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return r.createElement(f.Provider,{value:n},t)}function g(){const e=(0,r.useContext)(f);if(!e)throw new i.i6("AnnouncementBarProvider");return e}},2949:(e,t,n)=>{"use strict";n.d(t,{I:()=>h,S:()=>m});var r=n(7294),a=n(412),o=n(902),i=n(12),s=n(6668);const l=r.createContext(void 0),c="theme",u=(0,i.WA)(c),d={light:"light",dark:"dark"},f=e=>e===d.dark?d.dark:d.light,p=e=>a.Z.canUseDOM?f(document.documentElement.getAttribute("data-theme")):f(e),g=e=>{u.set(f(e))};function m(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,s.L)(),[a,o]=(0,r.useState)(p(e));(0,r.useEffect)((()=>{t&&u.del()}),[t]);const i=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:a=!0}=r;t?(o(t),a&&g(t)):(o(n?window.matchMedia("(prefers-color-scheme: dark)").matches?d.dark:d.light:e),u.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",f(a))}),[a]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==c)return;const t=u.get();null!==t&&i(f(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,i]);const l=(0,r.useRef)(!1);return(0,r.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{window.matchMedia("print").matches||l.current?l.current=window.matchMedia("print").matches:i(null)};return e.addListener(r),()=>e.removeListener(r)}),[i,t,n]),(0,r.useMemo)((()=>({colorMode:a,setColorMode:i,get isDarkTheme(){return a===d.dark},setLightTheme(){i(d.light)},setDarkTheme(){i(d.dark)}})),[a,i])}();return r.createElement(l.Provider,{value:n},t)}function h(){const e=(0,r.useContext)(l);if(null==e)throw new o.i6("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},373:(e,t,n)=>{"use strict";n.d(t,{J:()=>v,L5:()=>h,Oh:()=>y});var r=n(7294),a=n(143),o=n(9935),i=n(6668),s=n(2802),l=n(902),c=n(12);const u=e=>`docs-preferred-version-${e}`,d={save:(e,t,n)=>{(0,c.WA)(u(e),{persistence:t}).set(n)},read:(e,t)=>(0,c.WA)(u(e),{persistence:t}).get(),clear:(e,t)=>{(0,c.WA)(u(e),{persistence:t}).del()}},f=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const p=r.createContext(null);function g(){const e=(0,a._r)(),t=(0,i.L)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[o,s]=(0,r.useState)((()=>f(n)));(0,r.useEffect)((()=>{s(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function a(e){const t=d.read(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(d.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,a(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[o,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){d.save(e,t,n),s((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function m(e){let{children:t}=e;const n=g();return r.createElement(p.Provider,{value:n},t)}function h(e){let{children:t}=e;return s.cE?r.createElement(m,null,t):r.createElement(r.Fragment,null,t)}function b(){const e=(0,r.useContext)(p);if(!e)throw new l.i6("DocsPreferredVersionContextProvider");return e}function v(e){void 0===e&&(e=o.m);const t=(0,a.zh)(e),[n,i]=b(),{preferredVersionName:s}=n[e];return{preferredVersion:t.versions.find((e=>e.name===s))??null,savePreferredVersionName:(0,r.useCallback)((t=>{i.savePreferredVersion(e,t)}),[i,e])}}function y(){const e=(0,a._r)(),[t]=b();function n(n){const r=e[n],{preferredVersionName:a}=t[n];return r.versions.find((e=>e.name===a))??null}const r=Object.keys(e);return Object.fromEntries(r.map((e=>[e,n(e)])))}},1116:(e,t,n)=>{"use strict";n.d(t,{V:()=>l,b:()=>s});var r=n(7294),a=n(902);const o=Symbol("EmptyContext"),i=r.createContext(o);function s(e){let{children:t,name:n,items:a}=e;const o=(0,r.useMemo)((()=>n&&a?{name:n,items:a}:null),[n,a]);return r.createElement(i.Provider,{value:o},t)}function l(){const e=(0,r.useContext)(i);if(e===o)throw new a.i6("DocsSidebarProvider");return e}},3163:(e,t,n)=>{"use strict";n.d(t,{M:()=>d,e:()=>f});var r=n(7294),a=n(3102),o=n(7524),i=n(1980),s=n(6668),l=n(902);const c=r.createContext(void 0);function u(){const e=function(){const e=(0,a.HY)(),{items:t}=(0,s.L)().navbar;return 0===t.length&&!e.component}(),t=(0,o.i)(),n=!e&&"mobile"===t,[l,c]=(0,r.useState)(!1);(0,i.Rb)((()=>{if(l)return c(!1),!1}));const u=(0,r.useCallback)((()=>{c((e=>!e))}),[]);return(0,r.useEffect)((()=>{"desktop"===t&&c(!1)}),[t]),(0,r.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:l})),[e,n,u,l])}function d(e){let{children:t}=e;const n=u();return r.createElement(c.Provider,{value:n},t)}function f(){const e=r.useContext(c);if(void 0===e)throw new l.i6("NavbarMobileSidebarProvider");return e}},3102:(e,t,n)=>{"use strict";n.d(t,{HY:()=>s,Zo:()=>l,n2:()=>i});var r=n(7294),a=n(902);const o=r.createContext(null);function i(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return r.createElement(o.Provider,{value:n},t)}function s(){const e=(0,r.useContext)(o);if(!e)throw new a.i6("NavbarSecondaryMenuContentProvider");return e[0]}function l(e){let{component:t,props:n}=e;const i=(0,r.useContext)(o);if(!i)throw new a.i6("NavbarSecondaryMenuContentProvider");const[,s]=i,l=(0,a.Ql)(n);return(0,r.useEffect)((()=>{s({component:t,props:l})}),[s,t,l]),(0,r.useEffect)((()=>()=>s({component:null,props:null})),[s]),null}},9727:(e,t,n)=>{"use strict";n.d(t,{h:()=>a,t:()=>o});var r=n(7294);const a="navigation-with-keyboard";function o(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(a),"mousedown"===e.type&&document.body.classList.remove(a)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(a),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},6177:(e,t,n)=>{"use strict";n.d(t,{K:()=>s,M:()=>l});var r=n(7294),a=n(2263),o=n(1980);const i="q";function s(){return(0,o.Nc)(i)}function l(){const{siteConfig:{baseUrl:e,themeConfig:t}}=(0,a.Z)(),{algolia:{searchPagePath:n}}=t;return(0,r.useCallback)((t=>`${e}${n}?${i}=${encodeURIComponent(t)}`),[e,n])}},7524:(e,t,n)=>{"use strict";n.d(t,{i:()=>c});var r=n(7294),a=n(412);const o={desktop:"desktop",mobile:"mobile",ssr:"ssr"},i=996;function s(){return a.Z.canUseDOM?window.innerWidth>i?o.desktop:o.mobile:o.ssr}const l=!1;function c(){const[e,t]=(0,r.useState)((()=>l?"ssr":s()));return(0,r.useEffect)((()=>{function e(){t(s())}const n=l?window.setTimeout(e,1e3):void 0;return window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e),clearTimeout(n)}}),[]),e}},5281:(e,t,n)=>{"use strict";n.d(t,{k:()=>r});const r={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{}}},1442:(e,t,n)=>{"use strict";function r(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{n:()=>r})},2802:(e,t,n)=>{"use strict";n.d(t,{Wl:()=>f,_F:()=>m,cE:()=>d,hI:()=>k,lO:()=>v,vY:()=>w,oz:()=>y,s1:()=>b});var r=n(7294),a=n(6550),o=n(8790),i=n(143),s=n(373),l=n(1116);function c(e){return Array.from(new Set(e))}var u=n(8596);const d=!!i._r;function f(e){if(e.href)return e.href;for(const t of e.items){if("link"===t.type)return t.href;if("category"===t.type){const e=f(t);if(e)return e}}}const p=(e,t)=>void 0!==e&&(0,u.Mg)(e,t),g=(e,t)=>e.some((e=>m(e,t)));function m(e,t){return"link"===e.type?p(e.href,t):"category"===e.type&&(p(e.href,t)||g(e.items,t))}function h(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const a=[];return function e(t){for(const o of t)if("category"===o.type&&((0,u.Mg)(o.href,n)||e(o.items))||"link"===o.type&&(0,u.Mg)(o.href,n)){return r&&"category"!==o.type||a.unshift(o),!0}return!1}(t),a}function b(){const e=(0,l.V)(),{pathname:t}=(0,a.TH)(),n=(0,i.gA)()?.pluginData.breadcrumbs;return!1!==n&&e?h({sidebarItems:e.items,pathname:t}):null}function v(e){const{activeVersion:t}=(0,i.Iw)(e),{preferredVersion:n}=(0,s.J)(e),a=(0,i.yW)(e);return(0,r.useMemo)((()=>c([t,n,a].filter(Boolean))),[t,n,a])}function y(e,t){const n=v(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),r=t.find((t=>t[0]===e));if(!r)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable sidebar ids are:\n- ${t.map((e=>e[0])).join("\n- ")}`);return r[1]}),[e,n])}function w(e,t){const n=v(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),r=t.find((t=>t.id===e));if(!r){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`Couldn't find any doc with id "${e}" in version${n.length>1?"s":""} "${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${c(t.map((e=>e.id))).join("\n- ")}`)}return r}),[e,n])}function k(e){let{route:t,versionMetadata:n}=e;const r=(0,a.TH)(),i=t.routes,s=i.find((e=>(0,a.LX)(r.pathname,e)));if(!s)return null;const l=s.sidebar,c=l?n.docsSidebars[l]:void 0;return{docElement:(0,o.H)(i),sidebarName:l,sidebarItems:c}}},2128:(e,t,n)=>{"use strict";n.d(t,{p:()=>a});var r=n(2263);function a(e){const{siteConfig:t}=(0,r.Z)(),{title:n,titleDelimiter:a}=t;return e?.trim().length?`${e.trim()} ${a} ${n}`:n}},1980:(e,t,n)=>{"use strict";n.d(t,{Nc:()=>c,Rb:()=>s});var r=n(7294),a=n(6550),o=n(1688),i=n(902);function s(e){!function(e){const t=(0,a.k6)(),n=(0,i.zX)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}function l(e){return function(e){const t=(0,a.k6)();return(0,o.useSyncExternalStore)(t.listen,(()=>e(t)),(()=>e(t)))}((t=>null===e?null:new URLSearchParams(t.location.search).get(e)))}function c(e){const t=l(e)??"",n=function(){const e=(0,a.k6)();return(0,r.useCallback)(((t,n,r)=>{const a=new URLSearchParams(e.location.search);n?a.set(t,n):a.delete(t),(r?.push?e.push:e.replace)({search:a.toString()})}),[e])}();return[t,(0,r.useCallback)(((t,r)=>{n(e,t,r)}),[n,e])]}},833:(e,t,n)=>{"use strict";n.d(t,{FG:()=>f,d:()=>u,VC:()=>p});var r=n(7294),a=n(6010),o=n(5742),i=n(226);function s(){const e=r.useContext(i._);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var l=n(4996),c=n(2128);function u(e){let{title:t,description:n,keywords:a,image:i,children:s}=e;const u=(0,c.p)(t),{withBaseUrl:d}=(0,l.C)(),f=i?d(i,{absolute:!0}):void 0;return r.createElement(o.Z,null,t&&r.createElement("title",null,u),t&&r.createElement("meta",{property:"og:title",content:u}),n&&r.createElement("meta",{name:"description",content:n}),n&&r.createElement("meta",{property:"og:description",content:n}),a&&r.createElement("meta",{name:"keywords",content:Array.isArray(a)?a.join(","):a}),f&&r.createElement("meta",{property:"og:image",content:f}),f&&r.createElement("meta",{name:"twitter:image",content:f}),s)}const d=r.createContext(void 0);function f(e){let{className:t,children:n}=e;const i=r.useContext(d),s=(0,a.Z)(i,t);return r.createElement(d.Provider,{value:s},r.createElement(o.Z,null,r.createElement("html",{className:s})),n)}function p(e){let{children:t}=e;const n=s(),o=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const i=`plugin-id-${n.plugin.id}`;return r.createElement(f,{className:(0,a.Z)(o,i)},t)}},902:(e,t,n)=>{"use strict";n.d(t,{D9:()=>i,Qc:()=>c,Ql:()=>l,i6:()=>s,zX:()=>o});var r=n(7294);const a=n(412).Z.canUseDOM?r.useLayoutEffect:r.useEffect;function o(e){const t=(0,r.useRef)(e);return a((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function i(e){const t=(0,r.useRef)();return a((()=>{t.current=e})),t.current}class s extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function l(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function c(e){return t=>{let{children:n}=t;return r.createElement(r.Fragment,null,e.reduceRight(((e,t)=>r.createElement(t,null,e)),n))}}},8022:(e,t,n)=>{"use strict";function r(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}n.d(t,{F:()=>r})},8596:(e,t,n)=>{"use strict";n.d(t,{Mg:()=>i,Ns:()=>s});var r=n(7294),a=n(723),o=n(2263);function i(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function s(){const{baseUrl:e}=(0,o.Z)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function a(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(a).flatMap((e=>e.routes??[])))}(n)}({routes:a.Z,baseUrl:e})),[e])}},2466:(e,t,n)=>{"use strict";n.d(t,{Ct:()=>f,OC:()=>l,RF:()=>d});var r=n(7294),a=n(412),o=n(2389),i=n(902);const s=r.createContext(void 0);function l(e){let{children:t}=e;const n=function(){const e=(0,r.useRef)(!0);return(0,r.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return r.createElement(s.Provider,{value:n},t)}function c(){const e=(0,r.useContext)(s);if(null==e)throw new i.i6("ScrollControllerProvider");return e}const u=()=>a.Z.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function d(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=c(),a=(0,r.useRef)(u()),o=(0,i.zX)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=u();o(e,a.current),a.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[o,n,...t])}function f(){const e=(0,r.useRef)(null),t=(0,o.Z)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function r(){const a=document.documentElement.scrollTop;(n&&a>e||!n&&at&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},3320:(e,t,n)=>{"use strict";n.d(t,{HX:()=>i,_q:()=>l,os:()=>s});var r=n(143),a=n(2263),o=n(373);const i="default";function s(e,t){return`docs-${e}-${t}`}function l(){const{i18n:e}=(0,a.Z)(),t=(0,r._r)(),n=(0,r.WS)(),l=(0,o.Oh)();const c=[i,...Object.keys(t).map((function(e){const r=n?.activePlugin.pluginId===e?n.activeVersion:void 0,a=l[e],o=t[e].versions.find((e=>e.isLast));return s(e,(r??a??o).name)}))];return{locale:e.currentLocale,tags:c}}},12:(e,t,n)=>{"use strict";n.d(t,{WA:()=>l});n(7294),n(1688);const r="localStorage";function a(e){let{key:t,oldValue:n,newValue:r,storage:a}=e;if(n===r)return;const o=document.createEvent("StorageEvent");o.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,a),window.dispatchEvent(o)}function o(e){if(void 0===e&&(e=r),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,i||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),i=!0),null}var t}let i=!1;const s={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function l(e,t){if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(e);const n=o(t?.persistence);return null===n?s:{get:()=>{try{return n.getItem(e)}catch(t){return console.error(`Docusaurus storage error, can't get key=${e}`,t),null}},set:t=>{try{const r=n.getItem(e);n.setItem(e,t),a({key:e,oldValue:r,newValue:t,storage:n})}catch(r){console.error(`Docusaurus storage error, can't set ${e}=${t}`,r)}},del:()=>{try{const t=n.getItem(e);n.removeItem(e),a({key:e,oldValue:t,newValue:null,storage:n})}catch(t){console.error(`Docusaurus storage error, can't delete key=${e}`,t)}},listen:t=>{try{const r=r=>{r.storageArea===n&&r.key===e&&t(r)};return window.addEventListener("storage",r),()=>window.removeEventListener("storage",r)}catch(r){return console.error(`Docusaurus storage error, can't listen for changes of key=${e}`,r),()=>{}}}}}},4711:(e,t,n)=>{"use strict";n.d(t,{l:()=>o});var r=n(2263),a=n(6550);function o(){const{siteConfig:{baseUrl:e,url:t},i18n:{defaultLocale:n,currentLocale:o}}=(0,r.Z)(),{pathname:i}=(0,a.TH)(),s=o===n?e:e.replace(`/${o}/`,"/"),l=i.replace(e,"");return{createUrl:function(e){let{locale:r,fullyQualified:a}=e;return`${a?t:""}${function(e){return e===n?`${s}`:`${s}${e}/`}(r)}${l}`}}}},5936:(e,t,n)=>{"use strict";n.d(t,{S:()=>i});var r=n(7294),a=n(6550),o=n(902);function i(e){const t=(0,a.TH)(),n=(0,o.D9)(t),i=(0,o.zX)(e);(0,r.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},6668:(e,t,n)=>{"use strict";n.d(t,{L:()=>a});var r=n(2263);function a(){return(0,r.Z)().siteConfig.themeConfig}},6278:(e,t,n)=>{"use strict";n.d(t,{L:()=>a});var r=n(2263);function a(){const{siteConfig:{themeConfig:e}}=(0,r.Z)();return e}},239:(e,t,n)=>{"use strict";n.d(t,{l:()=>s});var r=n(7294),a=n(8022),o=n(4996),i=n(6278);function s(){const{withBaseUrl:e}=(0,o.C)(),{algolia:{externalUrlRegex:t,replaceSearchResultPathname:n}}=(0,i.L)();return(0,r.useCallback)((r=>{const o=new URL(r);if((0,a.F)(t,o.href))return r;const i=`${o.pathname+o.hash}`;return e(function(e,t){return t?e.replaceAll(new RegExp(t.from,"g"),t.to):e}(i,n))}),[e,t,n])}},8802:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[a]=e.split(/[#?]/),o="/"===a||a===r?a:(i=a,n?function(e){return e.endsWith("/")?e:`${e}/`}(i):function(e){return e.endsWith("/")?e.slice(0,-1):e}(i));var i;return e.replace(a,o)}},4143:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=void 0,t.getErrorCausalChain=function e(t){return t.cause?[t,...e(t.cause)]:[t]}},8780:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="__blog-post-container";var a=n(8802);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return r(a).default}});var o=n(4143);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return o.getErrorCausalChain}})},6010:(e,t,n)=>{"use strict";function r(e){var t,n,a="";if("string"==typeof e||"number"==typeof e)a+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;ta});const a=function(){for(var e,t,n=0,a="";n{"use strict";n.d(t,{lX:()=>w,q_:()=>C,ob:()=>p,PP:()=>L,Ep:()=>f});var r=n(7462);function a(e){return"/"===e.charAt(0)}function o(e,t){for(var n=t,r=n+1,a=e.length;r=0;f--){var p=i[f];"."===p?o(i,f):".."===p?(o(i,f),d++):d&&(o(i,f),d--)}if(!c)for(;d--;d)i.unshift("..");!c||""===i[0]||i[0]&&a(i[0])||i.unshift("");var g=i.join("/");return n&&"/"!==g.substr(-1)&&(g+="/"),g};var s=n(8776);function l(e){return"/"===e.charAt(0)?e:"/"+e}function c(e){return"/"===e.charAt(0)?e.substr(1):e}function u(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function f(e){var t=e.pathname,n=e.search,r=e.hash,a=t||"/";return n&&"?"!==n&&(a+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(a+="#"===r.charAt(0)?r:"#"+r),a}function p(e,t,n,a){var o;"string"==typeof e?(o=function(e){var t=e||"/",n="",r="",a=t.indexOf("#");-1!==a&&(r=t.substr(a),t=t.substr(0,a));var o=t.indexOf("?");return-1!==o&&(n=t.substr(o),t=t.substr(0,o)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),o.state=t):(void 0===(o=(0,r.Z)({},e)).pathname&&(o.pathname=""),o.search?"?"!==o.search.charAt(0)&&(o.search="?"+o.search):o.search="",o.hash?"#"!==o.hash.charAt(0)&&(o.hash="#"+o.hash):o.hash="",void 0!==t&&void 0===o.state&&(o.state=t));try{o.pathname=decodeURI(o.pathname)}catch(s){throw s instanceof URIError?new URIError('Pathname "'+o.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):s}return n&&(o.key=n),a?o.pathname?"/"!==o.pathname.charAt(0)&&(o.pathname=i(o.pathname,a.pathname)):o.pathname=a.pathname:o.pathname||(o.pathname="/"),o}function g(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,a){if(null!=e){var o="function"==typeof e?e(t,n):e;"string"==typeof o?"function"==typeof r?r(o,a):a(!0):a(!1!==o)}else a(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;rt?n.splice(t,n.length-t,a):n.push(a),d({action:r,location:a,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",a=p(e,t,m(),w.location);u.confirmTransitionTo(a,r,n,(function(e){e&&(w.entries[w.index]=a,d({action:r,location:a}))}))},go:y,goBack:function(){y(-1)},goForward:function(){y(1)},canGo:function(e){var t=w.index+e;return t>=0&&t{"use strict";var r=n(9864),a={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},o={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},s={};function l(e){return r.isMemo(e)?i:s[e.$$typeof]||a}s[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},s[r.Memo]=i;var c=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,g=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(g){var a=p(n);a&&a!==g&&e(t,a,r)}var i=u(n);d&&(i=i.concat(d(n)));for(var s=l(t),m=l(n),h=0;h{"use strict";e.exports=function(e,t,n,r,a,o,i,s){if(!e){var l;if(void 0===t)l=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,r,a,o,i,s],u=0;(l=new Error(t.replace(/%s/g,(function(){return c[u++]})))).name="Invariant Violation"}throw l.framesToPop=1,l}}},5826:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},2497:(e,t,n)=>{"use strict";n.r(t)},2295:(e,t,n)=>{"use strict";n.r(t)},4865:function(e,t,n){var r,a;r=function(){var e,t,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
'};function a(e,t,n){return en?n:e}function o(e){return 100*(-1+e)}function i(e,t,n){var a;return(a="translate3d"===r.positionUsing?{transform:"translate3d("+o(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+o(e)+"%,0)"}:{"margin-left":o(e)+"%"}).transition="all "+t+"ms "+n,a}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=a(e,r.minimum,1),n.status=1===e?null:e;var o=n.render(!t),c=o.querySelector(r.barSelector),u=r.speed,d=r.easing;return o.offsetWidth,s((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),l(c,i(e,u,d)),1===e?(l(o,{transition:"none",opacity:1}),o.offsetWidth,setTimeout((function(){l(o,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*a(Math.random()*t,.1,.95)),t=a(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var a,i=t.querySelector(r.barSelector),s=e?"-100":o(n.status||0),c=document.querySelector(r.parent);return l(i,{transition:"all 0 linear",transform:"translate3d("+s+"%,0,0)"}),r.showSpinner||(a=t.querySelector(r.spinnerSelector))&&p(a),c!=document.body&&u(c,"nprogress-custom-parent"),c.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&p(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var s=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),l=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;for(var r,a=e.length,o=t.charAt(0).toUpperCase()+t.slice(1);a--;)if((r=e[a]+o)in n)return r;return t}function a(e){return e=n(e),t[e]||(t[e]=r(e))}function o(e,t,n){t=a(t),e.style[t]=n}return function(e,t){var n,r,a=arguments;if(2==a.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&o(e,n,r);else o(e,a[1],a[2])}}();function c(e,t){return("string"==typeof e?e:f(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=f(e),r=n+t;c(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=f(e);c(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function f(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function p(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(a="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=a)},7418:e=>{"use strict";var t=Object.getOwnPropertySymbols,n=Object.prototype.hasOwnProperty,r=Object.prototype.propertyIsEnumerable;e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(a){return!1}}()?Object.assign:function(e,a){for(var o,i,s=function(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}(e),l=1;l{"use strict";n.d(t,{Z:()=>o});var r=function(){var e=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,t=0,n={},r={util:{encode:function e(t){return t instanceof a?new a(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/=d.reach);_+=E.value.length,E=E.next){var S=E.value;if(t.length>e.length)return;if(!(S instanceof a)){var x,C=1;if(v){if(!(x=o(k,_,e,b))||x.index>=e.length)break;var T=x.index,L=x.index+x[0].length,A=_;for(A+=E.value.length;T>=A;)A+=(E=E.next).value.length;if(_=A-=E.value.length,E.value instanceof a)continue;for(var R=E;R!==t.tail&&(Ad.reach&&(d.reach=I);var D=E.prev;if(N&&(D=l(t,D,N),_+=N.length),c(t,D,C),E=l(t,D,new a(f,h?r.tokenize(O,h):O,y,O)),P&&l(t,E,P),C>1){var M={cause:f+","+g,reach:I};i(e,t,n,E.prev,_,M),d&&M.reach>d.reach&&(d.reach=M.reach)}}}}}}function s(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function l(e,t,n){var r=t.next,a={value:n,prev:t,next:r};return t.next=a,r.prev=a,e.length++,a}function c(e,t,n){for(var r=t.next,a=0;a"+o.content+""},r}(),a=r;r.default=r,a.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},a.languages.markup.tag.inside["attr-value"].inside.entity=a.languages.markup.entity,a.languages.markup.doctype.inside["internal-subset"].inside=a.languages.markup,a.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(a.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:a.languages[t]},n.cdata=/^$/i;var r={"included-cdata":{pattern://i,inside:n}};r["language-"+t]={pattern:/[\s\S]+/,inside:a.languages[t]};var o={};o[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:r},a.languages.insertBefore("markup","cdata",o)}}),Object.defineProperty(a.languages.markup.tag,"addAttribute",{value:function(e,t){a.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:a.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),a.languages.html=a.languages.markup,a.languages.mathml=a.languages.markup,a.languages.svg=a.languages.markup,a.languages.xml=a.languages.extend("markup",{}),a.languages.ssml=a.languages.xml,a.languages.atom=a.languages.xml,a.languages.rss=a.languages.xml,function(e){var t="\\b(?:BASH|BASHOPTS|BASH_ALIASES|BASH_ARGC|BASH_ARGV|BASH_CMDS|BASH_COMPLETION_COMPAT_DIR|BASH_LINENO|BASH_REMATCH|BASH_SOURCE|BASH_VERSINFO|BASH_VERSION|COLORTERM|COLUMNS|COMP_WORDBREAKS|DBUS_SESSION_BUS_ADDRESS|DEFAULTS_PATH|DESKTOP_SESSION|DIRSTACK|DISPLAY|EUID|GDMSESSION|GDM_LANG|GNOME_KEYRING_CONTROL|GNOME_KEYRING_PID|GPG_AGENT_INFO|GROUPS|HISTCONTROL|HISTFILE|HISTFILESIZE|HISTSIZE|HOME|HOSTNAME|HOSTTYPE|IFS|INSTANCE|JOB|LANG|LANGUAGE|LC_ADDRESS|LC_ALL|LC_IDENTIFICATION|LC_MEASUREMENT|LC_MONETARY|LC_NAME|LC_NUMERIC|LC_PAPER|LC_TELEPHONE|LC_TIME|LESSCLOSE|LESSOPEN|LINES|LOGNAME|LS_COLORS|MACHTYPE|MAILCHECK|MANDATORY_PATH|NO_AT_BRIDGE|OLDPWD|OPTERR|OPTIND|ORBIT_SOCKETDIR|OSTYPE|PAPERSIZE|PATH|PIPESTATUS|PPID|PS1|PS2|PS3|PS4|PWD|RANDOM|REPLY|SECONDS|SELINUX_INIT|SESSION|SESSIONTYPE|SESSION_MANAGER|SHELL|SHELLOPTS|SHLVL|SSH_AUTH_SOCK|TERM|UID|UPSTART_EVENTS|UPSTART_INSTANCE|UPSTART_JOB|UPSTART_SESSION|USER|WINDOWID|XAUTHORITY|XDG_CONFIG_DIRS|XDG_CURRENT_DESKTOP|XDG_DATA_DIRS|XDG_GREETER_DATA_DIR|XDG_MENU_PREFIX|XDG_RUNTIME_DIR|XDG_SEAT|XDG_SEAT_PATH|XDG_SESSION_DESKTOP|XDG_SESSION_ID|XDG_SESSION_PATH|XDG_SESSION_TYPE|XDG_VTNR|XMODIFIERS)\\b",n={pattern:/(^(["']?)\w+\2)[ \t]+\S.*/,lookbehind:!0,alias:"punctuation",inside:null},r={bash:n,environment:{pattern:RegExp("\\$"+t),alias:"constant"},variable:[{pattern:/\$?\(\([\s\S]+?\)\)/,greedy:!0,inside:{variable:[{pattern:/(^\$\(\([\s\S]+)\)\)/,lookbehind:!0},/^\$\(\(/],number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee]-?\d+)?/,operator:/--|\+\+|\*\*=?|<<=?|>>=?|&&|\|\||[=!+\-*/%<>^&|]=?|[?~:]/,punctuation:/\(\(?|\)\)?|,|;/}},{pattern:/\$\((?:\([^)]+\)|[^()])+\)|`[^`]+`/,greedy:!0,inside:{variable:/^\$\(|^`|\)$|`$/}},{pattern:/\$\{[^}]+\}/,greedy:!0,inside:{operator:/:[-=?+]?|[!\/]|##?|%%?|\^\^?|,,?/,punctuation:/[\[\]]/,environment:{pattern:RegExp("(\\{)"+t),lookbehind:!0,alias:"constant"}}},/\$(?:\w+|[#?*!@$])/],entity:/\\(?:[abceEfnrtv\\"]|O?[0-7]{1,3}|U[0-9a-fA-F]{8}|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{1,2})/};e.languages.bash={shebang:{pattern:/^#!\s*\/.*/,alias:"important"},comment:{pattern:/(^|[^"{\\$])#.*/,lookbehind:!0},"function-name":[{pattern:/(\bfunction\s+)[\w-]+(?=(?:\s*\(?:\s*\))?\s*\{)/,lookbehind:!0,alias:"function"},{pattern:/\b[\w-]+(?=\s*\(\s*\)\s*\{)/,alias:"function"}],"for-or-select":{pattern:/(\b(?:for|select)\s+)\w+(?=\s+in\s)/,alias:"variable",lookbehind:!0},"assign-left":{pattern:/(^|[\s;|&]|[<>]\()\w+(?=\+?=)/,inside:{environment:{pattern:RegExp("(^|[\\s;|&]|[<>]\\()"+t),lookbehind:!0,alias:"constant"}},alias:"variable",lookbehind:!0},string:[{pattern:/((?:^|[^<])<<-?\s*)(\w+)\s[\s\S]*?(?:\r?\n|\r)\2/,lookbehind:!0,greedy:!0,inside:r},{pattern:/((?:^|[^<])<<-?\s*)(["'])(\w+)\2\s[\s\S]*?(?:\r?\n|\r)\3/,lookbehind:!0,greedy:!0,inside:{bash:n}},{pattern:/(^|[^\\](?:\\\\)*)"(?:\\[\s\S]|\$\([^)]+\)|\$(?!\()|`[^`]+`|[^"\\`$])*"/,lookbehind:!0,greedy:!0,inside:r},{pattern:/(^|[^$\\])'[^']*'/,lookbehind:!0,greedy:!0},{pattern:/\$'(?:[^'\\]|\\[\s\S])*'/,greedy:!0,inside:{entity:r.entity}}],environment:{pattern:RegExp("\\$?"+t),alias:"constant"},variable:r.variable,function:{pattern:/(^|[\s;|&]|[<>]\()(?:add|apropos|apt|apt-cache|apt-get|aptitude|aspell|automysqlbackup|awk|basename|bash|bc|bconsole|bg|bzip2|cal|cat|cfdisk|chgrp|chkconfig|chmod|chown|chroot|cksum|clear|cmp|column|comm|composer|cp|cron|crontab|csplit|curl|cut|date|dc|dd|ddrescue|debootstrap|df|diff|diff3|dig|dir|dircolors|dirname|dirs|dmesg|docker|docker-compose|du|egrep|eject|env|ethtool|expand|expect|expr|fdformat|fdisk|fg|fgrep|file|find|fmt|fold|format|free|fsck|ftp|fuser|gawk|git|gparted|grep|groupadd|groupdel|groupmod|groups|grub-mkconfig|gzip|halt|head|hg|history|host|hostname|htop|iconv|id|ifconfig|ifdown|ifup|import|install|ip|jobs|join|kill|killall|less|link|ln|locate|logname|logrotate|look|lpc|lpr|lprint|lprintd|lprintq|lprm|ls|lsof|lynx|make|man|mc|mdadm|mkconfig|mkdir|mke2fs|mkfifo|mkfs|mkisofs|mknod|mkswap|mmv|more|most|mount|mtools|mtr|mutt|mv|nano|nc|netstat|nice|nl|node|nohup|notify-send|npm|nslookup|op|open|parted|passwd|paste|pathchk|ping|pkill|pnpm|podman|podman-compose|popd|pr|printcap|printenv|ps|pushd|pv|quota|quotacheck|quotactl|ram|rar|rcp|reboot|remsync|rename|renice|rev|rm|rmdir|rpm|rsync|scp|screen|sdiff|sed|sendmail|seq|service|sftp|sh|shellcheck|shuf|shutdown|sleep|slocate|sort|split|ssh|stat|strace|su|sudo|sum|suspend|swapon|sync|tac|tail|tar|tee|time|timeout|top|touch|tr|traceroute|tsort|tty|umount|uname|unexpand|uniq|units|unrar|unshar|unzip|update-grub|uptime|useradd|userdel|usermod|users|uudecode|uuencode|v|vcpkg|vdir|vi|vim|virsh|vmstat|wait|watch|wc|wget|whereis|which|who|whoami|write|xargs|xdg-open|yarn|yes|zenity|zip|zsh|zypper)(?=$|[)\s;|&])/,lookbehind:!0},keyword:{pattern:/(^|[\s;|&]|[<>]\()(?:case|do|done|elif|else|esac|fi|for|function|if|in|select|then|until|while)(?=$|[)\s;|&])/,lookbehind:!0},builtin:{pattern:/(^|[\s;|&]|[<>]\()(?:\.|:|alias|bind|break|builtin|caller|cd|command|continue|declare|echo|enable|eval|exec|exit|export|getopts|hash|help|let|local|logout|mapfile|printf|pwd|read|readarray|readonly|return|set|shift|shopt|source|test|times|trap|type|typeset|ulimit|umask|unalias|unset)(?=$|[)\s;|&])/,lookbehind:!0,alias:"class-name"},boolean:{pattern:/(^|[\s;|&]|[<>]\()(?:false|true)(?=$|[)\s;|&])/,lookbehind:!0},"file-descriptor":{pattern:/\B&\d\b/,alias:"important"},operator:{pattern:/\d?<>|>\||\+=|=[=~]?|!=?|<<[<-]?|[&\d]?>>|\d[<>]&?|[<>][&=]?|&[>&]?|\|[&|]?/,inside:{"file-descriptor":{pattern:/^\d/,alias:"important"}}},punctuation:/\$?\(\(?|\)\)?|\.\.|[{}[\];\\]/,number:{pattern:/(^|\s)(?:[1-9]\d*|0)(?:[.,]\d+)?\b/,lookbehind:!0}},n.inside=e.languages.bash;for(var a=["comment","function-name","for-or-select","assign-left","string","environment","function","keyword","builtin","boolean","file-descriptor","operator","punctuation","number"],o=r.variable[1].inside,i=0;i]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},a.languages.c=a.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),a.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),a.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},a.languages.c.string],char:a.languages.c.char,comment:a.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:a.languages.c}}}}),a.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete a.languages.c.boolean,function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!)\w+(?:\s*\.\s*\w+)*\b/.source.replace(//g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!)\w+/.source.replace(//g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/(?:\s*:\s*)?|:\s*/.source.replace(//g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(a),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}(a),function(e){var t,n=/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/;e.languages.css.selector={pattern:e.languages.css.selector.pattern,lookbehind:!0,inside:t={"pseudo-element":/:(?:after|before|first-letter|first-line|selection)|::[-\w]+/,"pseudo-class":/:[-\w]+/,class:/\.[-\w]+/,id:/#[-\w]+/,attribute:{pattern:RegExp("\\[(?:[^[\\]\"']|"+n.source+")*\\]"),greedy:!0,inside:{punctuation:/^\[|\]$/,"case-sensitivity":{pattern:/(\s)[si]$/i,lookbehind:!0,alias:"keyword"},namespace:{pattern:/^(\s*)(?:(?!\s)[-*\w\xA0-\uFFFF])*\|(?!=)/,lookbehind:!0,inside:{punctuation:/\|$/}},"attr-name":{pattern:/^(\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+/,lookbehind:!0},"attr-value":[n,{pattern:/(=\s*)(?:(?!\s)[-\w\xA0-\uFFFF])+(?=\s*$)/,lookbehind:!0}],operator:/[|~*^$]?=/}},"n-th":[{pattern:/(\(\s*)[+-]?\d*[\dn](?:\s*[+-]\s*\d+)?(?=\s*\))/,lookbehind:!0,inside:{number:/[\dn]+/,operator:/[+-]/}},{pattern:/(\(\s*)(?:even|odd)(?=\s*\))/i,lookbehind:!0}],combinator:/>|\+|~|\|\|/,punctuation:/[(),]/}},e.languages.css.atrule.inside["selector-function-argument"].inside=t,e.languages.insertBefore("css","property",{variable:{pattern:/(^|[^-\w\xA0-\uFFFF])--(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*/i,lookbehind:!0}});var r={pattern:/(\b\d+)(?:%|[a-z]+(?![\w-]))/,lookbehind:!0},a={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0};e.languages.insertBefore("css","function",{operator:{pattern:/(\s)[+\-*\/](?=\s)/,lookbehind:!0},hexcode:{pattern:/\B#[\da-f]{3,8}\b/i,alias:"color"},color:[{pattern:/(^|[^\w-])(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)(?![\w-])/i,lookbehind:!0},{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:r,number:a,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:r,number:a})}(a),a.languages.javascript=a.languages.extend("clike",{"class-name":[a.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),a.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,a.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:a.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:a.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:a.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:a.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:a.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),a.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:a.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),a.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),a.languages.markup&&(a.languages.markup.tag.addInlined("script","javascript"),a.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),a.languages.js=a.languages.javascript,function(e){var t=/#(?!\{).+/,n={pattern:/#\{[^}]+\}/,alias:"variable"};e.languages.coffeescript=e.languages.extend("javascript",{comment:t,string:[{pattern:/'(?:\\[\s\S]|[^\\'])*'/,greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,greedy:!0,inside:{interpolation:n}}],keyword:/\b(?:and|break|by|catch|class|continue|debugger|delete|do|each|else|extend|extends|false|finally|for|if|in|instanceof|is|isnt|let|loop|namespace|new|no|not|null|of|off|on|or|own|return|super|switch|then|this|throw|true|try|typeof|undefined|unless|until|when|while|window|with|yes|yield)\b/,"class-member":{pattern:/@(?!\d)\w+/,alias:"variable"}}),e.languages.insertBefore("coffeescript","comment",{"multiline-comment":{pattern:/###[\s\S]+?###/,alias:"comment"},"block-regex":{pattern:/\/{3}[\s\S]*?\/{3}/,alias:"regex",inside:{comment:t,interpolation:n}}}),e.languages.insertBefore("coffeescript","string",{"inline-javascript":{pattern:/`(?:\\[\s\S]|[^\\`])*`/,inside:{delimiter:{pattern:/^`|`$/,alias:"punctuation"},script:{pattern:/[\s\S]+/,alias:"language-javascript",inside:e.languages.javascript}}},"multiline-string":[{pattern:/'''[\s\S]*?'''/,greedy:!0,alias:"string"},{pattern:/"""[\s\S]*?"""/,greedy:!0,alias:"string",inside:{interpolation:n}}]}),e.languages.insertBefore("coffeescript","keyword",{property:/(?!\d)\w+(?=\s*:(?!:))/}),delete e.languages.coffeescript["template-string"],e.languages.coffee=e.languages.coffeescript}(a),function(e){var t=/[*&][^\s[\]{},]+/,n=/!(?:<[\w\-%#;/?:@&=+$,.!~*'()[\]]+>|(?:[a-zA-Z\d-]*!)?[\w\-%#;/?:@&=+$.~*'()]+)?/,r="(?:"+n.source+"(?:[ \t]+"+t.source+")?|"+t.source+"(?:[ \t]+"+n.source+")?)",a=/(?:[^\s\x00-\x08\x0e-\x1f!"#%&'*,\-:>?@[\]`{|}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]|[?:-])(?:[ \t]*(?:(?![#:])|:))*/.source.replace(//g,(function(){return/[^\s\x00-\x08\x0e-\x1f,[\]{}\x7f-\x84\x86-\x9f\ud800-\udfff\ufffe\uffff]/.source})),o=/"(?:[^"\\\r\n]|\\.)*"|'(?:[^'\\\r\n]|\\.)*'/.source;function i(e,t){t=(t||"").replace(/m/g,"")+"m";var n=/([:\-,[{]\s*(?:\s<>[ \t]+)?)(?:<>)(?=[ \t]*(?:$|,|\]|\}|(?:[\r\n]\s*)?#))/.source.replace(/<>/g,(function(){return r})).replace(/<>/g,(function(){return e}));return RegExp(n,t)}e.languages.yaml={scalar:{pattern:RegExp(/([\-:]\s*(?:\s<>[ \t]+)?[|>])[ \t]*(?:((?:\r?\n|\r)[ \t]+)\S[^\r\n]*(?:\2[^\r\n]+)*)/.source.replace(/<>/g,(function(){return r}))),lookbehind:!0,alias:"string"},comment:/#.*/,key:{pattern:RegExp(/((?:^|[:\-,[{\r\n?])[ \t]*(?:<>[ \t]+)?)<>(?=\s*:\s)/.source.replace(/<>/g,(function(){return r})).replace(/<>/g,(function(){return"(?:"+a+"|"+o+")"}))),lookbehind:!0,greedy:!0,alias:"atrule"},directive:{pattern:/(^[ \t]*)%.+/m,lookbehind:!0,alias:"important"},datetime:{pattern:i(/\d{4}-\d\d?-\d\d?(?:[tT]|[ \t]+)\d\d?:\d{2}:\d{2}(?:\.\d*)?(?:[ \t]*(?:Z|[-+]\d\d?(?::\d{2})?))?|\d{4}-\d{2}-\d{2}|\d\d?:\d{2}(?::\d{2}(?:\.\d*)?)?/.source),lookbehind:!0,alias:"number"},boolean:{pattern:i(/false|true/.source,"i"),lookbehind:!0,alias:"important"},null:{pattern:i(/null|~/.source,"i"),lookbehind:!0,alias:"important"},string:{pattern:i(o),lookbehind:!0,greedy:!0},number:{pattern:i(/[+-]?(?:0x[\da-f]+|0o[0-7]+|(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?|\.inf|\.nan)/.source,"i"),lookbehind:!0},tag:n,important:t,punctuation:/---|[:[\]{}\-,|>?]|\.\.\./},e.languages.yml=e.languages.yaml}(a),function(e){var t=/(?:\\.|[^\\\n\r]|(?:\n|\r\n?)(?![\r\n]))/.source;function n(e){return e=e.replace(//g,(function(){return t})),RegExp(/((?:^|[^\\])(?:\\{2})*)/.source+"(?:"+e+")")}var r=/(?:\\.|``(?:[^`\r\n]|`(?!`))+``|`[^`\r\n]+`|[^\\|\r\n`])+/.source,a=/\|?__(?:\|__)+\|?(?:(?:\n|\r\n?)|(?![\s\S]))/.source.replace(/__/g,(function(){return r})),o=/\|?[ \t]*:?-{3,}:?[ \t]*(?:\|[ \t]*:?-{3,}:?[ \t]*)+\|?(?:\n|\r\n?)/.source;e.languages.markdown=e.languages.extend("markup",{}),e.languages.insertBefore("markdown","prolog",{"front-matter-block":{pattern:/(^(?:\s*[\r\n])?)---(?!.)[\s\S]*?[\r\n]---(?!.)/,lookbehind:!0,greedy:!0,inside:{punctuation:/^---|---$/,"front-matter":{pattern:/\S+(?:\s+\S+)*/,alias:["yaml","language-yaml"],inside:e.languages.yaml}}},blockquote:{pattern:/^>(?:[\t ]*>)*/m,alias:"punctuation"},table:{pattern:RegExp("^"+a+o+"(?:"+a+")*","m"),inside:{"table-data-rows":{pattern:RegExp("^("+a+o+")(?:"+a+")*$"),lookbehind:!0,inside:{"table-data":{pattern:RegExp(r),inside:e.languages.markdown},punctuation:/\|/}},"table-line":{pattern:RegExp("^("+a+")"+o+"$"),lookbehind:!0,inside:{punctuation:/\||:?-{3,}:?/}},"table-header-row":{pattern:RegExp("^"+a+"$"),inside:{"table-header":{pattern:RegExp(r),alias:"important",inside:e.languages.markdown},punctuation:/\|/}}}},code:[{pattern:/((?:^|\n)[ \t]*\n|(?:^|\r\n?)[ \t]*\r\n?)(?: {4}|\t).+(?:(?:\n|\r\n?)(?: {4}|\t).+)*/,lookbehind:!0,alias:"keyword"},{pattern:/^```[\s\S]*?^```$/m,greedy:!0,inside:{"code-block":{pattern:/^(```.*(?:\n|\r\n?))[\s\S]+?(?=(?:\n|\r\n?)^```$)/m,lookbehind:!0},"code-language":{pattern:/^(```).+/,lookbehind:!0},punctuation:/```/}}],title:[{pattern:/\S.*(?:\n|\r\n?)(?:==+|--+)(?=[ \t]*$)/m,alias:"important",inside:{punctuation:/==+$|--+$/}},{pattern:/(^\s*)#.+/m,lookbehind:!0,alias:"important",inside:{punctuation:/^#+|#+$/}}],hr:{pattern:/(^\s*)([*-])(?:[\t ]*\2){2,}(?=\s*$)/m,lookbehind:!0,alias:"punctuation"},list:{pattern:/(^\s*)(?:[*+-]|\d+\.)(?=[\t ].)/m,lookbehind:!0,alias:"punctuation"},"url-reference":{pattern:/!?\[[^\]]+\]:[\t ]+(?:\S+|<(?:\\.|[^>\\])+>)(?:[\t ]+(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\)))?/,inside:{variable:{pattern:/^(!?\[)[^\]]+/,lookbehind:!0},string:/(?:"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'|\((?:\\.|[^)\\])*\))$/,punctuation:/^[\[\]!:]|[<>]/},alias:"url"},bold:{pattern:n(/\b__(?:(?!_)|_(?:(?!_))+_)+__\b|\*\*(?:(?!\*)|\*(?:(?!\*))+\*)+\*\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^..)[\s\S]+(?=..$)/,lookbehind:!0,inside:{}},punctuation:/\*\*|__/}},italic:{pattern:n(/\b_(?:(?!_)|__(?:(?!_))+__)+_\b|\*(?:(?!\*)|\*\*(?:(?!\*))+\*\*)+\*/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^.)[\s\S]+(?=.$)/,lookbehind:!0,inside:{}},punctuation:/[*_]/}},strike:{pattern:n(/(~~?)(?:(?!~))+\2/.source),lookbehind:!0,greedy:!0,inside:{content:{pattern:/(^~~?)[\s\S]+(?=\1$)/,lookbehind:!0,inside:{}},punctuation:/~~?/}},"code-snippet":{pattern:/(^|[^\\`])(?:``[^`\r\n]+(?:`[^`\r\n]+)*``(?!`)|`[^`\r\n]+`(?!`))/,lookbehind:!0,greedy:!0,alias:["code","keyword"]},url:{pattern:n(/!?\[(?:(?!\]))+\](?:\([^\s)]+(?:[\t ]+"(?:\\.|[^"\\])*")?\)|[ \t]?\[(?:(?!\]))+\])/.source),lookbehind:!0,greedy:!0,inside:{operator:/^!/,content:{pattern:/(^\[)[^\]]+(?=\])/,lookbehind:!0,inside:{}},variable:{pattern:/(^\][ \t]?\[)[^\]]+(?=\]$)/,lookbehind:!0},url:{pattern:/(^\]\()[^\s)]+/,lookbehind:!0},string:{pattern:/(^[ \t]+)"(?:\\.|[^"\\])*"(?=\)$)/,lookbehind:!0}}}}),["url","bold","italic","strike"].forEach((function(t){["url","bold","italic","strike","code-snippet"].forEach((function(n){t!==n&&(e.languages.markdown[t].inside.content.inside[n]=e.languages.markdown[n])}))})),e.hooks.add("after-tokenize",(function(e){"markdown"!==e.language&&"md"!==e.language||function e(t){if(t&&"string"!=typeof t)for(var n=0,r=t.length;n",quot:'"'},l=String.fromCodePoint||String.fromCharCode;e.languages.md=e.languages.markdown}(a),a.languages.graphql={comment:/#.*/,description:{pattern:/(?:"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*")(?=\s*[a-z_])/i,greedy:!0,alias:"string",inside:{"language-markdown":{pattern:/(^"(?:"")?)(?!\1)[\s\S]+(?=\1$)/,lookbehind:!0,inside:a.languages.markdown}}},string:{pattern:/"""(?:[^"]|(?!""")")*"""|"(?:\\.|[^\\"\r\n])*"/,greedy:!0},number:/(?:\B-|\b)\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,boolean:/\b(?:false|true)\b/,variable:/\$[a-z_]\w*/i,directive:{pattern:/@[a-z_]\w*/i,alias:"function"},"attr-name":{pattern:/\b[a-z_]\w*(?=\s*(?:\((?:[^()"]|"(?:\\.|[^\\"\r\n])*")*\))?:)/i,greedy:!0},"atom-input":{pattern:/\b[A-Z]\w*Input\b/,alias:"class-name"},scalar:/\b(?:Boolean|Float|ID|Int|String)\b/,constant:/\b[A-Z][A-Z_\d]*\b/,"class-name":{pattern:/(\b(?:enum|implements|interface|on|scalar|type|union)\s+|&\s*|:\s*|\[)[A-Z_]\w*/,lookbehind:!0},fragment:{pattern:/(\bfragment\s+|\.{3}\s*(?!on\b))[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-mutation":{pattern:/(\bmutation\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},"definition-query":{pattern:/(\bquery\s+)[a-zA-Z_]\w*/,lookbehind:!0,alias:"function"},keyword:/\b(?:directive|enum|extend|fragment|implements|input|interface|mutation|on|query|repeatable|scalar|schema|subscription|type|union)\b/,operator:/[!=|&]|\.{3}/,"property-query":/\w+(?=\s*\()/,object:/\w+(?=\s*\{)/,punctuation:/[!(){}\[\]:=,]/,property:/\w+/},a.hooks.add("after-tokenize",(function(e){if("graphql"===e.language)for(var t=e.tokens.filter((function(e){return"string"!=typeof e&&"comment"!==e.type&&"scalar"!==e.type})),n=0;n0)){var s=f(/^\{$/,/^\}$/);if(-1===s)continue;for(var l=n;l=0&&p(c,"variable-input")}}}}function u(e){return t[n+e]}function d(e,t){t=t||0;for(var n=0;n?|<|>)?|>[>=]?|\b(?:AND|BETWEEN|DIV|ILIKE|IN|IS|LIKE|NOT|OR|REGEXP|RLIKE|SOUNDS LIKE|XOR)\b/i,punctuation:/[;[\]()`,.]/},function(e){var t=e.languages.javascript["template-string"],n=t.pattern.source,r=t.inside.interpolation,a=r.inside["interpolation-punctuation"],o=r.pattern.source;function i(t,r){if(e.languages[t])return{pattern:RegExp("((?:"+r+")\\s*)"+n),lookbehind:!0,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},"embedded-code":{pattern:/[\s\S]+/,alias:t}}}}function s(e,t){return"___"+t.toUpperCase()+"_"+e+"___"}function l(t,n,r){var a={code:t,grammar:n,language:r};return e.hooks.run("before-tokenize",a),a.tokens=e.tokenize(a.code,a.grammar),e.hooks.run("after-tokenize",a),a.tokens}function c(t){var n={};n["interpolation-punctuation"]=a;var o=e.tokenize(t,n);if(3===o.length){var i=[1,1];i.push.apply(i,l(o[1],e.languages.javascript,"javascript")),o.splice.apply(o,i)}return new e.Token("interpolation",o,r.alias,t)}function u(t,n,r){var a=e.tokenize(t,{interpolation:{pattern:RegExp(o),lookbehind:!0}}),i=0,u={},d=l(a.map((function(e){if("string"==typeof e)return e;for(var n,a=e.content;-1!==t.indexOf(n=s(i++,r)););return u[n]=a,n})).join(""),n,r),f=Object.keys(u);return i=0,function e(t){for(var n=0;n=f.length)return;var r=t[n];if("string"==typeof r||"string"==typeof r.content){var a=f[i],o="string"==typeof r?r:r.content,s=o.indexOf(a);if(-1!==s){++i;var l=o.substring(0,s),d=c(u[a]),p=o.substring(s+a.length),g=[];if(l&&g.push(l),g.push(d),p){var m=[p];e(m),g.push.apply(g,m)}"string"==typeof r?(t.splice.apply(t,[n,1].concat(g)),n+=g.length-1):r.content=g}}else{var h=r.content;Array.isArray(h)?e(h):e([h])}}}(d),new e.Token(r,d,"language-"+r,t)}e.languages.javascript["template-string"]=[i("css",/\b(?:styled(?:\([^)]*\))?(?:\s*\.\s*\w+(?:\([^)]*\))*)*|css(?:\s*\.\s*(?:global|resolve))?|createGlobalStyle|keyframes)/.source),i("html",/\bhtml|\.\s*(?:inner|outer)HTML\s*\+?=/.source),i("svg",/\bsvg/.source),i("markdown",/\b(?:markdown|md)/.source),i("graphql",/\b(?:gql|graphql(?:\s*\.\s*experimental)?)/.source),i("sql",/\bsql/.source),t].filter(Boolean);var d={javascript:!0,js:!0,typescript:!0,ts:!0,jsx:!0,tsx:!0};function f(e){return"string"==typeof e?e:Array.isArray(e)?e.map(f).join(""):f(e.content)}e.hooks.add("after-tokenize",(function(t){t.language in d&&function t(n){for(var r=0,a=n.length;r]|<(?:[^<>]|<[^<>]*>)*>)*>)?/,lookbehind:!0,greedy:!0,inside:null},builtin:/\b(?:Array|Function|Promise|any|boolean|console|never|number|string|symbol|unknown)\b/}),e.languages.typescript.keyword.push(/\b(?:abstract|declare|is|keyof|readonly|require)\b/,/\b(?:asserts|infer|interface|module|namespace|type)\b(?=\s*(?:[{_$a-zA-Z\xA0-\uFFFF]|$))/,/\btype\b(?=\s*(?:[\{*]|$))/),delete e.languages.typescript.parameter,delete e.languages.typescript["literal-property"];var t=e.languages.extend("typescript",{});delete t["class-name"],e.languages.typescript["class-name"].inside=t,e.languages.insertBefore("typescript","function",{decorator:{pattern:/@[$\w\xA0-\uFFFF]+/,inside:{at:{pattern:/^@/,alias:"operator"},function:/^[\s\S]+/}},"generic-function":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>(?=\s*\()/,greedy:!0,inside:{function:/^#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:t}}}}),e.languages.ts=e.languages.typescript}(a),function(e){function t(e,t){return RegExp(e.replace(//g,(function(){return/(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*/.source})),t)}e.languages.insertBefore("javascript","function-variable",{"method-variable":{pattern:RegExp("(\\.\\s*)"+e.languages.javascript["function-variable"].pattern.source),lookbehind:!0,alias:["function-variable","method","function","property-access"]}}),e.languages.insertBefore("javascript","function",{method:{pattern:RegExp("(\\.\\s*)"+e.languages.javascript.function.source),lookbehind:!0,alias:["function","property-access"]}}),e.languages.insertBefore("javascript","constant",{"known-class-name":[{pattern:/\b(?:(?:Float(?:32|64)|(?:Int|Uint)(?:8|16|32)|Uint8Clamped)?Array|ArrayBuffer|BigInt|Boolean|DataView|Date|Error|Function|Intl|JSON|(?:Weak)?(?:Map|Set)|Math|Number|Object|Promise|Proxy|Reflect|RegExp|String|Symbol|WebAssembly)\b/,alias:"class-name"},{pattern:/\b(?:[A-Z]\w*)Error\b/,alias:"class-name"}]}),e.languages.insertBefore("javascript","keyword",{imports:{pattern:t(/(\bimport\b\s*)(?:(?:\s*,\s*(?:\*\s*as\s+|\{[^{}]*\}))?|\*\s*as\s+|\{[^{}]*\})(?=\s*\bfrom\b)/.source),lookbehind:!0,inside:e.languages.javascript},exports:{pattern:t(/(\bexport\b\s*)(?:\*(?:\s*as\s+)?(?=\s*\bfrom\b)|\{[^{}]*\})/.source),lookbehind:!0,inside:e.languages.javascript}}),e.languages.javascript.keyword.unshift({pattern:/\b(?:as|default|export|from|import)\b/,alias:"module"},{pattern:/\b(?:await|break|catch|continue|do|else|finally|for|if|return|switch|throw|try|while|yield)\b/,alias:"control-flow"},{pattern:/\bnull\b/,alias:["null","nil"]},{pattern:/\bundefined\b/,alias:"nil"}),e.languages.insertBefore("javascript","operator",{spread:{pattern:/\.{3}/,alias:"operator"},arrow:{pattern:/=>/,alias:"operator"}}),e.languages.insertBefore("javascript","punctuation",{"property-access":{pattern:t(/(\.\s*)#?/.source),lookbehind:!0},"maybe-class-name":{pattern:/(^|[^$\w\xA0-\uFFFF])[A-Z][$\w\xA0-\uFFFF]+/,lookbehind:!0},dom:{pattern:/\b(?:document|(?:local|session)Storage|location|navigator|performance|window)\b/,alias:"variable"},console:{pattern:/\bconsole(?=\s*\.)/,alias:"class-name"}});for(var n=["function","function-variable","method","method-variable","property-access"],r=0;r*\.{3}(?:[^{}]|)*\})/.source;function o(e,t){return e=e.replace(//g,(function(){return n})).replace(//g,(function(){return r})).replace(//g,(function(){return a})),RegExp(e,t)}a=o(a).source,e.languages.jsx=e.languages.extend("markup",t),e.languages.jsx.tag.pattern=o(/<\/?(?:[\w.:-]+(?:+(?:[\w.:$-]+(?:=(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s{'"/>=]+|))?|))**\/?)?>/.source),e.languages.jsx.tag.inside.tag.pattern=/^<\/?[^\s>\/]*/,e.languages.jsx.tag.inside["attr-value"].pattern=/=(?!\{)(?:"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*'|[^\s'">]+)/,e.languages.jsx.tag.inside.tag.inside["class-name"]=/^[A-Z]\w*(?:\.[A-Z]\w*)*$/,e.languages.jsx.tag.inside.comment=t.comment,e.languages.insertBefore("inside","attr-name",{spread:{pattern:o(//.source),inside:e.languages.jsx}},e.languages.jsx.tag),e.languages.insertBefore("inside","special-attr",{script:{pattern:o(/=/.source),alias:"language-javascript",inside:{"script-punctuation":{pattern:/^=(?=\{)/,alias:"punctuation"},rest:e.languages.jsx}}},e.languages.jsx.tag);var i=function(e){return e?"string"==typeof e?e:"string"==typeof e.content?e.content:e.content.map(i).join(""):""},s=function(t){for(var n=[],r=0;r0&&n[n.length-1].tagName===i(a.content[0].content[1])&&n.pop():"/>"===a.content[a.content.length-1].content||n.push({tagName:i(a.content[0].content[1]),openedBraces:0}):n.length>0&&"punctuation"===a.type&&"{"===a.content?n[n.length-1].openedBraces++:n.length>0&&n[n.length-1].openedBraces>0&&"punctuation"===a.type&&"}"===a.content?n[n.length-1].openedBraces--:o=!0),(o||"string"==typeof a)&&n.length>0&&0===n[n.length-1].openedBraces){var l=i(a);r0&&("string"==typeof t[r-1]||"plain-text"===t[r-1].type)&&(l=i(t[r-1])+l,t.splice(r-1,1),r--),t[r]=new e.Token("plain-text",l,null,l)}a.content&&"string"!=typeof a.content&&s(a.content)}};e.hooks.add("after-tokenize",(function(e){"jsx"!==e.language&&"tsx"!==e.language||s(e.tokens)}))}(a),function(e){e.languages.diff={coord:[/^(?:\*{3}|-{3}|\+{3}).*$/m,/^@@.*@@$/m,/^\d.*$/m]};var t={"deleted-sign":"-","deleted-arrow":"<","inserted-sign":"+","inserted-arrow":">",unchanged:" ",diff:"!"};Object.keys(t).forEach((function(n){var r=t[n],a=[];/^\w+$/.test(n)||a.push(/\w+/.exec(n)[0]),"diff"===n&&a.push("bold"),e.languages.diff[n]={pattern:RegExp("^(?:["+r+"].*(?:\r\n?|\n|(?![\\s\\S])))+","m"),alias:a,inside:{line:{pattern:/(.)(?=[\s\S]).*(?:\r\n?|\n)?/,lookbehind:!0},prefix:{pattern:/[\s\S]/,alias:/\w+/.exec(n)[0]}}}})),Object.defineProperty(e.languages.diff,"PREFIXES",{value:t})}(a),a.languages.git={comment:/^#.*/m,deleted:/^[-\u2013].*/m,inserted:/^\+.*/m,string:/("|')(?:\\.|(?!\1)[^\\\r\n])*\1/,command:{pattern:/^.*\$ git .*$/m,inside:{parameter:/\s--?\w+/}},coord:/^@@.*@@$/m,"commit-sha1":/^commit \w{40}$/m},a.languages.go=a.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"|`[^`]*`/,lookbehind:!0,greedy:!0},keyword:/\b(?:break|case|chan|const|continue|default|defer|else|fallthrough|for|func|go(?:to)?|if|import|interface|map|package|range|return|select|struct|switch|type|var)\b/,boolean:/\b(?:_|false|iota|nil|true)\b/,number:[/\b0(?:b[01_]+|o[0-7_]+)i?\b/i,/\b0x(?:[a-f\d_]+(?:\.[a-f\d_]*)?|\.[a-f\d_]+)(?:p[+-]?\d+(?:_\d+)*)?i?(?!\w)/i,/(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?[\d_]+)?i?(?!\w)/i],operator:/[*\/%^!=]=?|\+[=+]?|-[=-]?|\|[=|]?|&(?:=|&|\^=?)?|>(?:>=?|=)?|<(?:<=?|=|-)?|:=|\.\.\./,builtin:/\b(?:append|bool|byte|cap|close|complex|complex(?:64|128)|copy|delete|error|float(?:32|64)|u?int(?:8|16|32|64)?|imag|len|make|new|panic|print(?:ln)?|real|recover|rune|string|uintptr)\b/}),a.languages.insertBefore("go","string",{char:{pattern:/'(?:\\.|[^'\\\r\n]){0,10}'/,greedy:!0}}),delete a.languages.go["class-name"],function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,a,o){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(a,(function(e){if("function"==typeof o&&!o(e))return e;for(var a,s=i.length;-1!==n.code.indexOf(a=t(r,s));)++s;return i[s]=e,a})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var a=0,o=Object.keys(n.tokenStack);!function i(s){for(var l=0;l=o.length);l++){var c=s[l];if("string"==typeof c||c.content&&"string"==typeof c.content){var u=o[a],d=n.tokenStack[u],f="string"==typeof c?c:c.content,p=t(r,u),g=f.indexOf(p);if(g>-1){++a;var m=f.substring(0,g),h=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),b=f.substring(g+p.length),v=[];m&&v.push.apply(v,i([m])),v.push(h),b&&v.push.apply(v,i([b])),"string"==typeof c?s.splice.apply(s,[l,1].concat(v)):c.content=v}}else c.content&&i(c.content)}return s}(n.tokens)}}}})}(a),function(e){e.languages.handlebars={comment:/\{\{![\s\S]*?\}\}/,delimiter:{pattern:/^\{\{\{?|\}\}\}?$/,alias:"punctuation"},string:/(["'])(?:\\.|(?!\1)[^\\\r\n])*\1/,number:/\b0x[\dA-Fa-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:[Ee][+-]?\d+)?/,boolean:/\b(?:false|true)\b/,block:{pattern:/^(\s*(?:~\s*)?)[#\/]\S+?(?=\s*(?:~\s*)?$|\s)/,lookbehind:!0,alias:"keyword"},brackets:{pattern:/\[[^\]]+\]/,inside:{punctuation:/\[|\]/,variable:/[\s\S]+/}},punctuation:/[!"#%&':()*+,.\/;<=>@\[\\\]^`{|}~]/,variable:/[^!"#%&'()*+,\/;<=>@\[\\\]^`{|}~\s]+/},e.hooks.add("before-tokenize",(function(t){e.languages["markup-templating"].buildPlaceholders(t,"handlebars",/\{\{\{[\s\S]+?\}\}\}|\{\{[\s\S]+?\}\}/g)})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"handlebars")})),e.languages.hbs=e.languages.handlebars}(a),a.languages.json={property:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,lookbehind:!0,greedy:!0},string:{pattern:/(^|[^\\])"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,lookbehind:!0,greedy:!0},comment:{pattern:/\/\/.*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},number:/-?\b\d+(?:\.\d+)?(?:e[+-]?\d+)?\b/i,punctuation:/[{}[\],]/,operator:/:/,boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"}},a.languages.webmanifest=a.languages.json,a.languages.less=a.languages.extend("css",{comment:[/\/\*[\s\S]*?\*\//,{pattern:/(^|[^\\])\/\/.*/,lookbehind:!0}],atrule:{pattern:/@[\w-](?:\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{punctuation:/[:()]/}},selector:{pattern:/(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\((?:[^(){}]|\([^(){}]*\))*\)|[^(){};@\s]|\s+(?!\s))*?(?=\s*\{)/,inside:{variable:/@+[\w-]+/}},property:/(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/,operator:/[+\-*\/]/}),a.languages.insertBefore("less","property",{variable:[{pattern:/@[\w-]+\s*:/,inside:{punctuation:/:/}},/@@?[\w-]+/],"mixin-usage":{pattern:/([{;]\s*)[.#](?!\d)[\w-].*?(?=[(;])/,lookbehind:!0,alias:"function"}}),a.languages.makefile={comment:{pattern:/(^|[^\\])#(?:\\(?:\r\n|[\s\S])|[^\\\r\n])*/,lookbehind:!0},string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"builtin-target":{pattern:/\.[A-Z][^:#=\s]+(?=\s*:(?!=))/,alias:"builtin"},target:{pattern:/^(?:[^:=\s]|[ \t]+(?![\s:]))+(?=\s*:(?!=))/m,alias:"symbol",inside:{variable:/\$+(?:(?!\$)[^(){}:#=\s]+|(?=[({]))/}},variable:/\$+(?:(?!\$)[^(){}:#=\s]+|\([@*%<^+?][DF]\)|(?=[({]))/,keyword:/-include\b|\b(?:define|else|endef|endif|export|ifn?def|ifn?eq|include|override|private|sinclude|undefine|unexport|vpath)\b/,function:{pattern:/(\()(?:abspath|addsuffix|and|basename|call|dir|error|eval|file|filter(?:-out)?|findstring|firstword|flavor|foreach|guile|if|info|join|lastword|load|notdir|or|origin|patsubst|realpath|shell|sort|strip|subst|suffix|value|warning|wildcard|word(?:list|s)?)(?=[ \t])/,lookbehind:!0},operator:/(?:::|[?:+!])?=|[|@]/,punctuation:/[:;(){}]/},a.languages.objectivec=a.languages.extend("c",{string:{pattern:/@?"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},keyword:/\b(?:asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|in|inline|int|long|register|return|self|short|signed|sizeof|static|struct|super|switch|typedef|typeof|union|unsigned|void|volatile|while)\b|(?:@interface|@end|@implementation|@protocol|@class|@public|@protected|@private|@property|@try|@catch|@finally|@throw|@synthesize|@dynamic|@selector)\b/,operator:/-[->]?|\+\+?|!=?|<>?=?|==?|&&?|\|\|?|[~^%?*\/@]/}),delete a.languages.objectivec["class-name"],a.languages.objc=a.languages.objectivec,a.languages.ocaml={comment:{pattern:/\(\*[\s\S]*?\*\)/,greedy:!0},char:{pattern:/'(?:[^\\\r\n']|\\(?:.|[ox]?[0-9a-f]{1,3}))'/i,greedy:!0},string:[{pattern:/"(?:\\(?:[\s\S]|\r\n)|[^\\\r\n"])*"/,greedy:!0},{pattern:/\{([a-z_]*)\|[\s\S]*?\|\1\}/,greedy:!0}],number:[/\b(?:0b[01][01_]*|0o[0-7][0-7_]*)\b/i,/\b0x[a-f0-9][a-f0-9_]*(?:\.[a-f0-9_]*)?(?:p[+-]?\d[\d_]*)?(?!\w)/i,/\b\d[\d_]*(?:\.[\d_]*)?(?:e[+-]?\d[\d_]*)?(?!\w)/i],directive:{pattern:/\B#\w+/,alias:"property"},label:{pattern:/\B~\w+/,alias:"property"},"type-variable":{pattern:/\B'\w+/,alias:"function"},variant:{pattern:/`\w+/,alias:"symbol"},keyword:/\b(?:as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|match|method|module|mutable|new|nonrec|object|of|open|private|rec|sig|struct|then|to|try|type|val|value|virtual|when|where|while|with)\b/,boolean:/\b(?:false|true)\b/,"operator-like-punctuation":{pattern:/\[[<>|]|[>|]\]|\{<|>\}/,alias:"punctuation"},operator:/\.[.~]|:[=>]|[=<>@^|&+\-*\/$%!?~][!$%&*+\-.\/:<=>?@^|~]*|\b(?:and|asr|land|lor|lsl|lsr|lxor|mod|or)\b/,punctuation:/;;|::|[(){}\[\].,:;#]|\b_\b/},a.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},a.languages.python["string-interpolation"].inside.interpolation.inside.rest=a.languages.python,a.languages.py=a.languages.python,a.languages.reason=a.languages.extend("clike",{string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^\\\r\n"])*"/,greedy:!0},"class-name":/\b[A-Z]\w*/,keyword:/\b(?:and|as|assert|begin|class|constraint|do|done|downto|else|end|exception|external|for|fun|function|functor|if|in|include|inherit|initializer|lazy|let|method|module|mutable|new|nonrec|object|of|open|or|private|rec|sig|struct|switch|then|to|try|type|val|virtual|when|while|with)\b/,operator:/\.{3}|:[:=]|\|>|->|=(?:==?|>)?|<=?|>=?|[|^?'#!~`]|[+\-*\/]\.?|\b(?:asr|land|lor|lsl|lsr|lxor|mod)\b/}),a.languages.insertBefore("reason","class-name",{char:{pattern:/'(?:\\x[\da-f]{2}|\\o[0-3][0-7][0-7]|\\\d{3}|\\.|[^'\\\r\n])'/,greedy:!0},constructor:/\b[A-Z]\w*\b(?!\s*\.)/,label:{pattern:/\b[a-z]\w*(?=::)/,alias:"symbol"}}),delete a.languages.reason.function,function(e){e.languages.sass=e.languages.extend("css",{comment:{pattern:/^([ \t]*)\/[\/*].*(?:(?:\r?\n|\r)\1[ \t].+)*/m,lookbehind:!0,greedy:!0}}),e.languages.insertBefore("sass","atrule",{"atrule-line":{pattern:/^(?:[ \t]*)[@+=].+/m,greedy:!0,inside:{atrule:/(?:@[\w-]+|[+=])/}}}),delete e.languages.sass.atrule;var t=/\$[-\w]+|#\{\$[-\w]+\}/,n=[/[+*\/%]|[=!]=|<=?|>=?|\b(?:and|not|or)\b/,{pattern:/(\s)-(?=\s)/,lookbehind:!0}];e.languages.insertBefore("sass","property",{"variable-line":{pattern:/^[ \t]*\$.+/m,greedy:!0,inside:{punctuation:/:/,variable:t,operator:n}},"property-line":{pattern:/^[ \t]*(?:[^:\s]+ *:.*|:[^:\s].*)/m,greedy:!0,inside:{property:[/[^:\s]+(?=\s*:)/,{pattern:/(:)[^:\s]+/,lookbehind:!0}],punctuation:/:/,variable:t,operator:n,important:e.languages.sass.important}}}),delete e.languages.sass.property,delete e.languages.sass.important,e.languages.insertBefore("sass","punctuation",{selector:{pattern:/^([ \t]*)\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*(?:,(?:\r?\n|\r)\1[ \t]+\S(?:,[^,\r\n]+|[^,\r\n]*)(?:,[^,\r\n]+)*)*/m,lookbehind:!0,greedy:!0}})}(a),a.languages.scss=a.languages.extend("css",{comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},atrule:{pattern:/@[\w-](?:\([^()]+\)|[^()\s]|\s+(?!\s))*?(?=\s+[{;])/,inside:{rule:/@[\w-]+/}},url:/(?:[-a-z]+-)?url(?=\()/i,selector:{pattern:/(?=\S)[^@;{}()]?(?:[^@;{}()\s]|\s+(?!\s)|#\{\$[-\w]+\})+(?=\s*\{(?:\}|\s|[^}][^:{}]*[:{][^}]))/,inside:{parent:{pattern:/&/,alias:"important"},placeholder:/%[-\w]+/,variable:/\$[-\w]+|#\{\$[-\w]+\}/}},property:{pattern:/(?:[-\w]|\$[-\w]|#\{\$[-\w]+\})+(?=\s*:)/,inside:{variable:/\$[-\w]+|#\{\$[-\w]+\}/}}}),a.languages.insertBefore("scss","atrule",{keyword:[/@(?:content|debug|each|else(?: if)?|extend|for|forward|function|if|import|include|mixin|return|use|warn|while)\b/i,{pattern:/( )(?:from|through)(?= )/,lookbehind:!0}]}),a.languages.insertBefore("scss","important",{variable:/\$[-\w]+|#\{\$[-\w]+\}/}),a.languages.insertBefore("scss","function",{"module-modifier":{pattern:/\b(?:as|hide|show|with)\b/i,alias:"keyword"},placeholder:{pattern:/%[-\w]+/,alias:"selector"},statement:{pattern:/\B!(?:default|optional)\b/i,alias:"keyword"},boolean:/\b(?:false|true)\b/,null:{pattern:/\bnull\b/,alias:"keyword"},operator:{pattern:/(\s)(?:[-+*\/%]|[=!]=|<=?|>=?|and|not|or)(?=\s)/,lookbehind:!0}}),a.languages.scss.atrule.inside.rest=a.languages.scss,function(e){var t={pattern:/(\b\d+)(?:%|[a-z]+)/,lookbehind:!0},n={pattern:/(^|[^\w.-])-?(?:\d+(?:\.\d+)?|\.\d+)/,lookbehind:!0},r={comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0},url:{pattern:/\burl\((["']?).*?\1\)/i,greedy:!0},string:{pattern:/("|')(?:(?!\1)[^\\\r\n]|\\(?:\r\n|[\s\S]))*\1/,greedy:!0},interpolation:null,func:null,important:/\B!(?:important|optional)\b/i,keyword:{pattern:/(^|\s+)(?:(?:else|for|if|return|unless)(?=\s|$)|@[\w-]+)/,lookbehind:!0},hexcode:/#[\da-f]{3,6}/i,color:[/\b(?:AliceBlue|AntiqueWhite|Aqua|Aquamarine|Azure|Beige|Bisque|Black|BlanchedAlmond|Blue|BlueViolet|Brown|BurlyWood|CadetBlue|Chartreuse|Chocolate|Coral|CornflowerBlue|Cornsilk|Crimson|Cyan|DarkBlue|DarkCyan|DarkGoldenRod|DarkGr[ae]y|DarkGreen|DarkKhaki|DarkMagenta|DarkOliveGreen|DarkOrange|DarkOrchid|DarkRed|DarkSalmon|DarkSeaGreen|DarkSlateBlue|DarkSlateGr[ae]y|DarkTurquoise|DarkViolet|DeepPink|DeepSkyBlue|DimGr[ae]y|DodgerBlue|FireBrick|FloralWhite|ForestGreen|Fuchsia|Gainsboro|GhostWhite|Gold|GoldenRod|Gr[ae]y|Green|GreenYellow|HoneyDew|HotPink|IndianRed|Indigo|Ivory|Khaki|Lavender|LavenderBlush|LawnGreen|LemonChiffon|LightBlue|LightCoral|LightCyan|LightGoldenRodYellow|LightGr[ae]y|LightGreen|LightPink|LightSalmon|LightSeaGreen|LightSkyBlue|LightSlateGr[ae]y|LightSteelBlue|LightYellow|Lime|LimeGreen|Linen|Magenta|Maroon|MediumAquaMarine|MediumBlue|MediumOrchid|MediumPurple|MediumSeaGreen|MediumSlateBlue|MediumSpringGreen|MediumTurquoise|MediumVioletRed|MidnightBlue|MintCream|MistyRose|Moccasin|NavajoWhite|Navy|OldLace|Olive|OliveDrab|Orange|OrangeRed|Orchid|PaleGoldenRod|PaleGreen|PaleTurquoise|PaleVioletRed|PapayaWhip|PeachPuff|Peru|Pink|Plum|PowderBlue|Purple|Red|RosyBrown|RoyalBlue|SaddleBrown|Salmon|SandyBrown|SeaGreen|SeaShell|Sienna|Silver|SkyBlue|SlateBlue|SlateGr[ae]y|Snow|SpringGreen|SteelBlue|Tan|Teal|Thistle|Tomato|Transparent|Turquoise|Violet|Wheat|White|WhiteSmoke|Yellow|YellowGreen)\b/i,{pattern:/\b(?:hsl|rgb)\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*\)\B|\b(?:hsl|rgb)a\(\s*\d{1,3}\s*,\s*\d{1,3}%?\s*,\s*\d{1,3}%?\s*,\s*(?:0|0?\.\d+|1)\s*\)\B/i,inside:{unit:t,number:n,function:/[\w-]+(?=\()/,punctuation:/[(),]/}}],entity:/\\[\da-f]{1,8}/i,unit:t,boolean:/\b(?:false|true)\b/,operator:[/~|[+!\/%<>?=]=?|[-:]=|\*[*=]?|\.{2,3}|&&|\|\||\B-\B|\b(?:and|in|is(?: a| defined| not|nt)?|not|or)\b/],number:n,punctuation:/[{}()\[\];:,]/};r.interpolation={pattern:/\{[^\r\n}:]+\}/,alias:"variable",inside:{delimiter:{pattern:/^\{|\}$/,alias:"punctuation"},rest:r}},r.func={pattern:/[\w-]+\([^)]*\).*/,inside:{function:/^[^(]+/,rest:r}},e.languages.stylus={"atrule-declaration":{pattern:/(^[ \t]*)@.+/m,lookbehind:!0,inside:{atrule:/^@[\w-]+/,rest:r}},"variable-declaration":{pattern:/(^[ \t]*)[\w$-]+\s*.?=[ \t]*(?:\{[^{}]*\}|\S.*|$)/m,lookbehind:!0,inside:{variable:/^\S+/,rest:r}},statement:{pattern:/(^[ \t]*)(?:else|for|if|return|unless)[ \t].+/m,lookbehind:!0,inside:{keyword:/^\S+/,rest:r}},"property-declaration":{pattern:/((?:^|\{)([ \t]*))(?:[\w-]|\{[^}\r\n]+\})+(?:\s*:\s*|[ \t]+)(?!\s)[^{\r\n]*(?:;|[^{\r\n,]$(?!(?:\r?\n|\r)(?:\{|\2[ \t])))/m,lookbehind:!0,inside:{property:{pattern:/^[^\s:]+/,inside:{interpolation:r.interpolation}},rest:r}},selector:{pattern:/(^[ \t]*)(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)(?:(?:\r?\n|\r)(?:\1(?:(?=\S)(?:[^{}\r\n:()]|::?[\w-]+(?:\([^)\r\n]*\)|(?![\w-]))|\{[^}\r\n]+\})+)))*(?:,$|\{|(?=(?:\r?\n|\r)(?:\{|\1[ \t])))/m,lookbehind:!0,inside:{interpolation:r.interpolation,comment:r.comment,punctuation:/[{},]/}},func:r.func,string:r.string,comment:{pattern:/(^|[^\\])(?:\/\*[\s\S]*?\*\/|\/\/.*)/,lookbehind:!0,greedy:!0},interpolation:r.interpolation,punctuation:/[{}()\[\];:.]/}}(a),function(e){var t=e.util.clone(e.languages.typescript);e.languages.tsx=e.languages.extend("jsx",t),delete e.languages.tsx.parameter,delete e.languages.tsx["literal-property"];var n=e.languages.tsx.tag;n.pattern=RegExp(/(^|[^\w$]|(?=<\/))/.source+"(?:"+n.pattern.source+")",n.pattern.flags),n.lookbehind=!0}(a),a.languages.wasm={comment:[/\(;[\s\S]*?;\)/,{pattern:/;;.*/,greedy:!0}],string:{pattern:/"(?:\\[\s\S]|[^"\\])*"/,greedy:!0},keyword:[{pattern:/\b(?:align|offset)=/,inside:{operator:/=/}},{pattern:/\b(?:(?:f32|f64|i32|i64)(?:\.(?:abs|add|and|ceil|clz|const|convert_[su]\/i(?:32|64)|copysign|ctz|demote\/f64|div(?:_[su])?|eqz?|extend_[su]\/i32|floor|ge(?:_[su])?|gt(?:_[su])?|le(?:_[su])?|load(?:(?:8|16|32)_[su])?|lt(?:_[su])?|max|min|mul|neg?|nearest|or|popcnt|promote\/f32|reinterpret\/[fi](?:32|64)|rem_[su]|rot[lr]|shl|shr_[su]|sqrt|store(?:8|16|32)?|sub|trunc(?:_[su]\/f(?:32|64))?|wrap\/i64|xor))?|memory\.(?:grow|size))\b/,inside:{punctuation:/\./}},/\b(?:anyfunc|block|br(?:_if|_table)?|call(?:_indirect)?|data|drop|elem|else|end|export|func|get_(?:global|local)|global|if|import|local|loop|memory|module|mut|nop|offset|param|result|return|select|set_(?:global|local)|start|table|tee_local|then|type|unreachable)\b/],variable:/\$[\w!#$%&'*+\-./:<=>?@\\^`|~]+/,number:/[+-]?\b(?:\d(?:_?\d)*(?:\.\d(?:_?\d)*)?(?:[eE][+-]?\d(?:_?\d)*)?|0x[\da-fA-F](?:_?[\da-fA-F])*(?:\.[\da-fA-F](?:_?[\da-fA-D])*)?(?:[pP][+-]?\d(?:_?\d)*)?)\b|\binf\b|\bnan(?::0x[\da-fA-F](?:_?[\da-fA-D])*)?\b/,punctuation:/[()]/};const o=a},9901:e=>{e.exports&&(e.exports={core:{meta:{path:"components/prism-core.js",option:"mandatory"},core:"Core"},themes:{meta:{path:"themes/{id}.css",link:"index.html?theme={id}",exclusive:!0},prism:{title:"Default",option:"default"},"prism-dark":"Dark","prism-funky":"Funky","prism-okaidia":{title:"Okaidia",owner:"ocodia"},"prism-twilight":{title:"Twilight",owner:"remybach"},"prism-coy":{title:"Coy",owner:"tshedor"},"prism-solarizedlight":{title:"Solarized Light",owner:"hectormatos2011 "},"prism-tomorrow":{title:"Tomorrow Night",owner:"Rosey"}},languages:{meta:{path:"components/prism-{id}",noCSS:!0,examplesPath:"examples/prism-{id}",addCheckAll:!0},markup:{title:"Markup",alias:["html","xml","svg","mathml","ssml","atom","rss"],aliasTitles:{html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",ssml:"SSML",atom:"Atom",rss:"RSS"},option:"default"},css:{title:"CSS",option:"default",modify:"markup"},clike:{title:"C-like",option:"default"},javascript:{title:"JavaScript",require:"clike",modify:"markup",optional:"regex",alias:"js",option:"default"},abap:{title:"ABAP",owner:"dellagustin"},abnf:{title:"ABNF",owner:"RunDevelopment"},actionscript:{title:"ActionScript",require:"javascript",modify:"markup",owner:"Golmote"},ada:{title:"Ada",owner:"Lucretia"},agda:{title:"Agda",owner:"xy-ren"},al:{title:"AL",owner:"RunDevelopment"},antlr4:{title:"ANTLR4",alias:"g4",owner:"RunDevelopment"},apacheconf:{title:"Apache Configuration",owner:"GuiTeK"},apex:{title:"Apex",require:["clike","sql"],owner:"RunDevelopment"},apl:{title:"APL",owner:"ngn"},applescript:{title:"AppleScript",owner:"Golmote"},aql:{title:"AQL",owner:"RunDevelopment"},arduino:{title:"Arduino",require:"cpp",alias:"ino",owner:"dkern"},arff:{title:"ARFF",owner:"Golmote"},armasm:{title:"ARM Assembly",alias:"arm-asm",owner:"RunDevelopment"},arturo:{title:"Arturo",alias:"art",optional:["bash","css","javascript","markup","markdown","sql"],owner:"drkameleon"},asciidoc:{alias:"adoc",title:"AsciiDoc",owner:"Golmote"},aspnet:{title:"ASP.NET (C#)",require:["markup","csharp"],owner:"nauzilus"},asm6502:{title:"6502 Assembly",owner:"kzurawel"},asmatmel:{title:"Atmel AVR Assembly",owner:"cerkit"},autohotkey:{title:"AutoHotkey",owner:"aviaryan"},autoit:{title:"AutoIt",owner:"Golmote"},avisynth:{title:"AviSynth",alias:"avs",owner:"Zinfidel"},"avro-idl":{title:"Avro IDL",alias:"avdl",owner:"RunDevelopment"},awk:{title:"AWK",alias:"gawk",aliasTitles:{gawk:"GAWK"},owner:"RunDevelopment"},bash:{title:"Bash",alias:["sh","shell"],aliasTitles:{sh:"Shell",shell:"Shell"},owner:"zeitgeist87"},basic:{title:"BASIC",owner:"Golmote"},batch:{title:"Batch",owner:"Golmote"},bbcode:{title:"BBcode",alias:"shortcode",aliasTitles:{shortcode:"Shortcode"},owner:"RunDevelopment"},bbj:{title:"BBj",owner:"hyyan"},bicep:{title:"Bicep",owner:"johnnyreilly"},birb:{title:"Birb",require:"clike",owner:"Calamity210"},bison:{title:"Bison",require:"c",owner:"Golmote"},bnf:{title:"BNF",alias:"rbnf",aliasTitles:{rbnf:"RBNF"},owner:"RunDevelopment"},bqn:{title:"BQN",owner:"yewscion"},brainfuck:{title:"Brainfuck",owner:"Golmote"},brightscript:{title:"BrightScript",owner:"RunDevelopment"},bro:{title:"Bro",owner:"wayward710"},bsl:{title:"BSL (1C:Enterprise)",alias:"oscript",aliasTitles:{oscript:"OneScript"},owner:"Diversus23"},c:{title:"C",require:"clike",owner:"zeitgeist87"},csharp:{title:"C#",require:"clike",alias:["cs","dotnet"],owner:"mvalipour"},cpp:{title:"C++",require:"c",owner:"zeitgeist87"},cfscript:{title:"CFScript",require:"clike",alias:"cfc",owner:"mjclemente"},chaiscript:{title:"ChaiScript",require:["clike","cpp"],owner:"RunDevelopment"},cil:{title:"CIL",owner:"sbrl"},cilkc:{title:"Cilk/C",require:"c",alias:"cilk-c",owner:"OpenCilk"},cilkcpp:{title:"Cilk/C++",require:"cpp",alias:["cilk-cpp","cilk"],owner:"OpenCilk"},clojure:{title:"Clojure",owner:"troglotit"},cmake:{title:"CMake",owner:"mjrogozinski"},cobol:{title:"COBOL",owner:"RunDevelopment"},coffeescript:{title:"CoffeeScript",require:"javascript",alias:"coffee",owner:"R-osey"},concurnas:{title:"Concurnas",alias:"conc",owner:"jasontatton"},csp:{title:"Content-Security-Policy",owner:"ScottHelme"},cooklang:{title:"Cooklang",owner:"ahue"},coq:{title:"Coq",owner:"RunDevelopment"},crystal:{title:"Crystal",require:"ruby",owner:"MakeNowJust"},"css-extras":{title:"CSS Extras",require:"css",modify:"css",owner:"milesj"},csv:{title:"CSV",owner:"RunDevelopment"},cue:{title:"CUE",owner:"RunDevelopment"},cypher:{title:"Cypher",owner:"RunDevelopment"},d:{title:"D",require:"clike",owner:"Golmote"},dart:{title:"Dart",require:"clike",owner:"Golmote"},dataweave:{title:"DataWeave",owner:"machaval"},dax:{title:"DAX",owner:"peterbud"},dhall:{title:"Dhall",owner:"RunDevelopment"},diff:{title:"Diff",owner:"uranusjr"},django:{title:"Django/Jinja2",require:"markup-templating",alias:"jinja2",owner:"romanvm"},"dns-zone-file":{title:"DNS zone file",owner:"RunDevelopment",alias:"dns-zone"},docker:{title:"Docker",alias:"dockerfile",owner:"JustinBeckwith"},dot:{title:"DOT (Graphviz)",alias:"gv",optional:"markup",owner:"RunDevelopment"},ebnf:{title:"EBNF",owner:"RunDevelopment"},editorconfig:{title:"EditorConfig",owner:"osipxd"},eiffel:{title:"Eiffel",owner:"Conaclos"},ejs:{title:"EJS",require:["javascript","markup-templating"],owner:"RunDevelopment",alias:"eta",aliasTitles:{eta:"Eta"}},elixir:{title:"Elixir",owner:"Golmote"},elm:{title:"Elm",owner:"zwilias"},etlua:{title:"Embedded Lua templating",require:["lua","markup-templating"],owner:"RunDevelopment"},erb:{title:"ERB",require:["ruby","markup-templating"],owner:"Golmote"},erlang:{title:"Erlang",owner:"Golmote"},"excel-formula":{title:"Excel Formula",alias:["xlsx","xls"],owner:"RunDevelopment"},fsharp:{title:"F#",require:"clike",owner:"simonreynolds7"},factor:{title:"Factor",owner:"catb0t"},false:{title:"False",owner:"edukisto"},"firestore-security-rules":{title:"Firestore security rules",require:"clike",owner:"RunDevelopment"},flow:{title:"Flow",require:"javascript",owner:"Golmote"},fortran:{title:"Fortran",owner:"Golmote"},ftl:{title:"FreeMarker Template Language",require:"markup-templating",owner:"RunDevelopment"},gml:{title:"GameMaker Language",alias:"gamemakerlanguage",require:"clike",owner:"LiarOnce"},gap:{title:"GAP (CAS)",owner:"RunDevelopment"},gcode:{title:"G-code",owner:"RunDevelopment"},gdscript:{title:"GDScript",owner:"RunDevelopment"},gedcom:{title:"GEDCOM",owner:"Golmote"},gettext:{title:"gettext",alias:"po",owner:"RunDevelopment"},gherkin:{title:"Gherkin",owner:"hason"},git:{title:"Git",owner:"lgiraudel"},glsl:{title:"GLSL",require:"c",owner:"Golmote"},gn:{title:"GN",alias:"gni",owner:"RunDevelopment"},"linker-script":{title:"GNU Linker Script",alias:"ld",owner:"RunDevelopment"},go:{title:"Go",require:"clike",owner:"arnehormann"},"go-module":{title:"Go module",alias:"go-mod",owner:"RunDevelopment"},gradle:{title:"Gradle",require:"clike",owner:"zeabdelkhalek-badido18"},graphql:{title:"GraphQL",optional:"markdown",owner:"Golmote"},groovy:{title:"Groovy",require:"clike",owner:"robfletcher"},haml:{title:"Haml",require:"ruby",optional:["css","css-extras","coffeescript","erb","javascript","less","markdown","scss","textile"],owner:"Golmote"},handlebars:{title:"Handlebars",require:"markup-templating",alias:["hbs","mustache"],aliasTitles:{mustache:"Mustache"},owner:"Golmote"},haskell:{title:"Haskell",alias:"hs",owner:"bholst"},haxe:{title:"Haxe",require:"clike",optional:"regex",owner:"Golmote"},hcl:{title:"HCL",owner:"outsideris"},hlsl:{title:"HLSL",require:"c",owner:"RunDevelopment"},hoon:{title:"Hoon",owner:"matildepark"},http:{title:"HTTP",optional:["csp","css","hpkp","hsts","javascript","json","markup","uri"],owner:"danielgtaylor"},hpkp:{title:"HTTP Public-Key-Pins",owner:"ScottHelme"},hsts:{title:"HTTP Strict-Transport-Security",owner:"ScottHelme"},ichigojam:{title:"IchigoJam",owner:"BlueCocoa"},icon:{title:"Icon",owner:"Golmote"},"icu-message-format":{title:"ICU Message Format",owner:"RunDevelopment"},idris:{title:"Idris",alias:"idr",owner:"KeenS",require:"haskell"},ignore:{title:".ignore",owner:"osipxd",alias:["gitignore","hgignore","npmignore"],aliasTitles:{gitignore:".gitignore",hgignore:".hgignore",npmignore:".npmignore"}},inform7:{title:"Inform 7",owner:"Golmote"},ini:{title:"Ini",owner:"aviaryan"},io:{title:"Io",owner:"AlesTsurko"},j:{title:"J",owner:"Golmote"},java:{title:"Java",require:"clike",owner:"sherblot"},javadoc:{title:"JavaDoc",require:["markup","java","javadoclike"],modify:"java",optional:"scala",owner:"RunDevelopment"},javadoclike:{title:"JavaDoc-like",modify:["java","javascript","php"],owner:"RunDevelopment"},javastacktrace:{title:"Java stack trace",owner:"RunDevelopment"},jexl:{title:"Jexl",owner:"czosel"},jolie:{title:"Jolie",require:"clike",owner:"thesave"},jq:{title:"JQ",owner:"RunDevelopment"},jsdoc:{title:"JSDoc",require:["javascript","javadoclike","typescript"],modify:"javascript",optional:["actionscript","coffeescript"],owner:"RunDevelopment"},"js-extras":{title:"JS Extras",require:"javascript",modify:"javascript",optional:["actionscript","coffeescript","flow","n4js","typescript"],owner:"RunDevelopment"},json:{title:"JSON",alias:"webmanifest",aliasTitles:{webmanifest:"Web App Manifest"},owner:"CupOfTea696"},json5:{title:"JSON5",require:"json",owner:"RunDevelopment"},jsonp:{title:"JSONP",require:"json",owner:"RunDevelopment"},jsstacktrace:{title:"JS stack trace",owner:"sbrl"},"js-templates":{title:"JS Templates",require:"javascript",modify:"javascript",optional:["css","css-extras","graphql","markdown","markup","sql"],owner:"RunDevelopment"},julia:{title:"Julia",owner:"cdagnino"},keepalived:{title:"Keepalived Configure",owner:"dev-itsheng"},keyman:{title:"Keyman",owner:"mcdurdin"},kotlin:{title:"Kotlin",alias:["kt","kts"],aliasTitles:{kts:"Kotlin Script"},require:"clike",owner:"Golmote"},kumir:{title:"KuMir (\u041a\u0443\u041c\u0438\u0440)",alias:"kum",owner:"edukisto"},kusto:{title:"Kusto",owner:"RunDevelopment"},latex:{title:"LaTeX",alias:["tex","context"],aliasTitles:{tex:"TeX",context:"ConTeXt"},owner:"japborst"},latte:{title:"Latte",require:["clike","markup-templating","php"],owner:"nette"},less:{title:"Less",require:"css",optional:"css-extras",owner:"Golmote"},lilypond:{title:"LilyPond",require:"scheme",alias:"ly",owner:"RunDevelopment"},liquid:{title:"Liquid",require:"markup-templating",owner:"cinhtau"},lisp:{title:"Lisp",alias:["emacs","elisp","emacs-lisp"],owner:"JuanCaicedo"},livescript:{title:"LiveScript",owner:"Golmote"},llvm:{title:"LLVM IR",owner:"porglezomp"},log:{title:"Log file",optional:"javastacktrace",owner:"RunDevelopment"},lolcode:{title:"LOLCODE",owner:"Golmote"},lua:{title:"Lua",owner:"Golmote"},magma:{title:"Magma (CAS)",owner:"RunDevelopment"},makefile:{title:"Makefile",owner:"Golmote"},markdown:{title:"Markdown",require:"markup",optional:"yaml",alias:"md",owner:"Golmote"},"markup-templating":{title:"Markup templating",require:"markup",owner:"Golmote"},mata:{title:"Mata",owner:"RunDevelopment"},matlab:{title:"MATLAB",owner:"Golmote"},maxscript:{title:"MAXScript",owner:"RunDevelopment"},mel:{title:"MEL",owner:"Golmote"},mermaid:{title:"Mermaid",owner:"RunDevelopment"},metafont:{title:"METAFONT",owner:"LaeriExNihilo"},mizar:{title:"Mizar",owner:"Golmote"},mongodb:{title:"MongoDB",owner:"airs0urce",require:"javascript"},monkey:{title:"Monkey",owner:"Golmote"},moonscript:{title:"MoonScript",alias:"moon",owner:"RunDevelopment"},n1ql:{title:"N1QL",owner:"TMWilds"},n4js:{title:"N4JS",require:"javascript",optional:"jsdoc",alias:"n4jsd",owner:"bsmith-n4"},"nand2tetris-hdl":{title:"Nand To Tetris HDL",owner:"stephanmax"},naniscript:{title:"Naninovel Script",owner:"Elringus",alias:"nani"},nasm:{title:"NASM",owner:"rbmj"},neon:{title:"NEON",owner:"nette"},nevod:{title:"Nevod",owner:"nezaboodka"},nginx:{title:"nginx",owner:"volado"},nim:{title:"Nim",owner:"Golmote"},nix:{title:"Nix",owner:"Golmote"},nsis:{title:"NSIS",owner:"idleberg"},objectivec:{title:"Objective-C",require:"c",alias:"objc",owner:"uranusjr"},ocaml:{title:"OCaml",owner:"Golmote"},odin:{title:"Odin",owner:"edukisto"},opencl:{title:"OpenCL",require:"c",modify:["c","cpp"],owner:"Milania1"},openqasm:{title:"OpenQasm",alias:"qasm",owner:"RunDevelopment"},oz:{title:"Oz",owner:"Golmote"},parigp:{title:"PARI/GP",owner:"Golmote"},parser:{title:"Parser",require:"markup",owner:"Golmote"},pascal:{title:"Pascal",alias:"objectpascal",aliasTitles:{objectpascal:"Object Pascal"},owner:"Golmote"},pascaligo:{title:"Pascaligo",owner:"DefinitelyNotAGoat"},psl:{title:"PATROL Scripting Language",owner:"bertysentry"},pcaxis:{title:"PC-Axis",alias:"px",owner:"RunDevelopment"},peoplecode:{title:"PeopleCode",alias:"pcode",owner:"RunDevelopment"},perl:{title:"Perl",owner:"Golmote"},php:{title:"PHP",require:"markup-templating",owner:"milesj"},phpdoc:{title:"PHPDoc",require:["php","javadoclike"],modify:"php",owner:"RunDevelopment"},"php-extras":{title:"PHP Extras",require:"php",modify:"php",owner:"milesj"},"plant-uml":{title:"PlantUML",alias:"plantuml",owner:"RunDevelopment"},plsql:{title:"PL/SQL",require:"sql",owner:"Golmote"},powerquery:{title:"PowerQuery",alias:["pq","mscript"],owner:"peterbud"},powershell:{title:"PowerShell",owner:"nauzilus"},processing:{title:"Processing",require:"clike",owner:"Golmote"},prolog:{title:"Prolog",owner:"Golmote"},promql:{title:"PromQL",owner:"arendjr"},properties:{title:".properties",owner:"Golmote"},protobuf:{title:"Protocol Buffers",require:"clike",owner:"just-boris"},pug:{title:"Pug",require:["markup","javascript"],optional:["coffeescript","ejs","handlebars","less","livescript","markdown","scss","stylus","twig"],owner:"Golmote"},puppet:{title:"Puppet",owner:"Golmote"},pure:{title:"Pure",optional:["c","cpp","fortran"],owner:"Golmote"},purebasic:{title:"PureBasic",require:"clike",alias:"pbfasm",owner:"HeX0R101"},purescript:{title:"PureScript",require:"haskell",alias:"purs",owner:"sriharshachilakapati"},python:{title:"Python",alias:"py",owner:"multipetros"},qsharp:{title:"Q#",require:"clike",alias:"qs",owner:"fedonman"},q:{title:"Q (kdb+ database)",owner:"Golmote"},qml:{title:"QML",require:"javascript",owner:"RunDevelopment"},qore:{title:"Qore",require:"clike",owner:"temnroegg"},r:{title:"R",owner:"Golmote"},racket:{title:"Racket",require:"scheme",alias:"rkt",owner:"RunDevelopment"},cshtml:{title:"Razor C#",alias:"razor",require:["markup","csharp"],optional:["css","css-extras","javascript","js-extras"],owner:"RunDevelopment"},jsx:{title:"React JSX",require:["markup","javascript"],optional:["jsdoc","js-extras","js-templates"],owner:"vkbansal"},tsx:{title:"React TSX",require:["jsx","typescript"]},reason:{title:"Reason",require:"clike",owner:"Golmote"},regex:{title:"Regex",owner:"RunDevelopment"},rego:{title:"Rego",owner:"JordanSh"},renpy:{title:"Ren'py",alias:"rpy",owner:"HyuchiaDiego"},rescript:{title:"ReScript",alias:"res",owner:"vmarcosp"},rest:{title:"reST (reStructuredText)",owner:"Golmote"},rip:{title:"Rip",owner:"ravinggenius"},roboconf:{title:"Roboconf",owner:"Golmote"},robotframework:{title:"Robot Framework",alias:"robot",owner:"RunDevelopment"},ruby:{title:"Ruby",require:"clike",alias:"rb",owner:"samflores"},rust:{title:"Rust",owner:"Golmote"},sas:{title:"SAS",optional:["groovy","lua","sql"],owner:"Golmote"},sass:{title:"Sass (Sass)",require:"css",optional:"css-extras",owner:"Golmote"},scss:{title:"Sass (SCSS)",require:"css",optional:"css-extras",owner:"MoOx"},scala:{title:"Scala",require:"java",owner:"jozic"},scheme:{title:"Scheme",owner:"bacchus123"},"shell-session":{title:"Shell session",require:"bash",alias:["sh-session","shellsession"],owner:"RunDevelopment"},smali:{title:"Smali",owner:"RunDevelopment"},smalltalk:{title:"Smalltalk",owner:"Golmote"},smarty:{title:"Smarty",require:"markup-templating",optional:"php",owner:"Golmote"},sml:{title:"SML",alias:"smlnj",aliasTitles:{smlnj:"SML/NJ"},owner:"RunDevelopment"},solidity:{title:"Solidity (Ethereum)",alias:"sol",require:"clike",owner:"glachaud"},"solution-file":{title:"Solution file",alias:"sln",owner:"RunDevelopment"},soy:{title:"Soy (Closure Template)",require:"markup-templating",owner:"Golmote"},sparql:{title:"SPARQL",require:"turtle",owner:"Triply-Dev",alias:"rq"},"splunk-spl":{title:"Splunk SPL",owner:"RunDevelopment"},sqf:{title:"SQF: Status Quo Function (Arma 3)",require:"clike",owner:"RunDevelopment"},sql:{title:"SQL",owner:"multipetros"},squirrel:{title:"Squirrel",require:"clike",owner:"RunDevelopment"},stan:{title:"Stan",owner:"RunDevelopment"},stata:{title:"Stata Ado",require:["mata","java","python"],owner:"RunDevelopment"},iecst:{title:"Structured Text (IEC 61131-3)",owner:"serhioromano"},stylus:{title:"Stylus",owner:"vkbansal"},supercollider:{title:"SuperCollider",alias:"sclang",owner:"RunDevelopment"},swift:{title:"Swift",owner:"chrischares"},systemd:{title:"Systemd configuration file",owner:"RunDevelopment"},"t4-templating":{title:"T4 templating",owner:"RunDevelopment"},"t4-cs":{title:"T4 Text Templates (C#)",require:["t4-templating","csharp"],alias:"t4",owner:"RunDevelopment"},"t4-vb":{title:"T4 Text Templates (VB)",require:["t4-templating","vbnet"],owner:"RunDevelopment"},tap:{title:"TAP",owner:"isaacs",require:"yaml"},tcl:{title:"Tcl",owner:"PeterChaplin"},tt2:{title:"Template Toolkit 2",require:["clike","markup-templating"],owner:"gflohr"},textile:{title:"Textile",require:"markup",optional:"css",owner:"Golmote"},toml:{title:"TOML",owner:"RunDevelopment"},tremor:{title:"Tremor",alias:["trickle","troy"],owner:"darach",aliasTitles:{trickle:"trickle",troy:"troy"}},turtle:{title:"Turtle",alias:"trig",aliasTitles:{trig:"TriG"},owner:"jakubklimek"},twig:{title:"Twig",require:"markup-templating",owner:"brandonkelly"},typescript:{title:"TypeScript",require:"javascript",optional:"js-templates",alias:"ts",owner:"vkbansal"},typoscript:{title:"TypoScript",alias:"tsconfig",aliasTitles:{tsconfig:"TSConfig"},owner:"dkern"},unrealscript:{title:"UnrealScript",alias:["uscript","uc"],owner:"RunDevelopment"},uorazor:{title:"UO Razor Script",owner:"jaseowns"},uri:{title:"URI",alias:"url",aliasTitles:{url:"URL"},owner:"RunDevelopment"},v:{title:"V",require:"clike",owner:"taggon"},vala:{title:"Vala",require:"clike",optional:"regex",owner:"TemplarVolk"},vbnet:{title:"VB.Net",require:"basic",owner:"Bigsby"},velocity:{title:"Velocity",require:"markup",owner:"Golmote"},verilog:{title:"Verilog",owner:"a-rey"},vhdl:{title:"VHDL",owner:"a-rey"},vim:{title:"vim",owner:"westonganger"},"visual-basic":{title:"Visual Basic",alias:["vb","vba"],aliasTitles:{vba:"VBA"},owner:"Golmote"},warpscript:{title:"WarpScript",owner:"RunDevelopment"},wasm:{title:"WebAssembly",owner:"Golmote"},"web-idl":{title:"Web IDL",alias:"webidl",owner:"RunDevelopment"},wgsl:{title:"WGSL",owner:"Dr4gonthree"},wiki:{title:"Wiki markup",require:"markup",owner:"Golmote"},wolfram:{title:"Wolfram language",alias:["mathematica","nb","wl"],aliasTitles:{mathematica:"Mathematica",nb:"Mathematica Notebook"},owner:"msollami"},wren:{title:"Wren",owner:"clsource"},xeora:{title:"Xeora",require:"markup",alias:"xeoracube",aliasTitles:{xeoracube:"XeoraCube"},owner:"freakmaxi"},"xml-doc":{title:"XML doc (.net)",require:"markup",modify:["csharp","fsharp","vbnet"],owner:"RunDevelopment"},xojo:{title:"Xojo (REALbasic)",owner:"Golmote"},xquery:{title:"XQuery",require:"markup",owner:"Golmote"},yaml:{title:"YAML",alias:"yml",owner:"hason"},yang:{title:"YANG",owner:"RunDevelopment"},zig:{title:"Zig",owner:"RunDevelopment"}},plugins:{meta:{path:"plugins/{id}/prism-{id}",link:"plugins/{id}/"},"line-highlight":{title:"Line Highlight",description:"Highlights specific lines and/or line ranges."},"line-numbers":{title:"Line Numbers",description:"Line number at the beginning of code lines.",owner:"kuba-kubula"},"show-invisibles":{title:"Show Invisibles",description:"Show hidden characters such as tabs and line breaks.",optional:["autolinker","data-uri-highlight"]},autolinker:{title:"Autolinker",description:"Converts URLs and emails in code to clickable links. Parses Markdown links in comments."},wpd:{title:"WebPlatform Docs",description:'Makes tokens link to WebPlatform.org documentation. The links open in a new tab.'},"custom-class":{title:"Custom Class",description:"This plugin allows you to prefix Prism's default classes (.comment can become .namespace--comment) or replace them with your defined ones (like .editor__comment). You can even add new classes.",owner:"dvkndn",noCSS:!0},"file-highlight":{title:"File Highlight",description:"Fetch external files and highlight them with Prism. Used on the Prism website itself.",noCSS:!0},"show-language":{title:"Show Language",description:"Display the highlighted language in code blocks (inline code does not show the label).",owner:"nauzilus",noCSS:!0,require:"toolbar"},"jsonp-highlight":{title:"JSONP Highlight",description:"Fetch content with JSONP and highlight some interesting content (e.g. GitHub/Gists or Bitbucket API).",noCSS:!0,owner:"nauzilus"},"highlight-keywords":{title:"Highlight Keywords",description:"Adds special CSS classes for each keyword for fine-grained highlighting.",owner:"vkbansal",noCSS:!0},"remove-initial-line-feed":{title:"Remove initial line feed",description:"Removes the initial line feed in code blocks.",owner:"Golmote",noCSS:!0},"inline-color":{title:"Inline color",description:"Adds a small inline preview for colors in style sheets.",require:"css-extras",owner:"RunDevelopment"},previewers:{title:"Previewers",description:"Previewers for angles, colors, gradients, easing and time.",require:"css-extras",owner:"Golmote"},autoloader:{title:"Autoloader",description:"Automatically loads the needed languages to highlight the code blocks.",owner:"Golmote",noCSS:!0},"keep-markup":{title:"Keep Markup",description:"Prevents custom markup from being dropped out during highlighting.",owner:"Golmote",optional:"normalize-whitespace",noCSS:!0},"command-line":{title:"Command Line",description:"Display a command line with a prompt and, optionally, the output/response from the commands.",owner:"chriswells0"},"unescaped-markup":{title:"Unescaped Markup",description:"Write markup without having to escape anything."},"normalize-whitespace":{title:"Normalize Whitespace",description:"Supports multiple operations to normalize whitespace in code blocks.",owner:"zeitgeist87",optional:"unescaped-markup",noCSS:!0},"data-uri-highlight":{title:"Data-URI Highlight",description:"Highlights data-URI contents.",owner:"Golmote",noCSS:!0},toolbar:{title:"Toolbar",description:"Attach a toolbar for plugins to easily register buttons on the top of a code block.",owner:"mAAdhaTTah"},"copy-to-clipboard":{title:"Copy to Clipboard Button",description:"Add a button that copies the code block to the clipboard when clicked.",owner:"mAAdhaTTah",require:"toolbar",noCSS:!0},"download-button":{title:"Download Button",description:"A button in the toolbar of a code block adding a convenient way to download a code file.",owner:"Golmote",require:"toolbar",noCSS:!0},"match-braces":{title:"Match braces",description:"Highlights matching braces.",owner:"RunDevelopment"},"diff-highlight":{title:"Diff Highlight",description:"Highlights the code inside diff blocks.",owner:"RunDevelopment",require:"diff"},"filter-highlight-all":{title:"Filter highlightAll",description:"Filters the elements the highlightAll and highlightAllUnder methods actually highlight.",owner:"RunDevelopment",noCSS:!0},treeview:{title:"Treeview",description:"A language with special styles to highlight file system tree structures.",owner:"Golmote"}}})},2885:(e,t,n)=>{const r=n(9901),a=n(9642),o=new Set;function i(e){void 0===e?e=Object.keys(r.languages).filter((e=>"meta"!=e)):Array.isArray(e)||(e=[e]);const t=[...o,...Object.keys(Prism.languages)];a(r,e,t).load((e=>{if(!(e in r.languages))return void(i.silent||console.warn("Language does not exist: "+e));const t="./prism-"+e;delete n.c[n(6500).resolve(t)],delete Prism.languages[e],n(6500)(t),o.add(e)}))}i.silent=!1,e.exports=i},6726:(e,t,n)=>{var r={"./":2885};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=6726},6500:(e,t,n)=>{var r={"./":2885};function a(e){var t=o(e);return n(t)}function o(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}a.keys=function(){return Object.keys(r)},a.resolve=o,e.exports=a,a.id=6500},9642:e=>{"use strict";var t=function(){var e=function(){};function t(e,t){Array.isArray(e)?e.forEach(t):null!=e&&t(e,0)}function n(e){for(var t={},n=0,r=e.length;n "));var s={},l=e[r];if(l){function c(t){if(!(t in e))throw new Error(r+" depends on an unknown component "+t);if(!(t in s))for(var i in a(t,o),s[t]=!0,n[t])s[i]=!0}t(l.require,c),t(l.optional,c),t(l.modify,c)}n[r]=s,o.pop()}}return function(e){var t=n[e];return t||(a(e,r),t=n[e]),t}}function a(e){for(var t in e)return!0;return!1}return function(o,i,s){var l=function(e){var t={};for(var n in e){var r=e[n];for(var a in r)if("meta"!=a){var o=r[a];t[a]="string"==typeof o?{title:o}:o}}return t}(o),c=function(e){var n;return function(r){if(r in e)return r;if(!n)for(var a in n={},e){var o=e[a];t(o&&o.alias,(function(t){if(t in n)throw new Error(t+" cannot be alias for both "+a+" and "+n[t]);if(t in e)throw new Error(t+" cannot be alias of "+a+" because it is a component.");n[t]=a}))}return n[r]||r}}(l);i=i.map(c),s=(s||[]).map(c);var u=n(i),d=n(s);i.forEach((function e(n){var r=l[n];t(r&&r.require,(function(t){t in d||(u[t]=!0,e(t))}))}));for(var f,p=r(l),g=u;a(g);){for(var m in f={},g){var h=l[m];t(h&&h.modify,(function(e){e in d&&(f[e]=!0)}))}for(var b in d)if(!(b in u))for(var v in p(b))if(v in u){f[b]=!0;break}for(var y in g=f)u[y]=!0}var w={getIds:function(){var e=[];return w.load((function(t){e.push(t)})),e},load:function(t,n){return function(t,n,r,a){var o=a?a.series:void 0,i=a?a.parallel:e,s={},l={};function c(e){if(e in s)return s[e];l[e]=!0;var a,u=[];for(var d in t(e))d in n&&u.push(d);if(0===u.length)a=r(e);else{var f=i(u.map((function(e){var t=c(e);return delete l[e],t})));o?a=o(f,(function(){return r(e)})):r(e)}return s[e]=a}for(var u in n)c(u);var d=[];for(var f in l)d.push(s[f]);return i(d)}(p,u,t,n)}};return w}}();e.exports=t},2703:(e,t,n)=>{"use strict";var r=n(414);function a(){}function o(){}o.resetWarningCache=a,e.exports=function(){function e(e,t,n,a,o,i){if(i!==r){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:o,resetWarningCache:a};return n.PropTypes=n,n}},5697:(e,t,n)=>{e.exports=n(2703)()},414:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},4448:(e,t,n)=>{"use strict";var r=n(7294),a=n(7418),o=n(3840);function i(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n