[{"data":1,"prerenderedAt":816},["ShallowReactive",2],{"\u002Fdocs\u002Fguides\u002Fssh":3},{"id":4,"title":5,"body":6,"description":808,"extension":809,"meta":810,"navigation":811,"path":812,"seo":813,"stem":814,"__hash__":815},"docs\u002Fdocs\u002Fguides\u002Fssh.md","SSH",{"type":7,"value":8,"toc":796},"minimark",[9,13,28,62,65,134,137,142,174,178,181,231,234,291,326,337,341,347,451,461,465,540,543,546,560,582,585,614,618,621,647,656,718,722,779,783,792],[10,11,5],"h1",{"id":12},"ssh",[14,15,16,17,22,23,27],"p",{},"For devices that can't run the ",[18,19,21],"a",{"href":20},"\u002Fdocs\u002Fagents\u002Flinux","Linux agent"," (many NAS systems, a Mac, a BSD\nbox, a Windows PC with OpenSSH Server), NetIgnite can shut them down and reboot them over SSH. The\n",[24,25,26],"strong",{},"device's agent"," logs in, because it's the one inside the LAN; the server stores the login and\nsends it to that agent for each command.",[29,30,31],"warning",{},[14,32,33,36,37,39,40,42,43,46,47,51,52,56,57,61],{},[24,34,35],{},"Prefer the Linux agent wherever it runs."," For a Linux machine with systemd, install the\n",[18,38,21],{"href":20}," on it and choose it as the device's ",[24,41,21],{}," instead of\nsetting up SSH. It can only shut down and reboot that machine (through polkit), and no login to the\nmachine is stored anywhere. With SSH, the server stores a login to the device: whoever gets the\nserver's database ",[24,44,45],{},"and"," its secrets key can log in to the device with it. If you use SSH, log in\nas a ",[18,48,50],{"href":49},"#a-dedicated-user","dedicated user"," that may only shut down and reboot, with a generated key.\nNever use ",[53,54,55],"code",{},"root",", an administrator or your own account (Windows is the exception that needs an\nadministrator, see ",[18,58,60],{"href":59},"#windows","Windows",").",[14,63,64],{},"What NetIgnite does over SSH is fixed:",[66,67,68,90],"table",{},[69,70,71],"thead",{},[72,73,74,77,80,87],"tr",{},[75,76],"th",{},[75,78,79],{},"Linux, macOS, BSD",[75,81,82,83],{},"with ",[84,85,86],"em",{},"Use sudo",[75,88,89],{},"Windows (OpenSSH)",[91,92,93,114],"tbody",{},[72,94,95,99,104,109],{},[96,97,98],"td",{},"Shut down",[96,100,101],{},[53,102,103],{},"shutdown -h now",[96,105,106],{},[53,107,108],{},"sudo -n shutdown -h now",[96,110,111],{},[53,112,113],{},"shutdown \u002Fs \u002Ft 0",[72,115,116,119,124,129],{},[96,117,118],{},"Reboot",[96,120,121],{},[53,122,123],{},"shutdown -r now",[96,125,126],{},[53,127,128],{},"sudo -n shutdown -r now",[96,130,131],{},[53,132,133],{},"shutdown \u002Fr \u002Ft 0",[14,135,136],{},"There's no way to run anything else: no shell, no file access, no other commands.",[138,139,141],"h2",{"id":140},"requirements","Requirements",[143,144,145,165,168],"ul",{},[146,147,148,149,152,153,156,157,161,162,164],"li",{},"The device's ",[24,150,151],{},"Agent"," (on its ",[24,154,155],{},"General"," tab) must be able to log in over SSH and be online: an\nESP32 agent or a Linux agent in ",[18,158,160],{"href":159},"\u002Fdocs\u002Fagents\u002Flinux#wake-on-lan-mode","Wake-on-LAN mode",", in the\ndevice's network. The agent's capabilities on its page include ",[53,163,12],{}," then.",[146,166,167],{},"An SSH server on the device, reachable from the agent.",[146,169,170,171,173],{},"You must be the device's owner. The ",[24,172,5],{}," tab isn't available to users the device is shared\nwith.",[138,175,177],{"id":176},"a-dedicated-user","A dedicated user",[14,179,180],{},"The stored login should be able to do as little as possible on the device, so that a leaked login\nallows nothing but a shutdown:",[143,182,183,196,221],{},[146,184,185,188,189,192,193,195],{},[24,186,187],{},"A user only for NetIgnite",", for example ",[53,190,191],{},"netignite",". Not ",[53,194,55],{},", not your own account.",[146,197,198,201,202,205,206,205,209,212,213,216,217,220],{},[24,199,200],{},"No other rights."," Don't add it to ",[53,203,204],{},"sudo",", ",[53,207,208],{},"wheel",[53,210,211],{},"admin"," or any other group with extra\nrights. The sudoers line from ",[24,214,215],{},"Prepare the device"," allows it exactly the two ",[53,218,219],{},"shutdown","\ncommands.",[146,222,223,226,227,230],{},[24,224,225],{},"A generated key, not a password."," The ",[53,228,229],{},"authorized_keys"," line of a generated key lets only the\ntwo commands through. A password works for everything the account can do, including a shell.",[14,232,233],{},"On Linux, create the user with:",[235,236,241],"pre",{"className":237,"code":238,"language":239,"meta":240,"style":240},"language-sh shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","sudo useradd --create-home --shell \u002Fbin\u002Fsh netignite\nsudo -u netignite mkdir -m 700 \u002Fhome\u002Fnetignite\u002F.ssh\n","sh","",[53,242,243,267],{"__ignoreMap":240},[244,245,248,251,255,258,261,264],"span",{"class":246,"line":247},"line",1,[244,249,204],{"class":250},"sBMFI",[244,252,254],{"class":253},"sfazB"," useradd",[244,256,257],{"class":253}," --create-home",[244,259,260],{"class":253}," --shell",[244,262,263],{"class":253}," \u002Fbin\u002Fsh",[244,265,266],{"class":253}," netignite\n",[244,268,270,272,275,278,281,284,288],{"class":246,"line":269},2,[244,271,204],{"class":250},[244,273,274],{"class":253}," -u",[244,276,277],{"class":253}," netignite",[244,279,280],{"class":253}," mkdir",[244,282,283],{"class":253}," -m",[244,285,287],{"class":286},"sbssI"," 700",[244,289,290],{"class":253}," \u002Fhome\u002Fnetignite\u002F.ssh\n",[14,292,293,294,297,298,301,302,304,305,309,310,313,314,317,318,321,322,325],{},"Keep a real shell such as ",[53,295,296],{},"\u002Fbin\u002Fsh"," (not ",[53,299,300],{},"nologin","): SSH runs the forced command through the user's\nshell. Then add the ",[53,303,229],{}," and sudoers lines as described\n",[18,306,308],{"href":307},"#linux-macos-bsd","below",". On macOS, create a ",[24,311,312],{},"Standard"," user (not an administrator) in\n",[24,315,316],{},"System Settings → Users & Groups"," and allow it under ",[24,319,320],{},"Remote Login","; on BSD, use ",[53,323,324],{},"adduser",".",[14,327,328,329,205,331,333,334,325],{},"For Linux, macOS and BSD, the dashboard warns when the username is ",[53,330,55],{},[53,332,211],{}," or ",[53,335,336],{},"Administrator",[138,338,340],{"id":339},"setting-up-the-login","Setting up the login",[14,342,343,344,346],{},"Open the device and its ",[24,345,5],{}," tab:",[66,348,349,359],{},[69,350,351],{},[72,352,353,356],{},[75,354,355],{},"Field",[75,357,358],{},"Description",[91,360,361,371,384,398,412,430],{},[72,362,363,368],{},[96,364,365],{},[24,366,367],{},"Host",[96,369,370],{},"Host name or IP address. Empty: the device's status check address.",[72,372,373,378],{},[96,374,375],{},[24,376,377],{},"Port",[96,379,380,381,325],{},"Usually ",[53,382,383],{},"22",[72,385,386,391],{},[96,387,388],{},[24,389,390],{},"Username",[96,392,393,394,188,396,325],{},"The account the agent logs in with: a ",[18,395,50],{"href":49},[53,397,191],{},[72,399,400,405],{},[96,401,402],{},[24,403,404],{},"Operating system",[96,406,407,333,409,411],{},[84,408,79],{},[84,410,89],{},". Decides the command (table above).",[72,413,414,418],{},[96,415,416],{},[24,417,86],{},[96,419,420,421,423,424,427,428,325],{},"Linux, macOS, BSD: run ",[53,422,219],{}," with ",[53,425,426],{},"sudo -n",". Not needed for ",[53,429,55],{},[72,431,432,437],{},[96,433,434],{},[24,435,436],{},"Authentication",[96,438,439,442,443,446,447,450],{},[24,440,441],{},"New key pair"," (recommended): the server generates an Ed25519 key pair. ",[24,444,445],{},"Password",": the account's password. ",[24,448,449],{},"Keep the current",": change the other fields only.",[14,452,453,454,457,458,460],{},"Click ",[24,455,456],{},"Save login",". With a generated key, the ",[24,459,215],{}," card shows what to add on\nthe device.",[462,463,79],"h3",{"id":464},"linux-macos-bsd",[466,467,468,512],"ol",{},[146,469,470,471,473,474,477,478,480,481,489,492,495,496,499,500,503,504,507,508,511],{},"Add the line from ",[24,472,215],{}," to ",[53,475,476],{},"~\u002F.ssh\u002Fauthorized_keys"," of the user. It looks\nlike this (with ",[84,479,86],{},"):",[235,482,487],{"className":483,"code":485,"filename":229,"language":486,"meta":240},[484],"language-text","restrict,command=\"case \\\"$SSH_ORIGINAL_COMMAND\\\" in 'sudo -n shutdown -h now'|'sudo -n shutdown -r now') exec $SSH_ORIGINAL_COMMAND ;; *) echo 'Only shutdown and reboot are allowed' >&2; exit 1 ;; esac\" ssh-ed25519 AAAA… netignite-device-7\n","text",[53,488,485],{"__ignoreMap":240},[490,491],"br",{},[53,493,494],{},"restrict"," turns off port forwarding, agent forwarding and a terminal. The forced ",[53,497,498],{},"command"," lets\nonly the two commands through and refuses anything else, so the key is useless for anything but\nshutdown and reboot. ",[24,501,502],{},"Test login"," doesn't open a session, so the forced command doesn't run\nfor it. You can add ",[53,505,506],{},"from=\"\u003Cagent's IP address>\""," after ",[53,509,510],{},"restrict,"," to accept the key only\nfrom the agent.",[146,513,514,515,517,518,521,522,524,525,532,534,536,537,325],{},"With ",[84,516,86],{},", allow the two commands without a password. Run\n",[53,519,520],{},"sudo visudo -f \u002Fetc\u002Fsudoers.d\u002Fnetignite"," and add the line from ",[24,523,215],{},":",[235,526,530],{"className":527,"code":528,"filename":529,"language":486,"meta":240},[484],"netignite ALL=(root) NOPASSWD: \u002Fusr\u002Fsbin\u002Fshutdown -h now, \u002Fusr\u002Fsbin\u002Fshutdown -r now, \u002Fsbin\u002Fshutdown -h now, \u002Fsbin\u002Fshutdown -r now\n","sudoers",[53,531,528],{"__ignoreMap":240},[490,533],{},[53,535,426],{}," fails at once instead of asking for a password, so a missing line shows up in the\ndashboard as ",[53,538,539],{},"sudo: a password is required",[14,541,542],{},"With a password instead of a key, there's no forced command: the account can do whatever its\npassword allows. Prefer a key.",[462,544,60],{"id":545},"windows",[14,547,548,549,552,553,556,557,559],{},"Install ",[24,550,551],{},"OpenSSH Server"," (Settings → System → Optional features), start the ",[53,554,555],{},"sshd"," service and\nchoose ",[84,558,89],{}," as the operating system. Shutting down needs an administrator account,\nso on Windows the login can't be limited to shutdown and reboot: whoever gets it controls the PC.\nKeep the risk small:",[143,561,562,571],{},[146,563,564,565,568,569,325],{},"Create a ",[24,566,567],{},"separate administrator account only for NetIgnite"," instead of using your own or the\nbuilt-in ",[53,570,336],{},[146,572,573,574,577,578,581],{},"Use a ",[24,575,576],{},"generated key"," rather than a password, and accept it only from the agent: put\n",[53,579,580],{},"restrict,from=\"\u003Cagent's IP address>\""," at the start of its line.",[14,583,584],{},"Where the login goes:",[143,586,587,608],{},[146,588,589,592,593,595,596,599,600,603,604,607],{},[24,590,591],{},"Key:"," put the line from ",[24,594,215],{}," (",[53,597,598],{},"restrict ssh-ed25519 AAAA…",") into\n",[53,601,602],{},"C:\\ProgramData\\ssh\\administrators_authorized_keys",". Only Administrators and SYSTEM may have\naccess to that file. Windows' OpenSSH runs forced commands through ",[53,605,606],{},"cmd.exe",", so this line has no\nforced command.",[146,609,610,613],{},[24,611,612],{},"Password:"," use the account's password.",[138,615,617],{"id":616},"trusting-the-host-key","Trusting the host key",[14,619,620],{},"NetIgnite trusts a device's SSH host key on first use, after you've checked it:",[466,622,623,636,642],{},[146,624,625,626,629,630,632,633,61],{},"In the ",[24,627,628],{},"Host key"," card, click ",[24,631,502],{},". The agent connects, checks the login without\nrunning anything and reports the device's host key fingerprint (",[53,634,635],{},"SHA256:…",[146,637,638,639,325],{},"Compare it with the key on the device, for example\n",[53,640,641],{},"ssh-keygen -lf \u002Fetc\u002Fssh\u002Fssh_host_ed25519_key.pub",[146,643,453,644,325],{},[24,645,646],{},"Trust this host key",[14,648,649,650,652,653,655],{},"Shutdown and reboot over SSH work from then on: the power button of the device gets ",[24,651,98],{},"\nand ",[24,654,118],{},". Every later login checks the key first and stops before sending the password or\nkey if it differs. Changing the login's host or port removes the trusted key; test and trust again.",[66,657,658,668],{},[69,659,660],{},[72,661,662,665],{},[75,663,664],{},"Test result",[75,666,667],{},"Meaning",[91,669,670,680,690,706],{},[72,671,672,677],{},[96,673,674],{},[84,675,676],{},"Login works",[96,678,679],{},"The agent logged in. Trust the key if you haven't.",[72,681,682,687],{},[96,683,684],{},[84,685,686],{},"The device didn't answer on its SSH port",[96,688,689],{},"Wrong host or port, the device is off, or a firewall blocks it.",[72,691,692,700],{},[96,693,694,205,697],{},[84,695,696],{},"Login failed",[53,698,699],{},"auth_failed",[96,701,702,703,705],{},"Wrong username, password, or ",[53,704,229],{}," line.",[72,707,708,715],{},[96,709,710,205,712],{},[84,711,696],{},[53,713,714],{},"host_key_mismatch",[96,716,717],{},"The device presents another key than the trusted one. If you reinstalled the device, trust the new key; otherwise someone may be intercepting the connection.",[138,719,721],{"id":720},"security","Security",[143,723,724,736,742,755,761,767],{},[146,725,726,729,730,732,733,735],{},[24,727,728],{},"A stored login is a key to the device."," That's why the ",[18,731,21],{"href":20}," is the\nbetter choice for Linux machines, and why the login should belong to a\n",[18,734,50],{"href":49}," that may only shut down and reboot.",[146,737,738,741],{},[24,739,740],{},"Write-only."," The API never returns a stored password or private key. The dashboard only shows\nthe public key.",[146,743,744,747,748,333,751,754],{},[24,745,746],{},"Encrypted at rest."," Passwords and private keys are encrypted with the server's secrets key\n(",[53,749,750],{},"NETIGNITE_SECRETS_KEY",[53,752,753],{},"config\u002Fsecrets.key","). Back up the key with the database; without it,\nyou have to set the logins up again.",[146,756,757,760],{},[24,758,759],{},"Only to the device's agent."," The login is sent over the agent's TLS WebSocket for each test or\ncommand, kept in memory only for that login and wiped afterwards. The agent never stores or logs\nit.",[146,762,763,766],{},[24,764,765],{},"Fixed commands, trusted host key."," Commands only run on a device whose host key you trusted.",[146,768,769,772,773,775,776,778],{},[24,770,771],{},"Owner only."," Users the device is shared with can use ",[24,774,98],{}," and ",[24,777,118],{}," (operators\nand managers) but can't see or change the login.",[138,780,782],{"id":781},"removing-the-login","Removing the login",[14,784,785,788,789,791],{},[24,786,787],{},"Remove SSH login"," deletes the stored password or key. Remove the ",[53,790,229],{}," line and the\nsudoers file from the device too.",[793,794,795],"style",{},"html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sbssI, html code.shiki .sbssI{--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":240,"searchDepth":269,"depth":269,"links":797},[798,799,800,805,806,807],{"id":140,"depth":269,"text":141},{"id":176,"depth":269,"text":177},{"id":339,"depth":269,"text":340,"children":801},[802,804],{"id":464,"depth":803,"text":79},3,{"id":545,"depth":803,"text":60},{"id":616,"depth":269,"text":617},{"id":720,"depth":269,"text":721},{"id":781,"depth":269,"text":782},"Shut down and reboot devices over SSH: why the Linux agent is the safer choice, a dedicated user with a generated Ed25519 key that may only shut down and reboot, and trusting the host key.","md",{},{"title":5},"\u002Fdocs\u002Fguides\u002Fssh",{"title":5,"description":808},"docs\u002Fguides\u002Fssh","E_w7BnJsMJviJQM9NB7Zu3Slr4YicJddv4PcL6Bmfj4",1792614952938]