[{"data":1,"prerenderedAt":1585},["ShallowReactive",2],{"page-\u002Flinux\u002F07-users-groups-auth":3},{"id":4,"title":5,"body":6,"description":1578,"extension":1579,"meta":1580,"navigation":401,"path":1581,"seo":1582,"stem":1583,"__hash__":1584},"content\u002Flinux\u002F07-users-groups-auth.md","07 — Users, Groups & Authentication",{"type":7,"value":8,"toc":1550},"minimark",[9,13,31,36,51,95,105,108,130,178,184,190,222,259,265,271,298,330,334,445,457,524,530,591,598,611,664,671,751,755,759,872,879,950,984,988,1007,1039,1045,1085,1089,1095,1159,1163,1263,1267,1412,1416,1426,1445,1455,1546],[10,11,5],"h1",{"id":12},"_07-users-groups-authentication",[14,15,16,17,21,22,25,26,30],"p",{},"Linux is a multi-user system. Every process runs ",[18,19,20],"strong",{},"as"," a user, every file is ",[18,23,24],{},"owned"," by a user, and access is controlled by comparing the process's identity to the file's ownership. This chapter covers the UID\u002FGID model, the PAM authentication stack, ",[27,28,29],"code",{},"sudo",", SSH key authentication, and the gotchas that cause \"permission denied\" mysteries.",[32,33,35],"h2",{"id":34},"users-and-uids","Users and UIDs",[14,37,38,39,42,43,46,47,50],{},"A ",[18,40,41],{},"user"," is identified by a ",[18,44,45],{},"UID"," (user ID, an integer). The username is just a human-friendly label mapped to a UID via ",[27,48,49],{},"\u002Fetc\u002Fpasswd",".",[52,53,54,67],"table",{},[55,56,57],"thead",{},[58,59,60,64],"tr",{},[61,62,63],"th",{},"UID Range",[61,65,66],{},"Purpose",[68,69,70,79,87],"tbody",{},[58,71,72,76],{},[73,74,75],"td",{},"0",[73,77,78],{},"root (the superuser)",[58,80,81,84],{},[73,82,83],{},"1–999",[73,85,86],{},"System accounts (daemon, bin, www-data, nobody)",[58,88,89,92],{},[73,90,91],{},"1000–60000",[73,93,94],{},"Regular users (default range on most distros)",[14,96,97,100,101,104],{},[18,98,99],{},"UID 0 is root",": the kernel checks ",[27,102,103],{},"uid == 0"," for privileged operations. The name \"root\" is convention; what matters is UID 0.",[14,106,107],{},"A process has three UIDs:",[109,110,111,118,124],"ul",{},[112,113,114,117],"li",{},[18,115,116],{},"real UID"," — who launched the process.",[112,119,120,123],{},[18,121,122],{},"effective UID"," — whose permissions it currently runs with (changed by setuid).",[112,125,126,129],{},[18,127,128],{},"saved UID"," — allows switching back (used by setuid programs).",[131,132,134],"code-wrapper",{"language":133},"bash",[135,136,140],"pre",{"className":137,"code":138,"language":133,"meta":139,"style":139},"language-bash shiki shiki-themes github-light github-dark","id                # uid=1000(alice) gid=1000(alice) groups=1000(alice),27(sudo)\nwhoami            # alice (effective user)\necho $UID         # 1000 (real UID, shell variable)\n","",[27,141,142,155,164],{"__ignoreMap":139},[143,144,147,151],"span",{"class":145,"line":146},"line",1,[143,148,150],{"class":149},"sIsaT","id",[143,152,154],{"class":153},"sdCPZ","                # uid=1000(alice) gid=1000(alice) groups=1000(alice),27(sudo)\n",[143,156,158,161],{"class":145,"line":157},2,[143,159,160],{"class":149},"whoami",[143,162,163],{"class":153},"            # alice (effective user)\n",[143,165,167,171,175],{"class":145,"line":166},3,[143,168,170],{"class":169},"snvgF","echo",[143,172,174],{"class":173},"ssxIu"," $UID         ",[143,176,177],{"class":153},"# 1000 (real UID, shell variable)\n",[32,179,181,183],{"id":180},"etcpasswd-user-database",[27,182,49],{}," — User Database",[14,185,186,187],{},"Format: ",[27,188,189],{},"username:password:UID:GID:GECOS:home:shell",[131,191,192],{"language":133},[135,193,195],{"className":137,"code":194,"language":133,"meta":139,"style":139},"cat \u002Fetc\u002Fpasswd\n# root:x:0:0:root:\u002Froot:\u002Fbin\u002Fbash\n# daemon:x:1:1:daemon:\u002Fusr\u002Fsbin:\u002Fusr\u002Fsbin\u002Fnologin\n# alice:x:1000:1000:Alice Smith,,,:\u002Fhome\u002Falice:\u002Fbin\u002Fbash\n",[27,196,197,206,211,216],{"__ignoreMap":139},[143,198,199,202],{"class":145,"line":146},[143,200,201],{"class":149},"cat",[143,203,205],{"class":204},"sJ6F3"," \u002Fetc\u002Fpasswd\n",[143,207,208],{"class":145,"line":157},[143,209,210],{"class":153},"# root:x:0:0:root:\u002Froot:\u002Fbin\u002Fbash\n",[143,212,213],{"class":145,"line":166},[143,214,215],{"class":153},"# daemon:x:1:1:daemon:\u002Fusr\u002Fsbin:\u002Fusr\u002Fsbin\u002Fnologin\n",[143,217,219],{"class":145,"line":218},4,[143,220,221],{"class":153},"# alice:x:1000:1000:Alice Smith,,,:\u002Fhome\u002Falice:\u002Fbin\u002Fbash\n",[109,223,224,246],{},[112,225,226,229,230,233,234,237,238,241,242,245],{},[18,227,228],{},"password"," — ",[27,231,232],{},"x"," means the hash is in ",[27,235,236],{},"\u002Fetc\u002Fshadow",". ",[27,239,240],{},"*"," or ",[27,243,244],{},"!"," means the account is locked.",[112,247,248,229,251,254,255,258],{},[18,249,250],{},"shell",[27,252,253],{},"\u002Fusr\u002Fsbin\u002Fnologin"," and ",[27,256,257],{},"\u002Fbin\u002Ffalse"," prevent interactive login (used for service accounts).",[32,260,262,264],{"id":261},"etcshadow-password-hashes",[27,263,236],{}," — Password Hashes",[14,266,267,268],{},"Only root can read this. Format: ",[27,269,270],{},"username:hash:lastchange:min:max:warn:inactive:expire:reserved",[131,272,273],{"language":133},[135,274,276],{"className":137,"code":275,"language":133,"meta":139,"style":139},"sudo cat \u002Fetc\u002Fshadow\n# root:$y$j9T$...:19500:0:99999:7:::       ← yescrypt hash\n# bob:!:19500:0:99999:7:::                 ← locked (no hash)\n",[27,277,278,288,293],{"__ignoreMap":139},[143,279,280,282,285],{"class":145,"line":146},[143,281,29],{"class":149},[143,283,284],{"class":204}," cat",[143,286,287],{"class":204}," \u002Fetc\u002Fshadow\n",[143,289,290],{"class":145,"line":157},[143,291,292],{"class":153},"# root:$y$j9T$...:19500:0:99999:7:::       ← yescrypt hash\n",[143,294,295],{"class":145,"line":166},[143,296,297],{"class":153},"# bob:!:19500:0:99999:7:::                 ← locked (no hash)\n",[109,299,300],{},[112,301,302,229,305,308,309,312,313,316,317,320,321,324,325,241,327,329],{},[18,303,304],{},"hash",[27,306,307],{},"$y$"," = yescrypt (modern), ",[27,310,311],{},"$6$"," = SHA-512, ",[27,314,315],{},"$5$"," = SHA-256, ",[27,318,319],{},"$1$"," = MD5 (obsolete), ",[27,322,323],{},"$2b$"," = bcrypt. ",[27,326,240],{},[27,328,244],{}," = locked.",[32,331,333],{"id":332},"managing-users","Managing Users",[131,335,336],{"language":133},[135,337,339],{"className":137,"code":338,"language":133,"meta":139,"style":139},"# Complex Implementation: create a service account with minimal privileges\nsudo useradd -r -s \u002Fusr\u002Fsbin\u002Fnologin -M -c \"App Service Account\" appuser\n# -r: system account (UID \u003C 1000)\n# -s \u002Fusr\u002Fsbin\u002Fnologin: no interactive login\n# -M: no home directory\n# -c: GECOS (description)\n\n# Create a regular user with home + groups:\nsudo useradd -m -s \u002Fbin\u002Fbash -G sudo,developers alice\n# -m: create home\n# -G: supplementary groups (comma-separated)\n",[27,340,341,346,374,379,384,390,396,403,409,433,439],{"__ignoreMap":139},[143,342,343],{"class":145,"line":146},[143,344,345],{"class":153},"# Complex Implementation: create a service account with minimal privileges\n",[143,347,348,350,353,356,359,362,365,368,371],{"class":145,"line":157},[143,349,29],{"class":149},[143,351,352],{"class":204}," useradd",[143,354,355],{"class":169}," -r",[143,357,358],{"class":169}," -s",[143,360,361],{"class":204}," \u002Fusr\u002Fsbin\u002Fnologin",[143,363,364],{"class":169}," -M",[143,366,367],{"class":169}," -c",[143,369,370],{"class":204}," \"App Service Account\"",[143,372,373],{"class":204}," appuser\n",[143,375,376],{"class":145,"line":166},[143,377,378],{"class":153},"# -r: system account (UID \u003C 1000)\n",[143,380,381],{"class":145,"line":218},[143,382,383],{"class":153},"# -s \u002Fusr\u002Fsbin\u002Fnologin: no interactive login\n",[143,385,387],{"class":145,"line":386},5,[143,388,389],{"class":153},"# -M: no home directory\n",[143,391,393],{"class":145,"line":392},6,[143,394,395],{"class":153},"# -c: GECOS (description)\n",[143,397,399],{"class":145,"line":398},7,[143,400,402],{"emptyLinePlaceholder":401},true,"\n",[143,404,406],{"class":145,"line":405},8,[143,407,408],{"class":153},"# Create a regular user with home + groups:\n",[143,410,412,414,416,419,421,424,427,430],{"class":145,"line":411},9,[143,413,29],{"class":149},[143,415,352],{"class":204},[143,417,418],{"class":169}," -m",[143,420,358],{"class":169},[143,422,423],{"class":204}," \u002Fbin\u002Fbash",[143,425,426],{"class":169}," -G",[143,428,429],{"class":204}," sudo,developers",[143,431,432],{"class":204}," alice\n",[143,434,436],{"class":145,"line":435},10,[143,437,438],{"class":153},"# -m: create home\n",[143,440,442],{"class":145,"line":441},11,[143,443,444],{"class":153},"# -G: supplementary groups (comma-separated)\n",[446,447,449,450,453,454],"h3",{"id":448},"caveat-anti-pattern-usermod-g-vs-ag","Caveat & Anti-Pattern: ",[27,451,452],{},"usermod -G"," vs ",[27,455,456],{},"-aG",[131,458,459],{"language":133},[135,460,462],{"className":137,"code":461,"language":133,"meta":139,"style":139},"# NAIVE: -G (without -a) REPLACES the supplementary group list\nsudo usermod -G docker alice\n# Alice is now ONLY in docker — removed from sudo, audio, etc.\n\n# PRODUCTION: -aG (append) adds the group while keeping existing ones\nsudo usermod -aG docker alice\n# Alice is now in docker AND sudo AND everything else she had\n\n# This is the #1 usermod footgun — always use -aG\n",[27,463,464,469,483,488,492,497,510,515,519],{"__ignoreMap":139},[143,465,466],{"class":145,"line":146},[143,467,468],{"class":153},"# NAIVE: -G (without -a) REPLACES the supplementary group list\n",[143,470,471,473,476,478,481],{"class":145,"line":157},[143,472,29],{"class":149},[143,474,475],{"class":204}," usermod",[143,477,426],{"class":169},[143,479,480],{"class":204}," docker",[143,482,432],{"class":204},[143,484,485],{"class":145,"line":166},[143,486,487],{"class":153},"# Alice is now ONLY in docker — removed from sudo, audio, etc.\n",[143,489,490],{"class":145,"line":218},[143,491,402],{"emptyLinePlaceholder":401},[143,493,494],{"class":145,"line":386},[143,495,496],{"class":153},"# PRODUCTION: -aG (append) adds the group while keeping existing ones\n",[143,498,499,501,503,506,508],{"class":145,"line":392},[143,500,29],{"class":149},[143,502,475],{"class":204},[143,504,505],{"class":169}," -aG",[143,507,480],{"class":204},[143,509,432],{"class":204},[143,511,512],{"class":145,"line":398},[143,513,514],{"class":153},"# Alice is now in docker AND sudo AND everything else she had\n",[143,516,517],{"class":145,"line":405},[143,518,402],{"emptyLinePlaceholder":401},[143,520,521],{"class":145,"line":411},[143,522,523],{"class":153},"# This is the #1 usermod footgun — always use -aG\n",[32,525,527,529],{"id":526},"sudo-delegate-privilege",[27,528,29],{}," — Delegate Privilege",[131,531,532],{"language":133},[135,533,535],{"className":137,"code":534,"language":133,"meta":139,"style":139},"sudo command            # run as root\nsudo -u alice command   # run as alice\nsudo -i                 # interactive root shell (login)\nsudo -s                 # interactive root shell (non-login)\nsudo -l                 # list what you're allowed to do\n",[27,536,537,547,562,572,581],{"__ignoreMap":139},[143,538,539,541,544],{"class":145,"line":146},[143,540,29],{"class":149},[143,542,543],{"class":204}," command",[143,545,546],{"class":153},"            # run as root\n",[143,548,549,551,554,557,559],{"class":145,"line":157},[143,550,29],{"class":149},[143,552,553],{"class":169}," -u",[143,555,556],{"class":204}," alice",[143,558,543],{"class":204},[143,560,561],{"class":153},"   # run as alice\n",[143,563,564,566,569],{"class":145,"line":166},[143,565,29],{"class":149},[143,567,568],{"class":169}," -i",[143,570,571],{"class":153},"                 # interactive root shell (login)\n",[143,573,574,576,578],{"class":145,"line":218},[143,575,29],{"class":149},[143,577,358],{"class":169},[143,579,580],{"class":153},"                 # interactive root shell (non-login)\n",[143,582,583,585,588],{"class":145,"line":386},[143,584,29],{"class":149},[143,586,587],{"class":169}," -l",[143,589,590],{"class":153},"                 # list what you're allowed to do\n",[446,592,594,597],{"id":593},"etcsudoers-the-rules",[27,595,596],{},"\u002Fetc\u002Fsudoers"," — The Rules",[14,599,600,606,607,610],{},[18,601,602,603,605],{},"Never edit ",[27,604,596],{}," directly"," — a syntax error can lock you out of root. Use ",[27,608,609],{},"visudo",":",[131,612,613],{"language":133},[135,614,616],{"className":137,"code":615,"language":133,"meta":139,"style":139},"sudo visudo\n# Better: use \u002Fetc\u002Fsudoers.d\u002F for custom rules\nsudo visudo -f \u002Fetc\u002Fsudoers.d\u002Falice\n# alice ALL=(root) NOPASSWD: \u002Fusr\u002Fbin\u002Fsystemctl restart nginx\nsudo chmod 440 \u002Fetc\u002Fsudoers.d\u002Falice   # sudoers files must be mode 440\n",[27,617,618,625,630,643,648],{"__ignoreMap":139},[143,619,620,622],{"class":145,"line":146},[143,621,29],{"class":149},[143,623,624],{"class":204}," visudo\n",[143,626,627],{"class":145,"line":157},[143,628,629],{"class":153},"# Better: use \u002Fetc\u002Fsudoers.d\u002F for custom rules\n",[143,631,632,634,637,640],{"class":145,"line":166},[143,633,29],{"class":149},[143,635,636],{"class":204}," visudo",[143,638,639],{"class":169}," -f",[143,641,642],{"class":204}," \u002Fetc\u002Fsudoers.d\u002Falice\n",[143,644,645],{"class":145,"line":218},[143,646,647],{"class":153},"# alice ALL=(root) NOPASSWD: \u002Fusr\u002Fbin\u002Fsystemctl restart nginx\n",[143,649,650,652,655,658,661],{"class":145,"line":386},[143,651,29],{"class":149},[143,653,654],{"class":204}," chmod",[143,656,657],{"class":169}," 440",[143,659,660],{"class":204}," \u002Fetc\u002Fsudoers.d\u002Falice",[143,662,663],{"class":153},"   # sudoers files must be mode 440\n",[446,665,449,667,670],{"id":666},"caveat-anti-pattern-sudo-echo-file-fails",[27,668,669],{},"sudo echo > \u002Ffile"," Fails",[131,672,673],{"language":133},[135,674,676],{"className":137,"code":675,"language":133,"meta":139,"style":139},"# NAIVE: the redirect runs as YOU, not root\nsudo echo \"x\" > \u002Fetc\u002Fprotected    # Permission denied (the > is yours, echo runs as root)\n\n# PRODUCTION: use tee (runs as root via sudo)\necho \"x\" | sudo tee \u002Fetc\u002Fprotected > \u002Fdev\u002Fnull\n# Or:\nsudo bash -c 'echo \"x\" > \u002Fetc\u002Fprotected'\n",[27,677,678,683,703,707,712,734,739],{"__ignoreMap":139},[143,679,680],{"class":145,"line":146},[143,681,682],{"class":153},"# NAIVE: the redirect runs as YOU, not root\n",[143,684,685,687,690,693,697,700],{"class":145,"line":157},[143,686,29],{"class":149},[143,688,689],{"class":204}," echo",[143,691,692],{"class":204}," \"x\"",[143,694,696],{"class":695},"svdQ7"," >",[143,698,699],{"class":204}," \u002Fetc\u002Fprotected",[143,701,702],{"class":153},"    # Permission denied (the > is yours, echo runs as root)\n",[143,704,705],{"class":145,"line":166},[143,706,402],{"emptyLinePlaceholder":401},[143,708,709],{"class":145,"line":218},[143,710,711],{"class":153},"# PRODUCTION: use tee (runs as root via sudo)\n",[143,713,714,716,718,721,724,727,729,731],{"class":145,"line":386},[143,715,170],{"class":169},[143,717,692],{"class":204},[143,719,720],{"class":695}," |",[143,722,723],{"class":149}," sudo",[143,725,726],{"class":204}," tee",[143,728,699],{"class":204},[143,730,696],{"class":695},[143,732,733],{"class":204}," \u002Fdev\u002Fnull\n",[143,735,736],{"class":145,"line":392},[143,737,738],{"class":153},"# Or:\n",[143,740,741,743,746,748],{"class":145,"line":398},[143,742,29],{"class":149},[143,744,745],{"class":204}," bash",[143,747,367],{"class":169},[143,749,750],{"class":204}," 'echo \"x\" > \u002Fetc\u002Fprotected'\n",[32,752,754],{"id":753},"ssh-authentication","SSH Authentication",[446,756,758],{"id":757},"ssh-keys","SSH Keys",[131,760,761],{"language":133},[135,762,764],{"className":137,"code":763,"language":133,"meta":139,"style":139},"# Complex Implementation: modern SSH key setup with Ed25519\nssh-keygen -t ed25519 -C \"alice@workstation\"\n# -t ed25519: modern, fast, secure (preferred over RSA)\n# Set a passphrase for the private key (recommended)\n\n# Copy the public key to a server:\nssh-copy-id alice@server\n\n# SSH requires strict permissions (silently refuses if wrong):\nchmod 700 ~\u002F.ssh\nchmod 600 ~\u002F.ssh\u002Fauthorized_keys\nchmod 600 ~\u002F.ssh\u002Fid_ed25519          # private key — must be 600\nchmod 644 ~\u002F.ssh\u002Fid_ed25519.pub      # public key — can be readable\n",[27,765,766,771,788,793,798,802,807,815,819,824,835,845,858],{"__ignoreMap":139},[143,767,768],{"class":145,"line":146},[143,769,770],{"class":153},"# Complex Implementation: modern SSH key setup with Ed25519\n",[143,772,773,776,779,782,785],{"class":145,"line":157},[143,774,775],{"class":149},"ssh-keygen",[143,777,778],{"class":169}," -t",[143,780,781],{"class":204}," ed25519",[143,783,784],{"class":169}," -C",[143,786,787],{"class":204}," \"alice@workstation\"\n",[143,789,790],{"class":145,"line":166},[143,791,792],{"class":153},"# -t ed25519: modern, fast, secure (preferred over RSA)\n",[143,794,795],{"class":145,"line":218},[143,796,797],{"class":153},"# Set a passphrase for the private key (recommended)\n",[143,799,800],{"class":145,"line":386},[143,801,402],{"emptyLinePlaceholder":401},[143,803,804],{"class":145,"line":392},[143,805,806],{"class":153},"# Copy the public key to a server:\n",[143,808,809,812],{"class":145,"line":398},[143,810,811],{"class":149},"ssh-copy-id",[143,813,814],{"class":204}," alice@server\n",[143,816,817],{"class":145,"line":405},[143,818,402],{"emptyLinePlaceholder":401},[143,820,821],{"class":145,"line":411},[143,822,823],{"class":153},"# SSH requires strict permissions (silently refuses if wrong):\n",[143,825,826,829,832],{"class":145,"line":435},[143,827,828],{"class":149},"chmod",[143,830,831],{"class":169}," 700",[143,833,834],{"class":204}," ~\u002F.ssh\n",[143,836,837,839,842],{"class":145,"line":441},[143,838,828],{"class":149},[143,840,841],{"class":169}," 600",[143,843,844],{"class":204}," ~\u002F.ssh\u002Fauthorized_keys\n",[143,846,848,850,852,855],{"class":145,"line":847},12,[143,849,828],{"class":149},[143,851,841],{"class":169},[143,853,854],{"class":204}," ~\u002F.ssh\u002Fid_ed25519",[143,856,857],{"class":153},"          # private key — must be 600\n",[143,859,861,863,866,869],{"class":145,"line":860},13,[143,862,828],{"class":149},[143,864,865],{"class":169}," 644",[143,867,868],{"class":204}," ~\u002F.ssh\u002Fid_ed25519.pub",[143,870,871],{"class":153},"      # public key — can be readable\n",[446,873,875,878],{"id":874},"sshd_config-hardening",[27,876,877],{},"sshd_config"," Hardening",[131,880,881],{"language":133},[135,882,884],{"className":137,"code":883,"language":133,"meta":139,"style":139},"PermitRootLogin no              # disable root login via SSH\nPasswordAuthentication no       # require key auth (after setting up keys!)\nPubkeyAuthentication yes\nAllowUsers alice bob            # whitelist (optional)\nMaxAuthTries 3                  # limit password guesses\nClientAliveInterval 300         # idle timeout (5 min)\n",[27,885,886,897,907,915,928,939],{"__ignoreMap":139},[143,887,888,891,894],{"class":145,"line":146},[143,889,890],{"class":149},"PermitRootLogin",[143,892,893],{"class":204}," no",[143,895,896],{"class":153},"              # disable root login via SSH\n",[143,898,899,902,904],{"class":145,"line":157},[143,900,901],{"class":149},"PasswordAuthentication",[143,903,893],{"class":204},[143,905,906],{"class":153},"       # require key auth (after setting up keys!)\n",[143,908,909,912],{"class":145,"line":166},[143,910,911],{"class":149},"PubkeyAuthentication",[143,913,914],{"class":204}," yes\n",[143,916,917,920,922,925],{"class":145,"line":218},[143,918,919],{"class":149},"AllowUsers",[143,921,556],{"class":204},[143,923,924],{"class":204}," bob",[143,926,927],{"class":153},"            # whitelist (optional)\n",[143,929,930,933,936],{"class":145,"line":386},[143,931,932],{"class":149},"MaxAuthTries",[143,934,935],{"class":169}," 3",[143,937,938],{"class":153},"                  # limit password guesses\n",[143,940,941,944,947],{"class":145,"line":392},[143,942,943],{"class":149},"ClientAliveInterval",[143,945,946],{"class":169}," 300",[143,948,949],{"class":153},"         # idle timeout (5 min)\n",[131,951,952],{"language":133},[135,953,955],{"className":137,"code":954,"language":133,"meta":139,"style":139},"sudo sshd -t                    # test config syntax (don't restart if errors!)\nsudo systemctl reload sshd      # reload without dropping connections\n",[27,956,957,969],{"__ignoreMap":139},[143,958,959,961,964,966],{"class":145,"line":146},[143,960,29],{"class":149},[143,962,963],{"class":204}," sshd",[143,965,778],{"class":169},[143,967,968],{"class":153},"                    # test config syntax (don't restart if errors!)\n",[143,970,971,973,976,979,981],{"class":145,"line":157},[143,972,29],{"class":149},[143,974,975],{"class":204}," systemctl",[143,977,978],{"class":204}," reload",[143,980,963],{"class":204},[143,982,983],{"class":153},"      # reload without dropping connections\n",[32,985,987],{"id":986},"pam-pluggable-authentication-modules","PAM — Pluggable Authentication Modules",[14,989,990,991,993,994,993,997,993,1000,1003,1004,610],{},"PAM is the authentication framework. Login, ",[27,992,29],{},", ",[27,995,996],{},"su",[27,998,999],{},"ssh",[27,1001,1002],{},"cron"," — all call PAM. Config in ",[27,1005,1006],{},"\u002Fetc\u002Fpam.d\u002F",[131,1008,1009],{"language":133},[135,1010,1012],{"className":137,"code":1011,"language":133,"meta":139,"style":139},"cat \u002Fetc\u002Fpam.d\u002Fcommon-auth    # the password-checking stack\n# auth [success=1 default=ignore] pam_unix.so nullok\n# auth requisite pam_deny.so\n# auth required pam_permit.so\n",[27,1013,1014,1024,1029,1034],{"__ignoreMap":139},[143,1015,1016,1018,1021],{"class":145,"line":146},[143,1017,201],{"class":149},[143,1019,1020],{"class":204}," \u002Fetc\u002Fpam.d\u002Fcommon-auth",[143,1022,1023],{"class":153},"    # the password-checking stack\n",[143,1025,1026],{"class":145,"line":157},[143,1027,1028],{"class":153},"# auth [success=1 default=ignore] pam_unix.so nullok\n",[143,1030,1031],{"class":145,"line":166},[143,1032,1033],{"class":153},"# auth requisite pam_deny.so\n",[143,1035,1036],{"class":145,"line":218},[143,1037,1038],{"class":153},"# auth required pam_permit.so\n",[14,1040,1041,1042],{},"Each line: ",[27,1043,1044],{},"type control module [args]",[109,1046,1047,1068],{},[112,1048,1049,1052,1053,1056,1057,1060,1061,1063,1064,1067],{},[18,1050,1051],{},"type",": ",[27,1054,1055],{},"auth"," (verify identity), ",[27,1058,1059],{},"account"," (is account valid?), ",[27,1062,228],{}," (change password), ",[27,1065,1066],{},"session"," (setup\u002Fteardown).",[112,1069,1070,1052,1073,1076,1077,1080,1081,1084],{},[18,1071,1072],{},"control",[27,1074,1075],{},"required"," (must pass, continue), ",[27,1078,1079],{},"requisite"," (must pass, stop on fail), ",[27,1082,1083],{},"sufficient"," (pass = success, stop).",[32,1086,1088],{"id":1087},"nss-name-service-switch","NSS — Name Service Switch",[14,1090,1091,1094],{},[27,1092,1093],{},"\u002Fetc\u002Fnsswitch.conf"," controls where user\u002Fgroup lookups happen — local files, LDAP, etc.:",[131,1096,1097],{"language":133},[135,1098,1100],{"className":137,"code":1099,"language":133,"meta":139,"style":139},"cat \u002Fetc\u002Fnsswitch.conf\n# passwd:  files systemd\n# group:   files systemd\n# hosts:   files dns\n# \"files\" → \u002Fetc\u002Fpasswd, \u002Fetc\u002Fgroup; \"dns\" → DNS for hostnames\n\ngetent passwd alice         # find alice (in files OR LDAP — works for any source)\ngetent group developers     # find group\n",[27,1101,1102,1109,1114,1119,1124,1129,1133,1146],{"__ignoreMap":139},[143,1103,1104,1106],{"class":145,"line":146},[143,1105,201],{"class":149},[143,1107,1108],{"class":204}," \u002Fetc\u002Fnsswitch.conf\n",[143,1110,1111],{"class":145,"line":157},[143,1112,1113],{"class":153},"# passwd:  files systemd\n",[143,1115,1116],{"class":145,"line":166},[143,1117,1118],{"class":153},"# group:   files systemd\n",[143,1120,1121],{"class":145,"line":218},[143,1122,1123],{"class":153},"# hosts:   files dns\n",[143,1125,1126],{"class":145,"line":386},[143,1127,1128],{"class":153},"# \"files\" → \u002Fetc\u002Fpasswd, \u002Fetc\u002Fgroup; \"dns\" → DNS for hostnames\n",[143,1130,1131],{"class":145,"line":392},[143,1132,402],{"emptyLinePlaceholder":401},[143,1134,1135,1138,1141,1143],{"class":145,"line":398},[143,1136,1137],{"class":149},"getent",[143,1139,1140],{"class":204}," passwd",[143,1142,556],{"class":204},[143,1144,1145],{"class":153},"         # find alice (in files OR LDAP — works for any source)\n",[143,1147,1148,1150,1153,1156],{"class":145,"line":405},[143,1149,1137],{"class":149},[143,1151,1152],{"class":204}," group",[143,1154,1155],{"class":204}," developers",[143,1157,1158],{"class":153},"     # find group\n",[32,1160,1162],{"id":1161},"tips-tricks","💡 Tips & Tricks",[109,1164,1165,1190,1208,1222,1242,1254],{},[112,1166,1167,1170,1171,1174,1175,1178,1179,1181,1182,1185,1186,1189],{},[18,1168,1169],{},"Idiom",": always use ",[27,1172,1173],{},"usermod -aG"," (not ",[27,1176,1177],{},"-G",") to add groups — ",[27,1180,1177],{}," alone ",[18,1183,1184],{},"replaces"," the supplementary group list, removing the user from all other groups. This is the #1 ",[27,1187,1188],{},"usermod"," footgun.",[112,1191,1192,1194,1195,1197,1198,1200,1201,1203,1204,1207],{},[18,1193,1169],{},": use ",[27,1196,609],{}," (never edit ",[27,1199,596],{}," directly) — ",[27,1202,609],{}," checks syntax before saving. A syntax error in ",[27,1205,1206],{},"sudoers"," can lock you out of root entirely.",[112,1209,1210,1194,1212,1174,1215,1218,1219,1221],{},[18,1211,1169],{},[27,1213,1214],{},"sudo -i",[27,1216,1217],{},"sudo su -",") for a root shell — ",[27,1220,1214],{}," is the idiomatic way; it's a single command, uses PAM properly, and logs the session.",[112,1223,1224,1194,1226,1174,1229,1232,1233,1237,1238,1241],{},[18,1225,1169],{},[27,1227,1228],{},"echo \"x\" | sudo tee \u002Fetc\u002Ffile",[27,1230,1231],{},"sudo echo \"x\" > \u002Fetc\u002Ffile",") — the redirect runs as ",[1234,1235,1236],"em",{},"you",", not root, so ",[27,1239,1240],{},"sudo echo > \u002Fetc\u002Ffile"," fails.",[112,1243,1244,1194,1246,1249,1250,1253],{},[18,1245,1169],{},[27,1247,1248],{},"ed25519"," SSH keys (not RSA) — Ed25519 is faster, shorter, and more secure. Only fall back to ",[27,1251,1252],{},"rsa -b 4096"," if the server is ancient.",[112,1255,1256,1194,1259,1262],{},[18,1257,1258],{},"Debug",[27,1260,1261],{},"sudo -l"," to see what a user can do — lists all sudoers rules matching the current user.",[32,1264,1266],{"id":1265},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[109,1268,1269,1290,1314,1333,1356,1372,1382,1400],{},[112,1270,1271,1052,1280,1283,1284,1287,1288,50],{},[18,1272,1273,1275,1276,1279],{},[27,1274,452],{}," (without ",[27,1277,1278],{},"-a",") replaces groups",[27,1281,1282],{},"sudo usermod -G docker alice"," removes alice from sudo, audio, etc. — she's now ",[1234,1285,1286],{},"only"," in docker. Always use ",[27,1289,456],{},[112,1291,1292,1052,1297,1300,1301,1303,1304,1307,1308,1310,1311,50],{},[18,1293,1294,1296],{},[27,1295,669],{}," fails",[27,1298,1299],{},"sudo echo \"x\" > \u002Fetc\u002Fprotected"," runs ",[27,1302,170],{}," as root but the ",[27,1305,1306],{},">"," redirect runs as ",[1234,1309,1236],{},". Use ",[27,1312,1313],{},"echo \"x\" | sudo tee \u002Fetc\u002Fprotected",[112,1315,1316,1052,1325,1328,1329,1332],{},[18,1317,1318,1320,1321,1324],{},[27,1319,996],{}," without ",[27,1322,1323],{},"-"," keeps your environment",[27,1326,1327],{},"su root"," (no dash) keeps your PATH, HOME — root commands may not be found. Always ",[27,1330,1331],{},"su - root"," for a login shell.",[112,1334,1335,1052,1338,1341,1342,993,1345,1348,1349,1352,1353,1355],{},[18,1336,1337],{},"SSH key permissions must be strict",[27,1339,1340],{},"~\u002F.ssh"," must be ",[27,1343,1344],{},"700",[27,1346,1347],{},"authorized_keys"," ",[27,1350,1351],{},"600",", private key ",[27,1354,1351],{},". SSH silently refuses keys that are group\u002Fworld-readable.",[112,1357,1358,1363,1364,1367,1368,1371],{},[18,1359,1360,1361],{},"Service accounts should have ",[27,1362,253],{},": setting a shell like ",[27,1365,1366],{},"\u002Fbin\u002Fbash"," on ",[27,1369,1370],{},"www-data"," allows interactive login (if someone gets the password).",[112,1373,1374,1381],{},[18,1375,1376,1377,1380],{},"Passwordless sudo (",[27,1378,1379],{},"NOPASSWD:",") is a security hole",": any compromise of that user = instant root. Limit it to specific commands.",[112,1383,1384,1387,1388,1391,1392,1395,1396,1399],{},[18,1385,1386],{},"Group membership changes need re-login",": if you add alice to ",[27,1389,1390],{},"docker",", her ",[1234,1393,1394],{},"existing"," shells still have the old groups. She must log out and back in (or ",[27,1397,1398],{},"newgrp docker",").",[112,1401,1402,1052,1405,1408,1409,50],{},[18,1403,1404],{},"Deleting a user doesn't kill their processes",[27,1406,1407],{},"userdel alice"," removes the account, but her running processes keep going. Kill them first: ",[27,1410,1411],{},"sudo pkill -u alice",[32,1413,1415],{"id":1414},"spot-the-bug","🧠 Spot the Bug",[14,1417,1418,1419,1421,1422,1320,1424,610],{},"An admin adds alice to the ",[27,1420,1390],{}," group so she can run ",[27,1423,1390],{},[27,1425,29],{},[131,1427,1428],{"language":133},[135,1429,1431],{"className":137,"code":1430,"language":133,"meta":139,"style":139},"sudo usermod -G docker alice\n",[27,1432,1433],{"__ignoreMap":139},[143,1434,1435,1437,1439,1441,1443],{"class":145,"line":146},[143,1436,29],{"class":149},[143,1438,475],{"class":204},[143,1440,426],{"class":169},[143,1442,480],{"class":204},[143,1444,432],{"class":204},[14,1446,1447,1448,1451,1452,1454],{},"Alice logs out, logs back in, and ",[27,1449,1450],{},"docker ps"," works — but she can no longer use ",[27,1453,29],{},". What happened?",[1456,1457,1458,1462,1490,1498,1517,1531],"details",{},[1459,1460,1461],"summary",{},"Answer",[14,1463,1464,1471,1472,1475,1476,1479,1480,1348,1482,229,1484,254,1486,1489],{},[18,1465,1466,1320,1468,1470],{},[27,1467,1177],{},[27,1469,1278],{}," replaces the supplementary group list."," Before, alice was in ",[27,1473,1474],{},"alice, sudo, developers",". After ",[27,1477,1478],{},"usermod -G docker alice",", she's in ",[1234,1481,1286],{},[27,1483,1390],{},[27,1485,29],{},[27,1487,1488],{},"developers"," are gone. She lost her sudo access.",[14,1491,1492],{},[18,1493,1494,1495,1497],{},"Fix — always use ",[27,1496,456],{}," (append):",[131,1499,1500],{"language":133},[135,1501,1503],{"className":137,"code":1502,"language":133,"meta":139,"style":139},"sudo usermod -aG docker alice\n",[27,1504,1505],{"__ignoreMap":139},[143,1506,1507,1509,1511,1513,1515],{"class":145,"line":146},[143,1508,29],{"class":149},[143,1510,475],{"class":204},[143,1512,505],{"class":169},[143,1514,480],{"class":204},[143,1516,432],{"class":204},[14,1518,1519,1520,1348,1522,1525,1526,993,1528,1530],{},"Now alice is in ",[27,1521,1390],{},[1234,1523,1524],{},"and"," all her existing groups (",[27,1527,29],{},[27,1529,1488],{},", etc.).",[14,1532,1533,1534,1536,1537,993,1539,1541,1542,1545],{},"The ",[27,1535,1278],{}," flag means \"append\" — it adds to the supplementary group list instead of replacing it. Without ",[27,1538,1278],{},[27,1540,1177],{}," sets the group list to ",[1234,1543,1544],{},"exactly"," what you specify, dropping everything else.",[1547,1548,1549],"style",{},"html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}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 .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}",{"title":139,"searchDepth":157,"depth":157,"links":1551},[1552,1553,1555,1557,1561,1568,1573,1574,1575,1576,1577],{"id":34,"depth":157,"text":35},{"id":180,"depth":157,"text":1554},"\u002Fetc\u002Fpasswd — User Database",{"id":261,"depth":157,"text":1556},"\u002Fetc\u002Fshadow — Password Hashes",{"id":332,"depth":157,"text":333,"children":1558},[1559],{"id":448,"depth":166,"text":1560},"Caveat & Anti-Pattern: usermod -G vs -aG",{"id":526,"depth":157,"text":1562,"children":1563},"sudo — Delegate Privilege",[1564,1566],{"id":593,"depth":166,"text":1565},"\u002Fetc\u002Fsudoers — The Rules",{"id":666,"depth":166,"text":1567},"Caveat & Anti-Pattern: sudo echo > \u002Ffile Fails",{"id":753,"depth":157,"text":754,"children":1569},[1570,1571],{"id":757,"depth":166,"text":758},{"id":874,"depth":166,"text":1572},"sshd_config Hardening",{"id":986,"depth":157,"text":987},{"id":1087,"depth":157,"text":1088},{"id":1161,"depth":157,"text":1162},{"id":1265,"depth":157,"text":1266},{"id":1414,"depth":157,"text":1415},"Linux is a multi-user system. Every process runs as a user, every file is owned by a user, and access is controlled by comparing the process's identity to the file's ownership. This chapter covers the UID\u002FGID model, the PAM authentication stack, sudo, SSH key authentication, and the gotchas that cause \"permission denied\" mysteries.","md",{},"\u002Flinux\u002F07-users-groups-auth",{"title":5,"description":1578},"linux\u002F07-users-groups-auth","KluCV-CIlUhjKecoUbDMeeAqVMGlg_8HZ4jhbJQY1GE",1789924649951]