From 4a11301214950f7cd877aecc3d794c747b49383d Mon Sep 17 00:00:00 2001 From: Derek Date: Thu, 27 Aug 2026 13:35:22 +1000 Subject: [PATCH] fix: remove five files nothing references Found by a hygiene sweep of the whole tree, not just a diff. Each was checked for references across the repo before removal, and the role-file-reference gate still resolves all 54 static references afterwards. roles/soe/files/default-background.svg roles/developer/files/branding/background.svg Byte-identical copies (md5 51893ea6) of the wallpaper that now lives in roles/soe-gui/files/, beside the task that copies it. Nothing could reach either: Ansible resolves a `src:` against the current role's files/ and the playbook directory, never a sibling role. ~494KB each. roles/developer/files/branding/avatar.svg No reference anywhere. avatar_file has defaulted to user-avatar.png since the branding feature's first commit, so this was never wired up. roles/developer/files/update/hyperi-update.png update_command.yml deploys only the .svg (Linux icon) and AppIcon.icns (macOS); the .desktop file's Icon= resolves via the installed .svg. tools/add-dev-user.sh Byte-identical (md5 dec58a0e) to roles/developer/files/add-dev-user, the copy Ansible actually installs to /usr/local/sbin. Referenced by nothing -- not tools/README.md, not any script or doc. --- .../roles/developer/files/branding/avatar.svg | 161 - .../developer/files/branding/background.svg | 5399 ----------------- .../developer/files/update/hyperi-update.png | Bin 14191 -> 0 bytes .../roles/soe/files/default-background.svg | 5399 ----------------- tools/add-dev-user.sh | 484 -- 5 files changed, 11443 deletions(-) delete mode 100644 ansible/roles/developer/files/branding/avatar.svg delete mode 100644 ansible/roles/developer/files/branding/background.svg delete mode 100644 ansible/roles/developer/files/update/hyperi-update.png delete mode 100644 ansible/roles/soe/files/default-background.svg delete mode 100755 tools/add-dev-user.sh diff --git a/ansible/roles/developer/files/branding/avatar.svg b/ansible/roles/developer/files/branding/avatar.svg deleted file mode 100644 index 708ef31..0000000 --- a/ansible/roles/developer/files/branding/avatar.svg +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - HYPERI - diff --git a/ansible/roles/developer/files/branding/background.svg b/ansible/roles/developer/files/branding/background.svg deleted file mode 100644 index 53ce9fb..0000000 --- a/ansible/roles/developer/files/branding/background.svg +++ /dev/null @@ -1,5399 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0110 1001 0011 0101 0010 1101 0110 0110 1001 0011 0101 0010 1101 - - - 1001 0110 1100 1001 0101 0011 0110 1001 0011 0101 0010 1101 0110 - - - - - - 01101001 00110101 00101101 01100110 10010011 01010010 11010110 - - - 11001001 01010011 01101001 00110101 00101101 01101001 00110101 - - - 10110010 01101100 10010101 00110110 10010011 01010010 11010110 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ansible/roles/developer/files/update/hyperi-update.png b/ansible/roles/developer/files/update/hyperi-update.png deleted file mode 100644 index 590c0e26482c52e7a7ac9fce7284a2e42850b3c5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14191 zcmd6OdmxnExA2-VgK-^FC^3>-iAmlNnTgUxMWs@S>7rCBQ6aa76cy3kn__fPZ`bK2 zLPk`QP`aqxl8j33xipw>J)?f-`+es-=lpw~KiJQH)?RzkbA(ZtD1E87R7_Mf|KD?=QPX z4_KUwU|+0EIVMyEwx6CA1Rv1On!{K? zw#WFuqHH!}ZacQ^X2HuW7K4Q0xtG8=f3;U<>s5g}@*wO9=y;hxwwGet|K%-{bUgsw z3rajwbE{GMeKH_?tU)P#L4R^hcd$^xB0ENTiT{b5aA~rl=BPW&0SfRq2VrI4jF+#^ zOP1km#7Qr)=0W)2um3Uz5kuEvn&9T_Jr=}3Oe8>ZTA;P~73^_ zzTQfYQm_Ard=Yt;ZyK%NdTR!NFnPWVdw~&Tx%44HJ8avg;7iFJH306U49Yi4id%9! zPWiK#vTIX>LO`JmK;`<;{LvP>CnpX?k)Nu2Ke$e$TxnM$97(e4t!&d(7PwLphYBKh zIwAO$yq-$QOlO^B22sF};EWlKvA0Y?wyB8@kZCwO{(10IqFR6xDmtjMM~#5JYC{wt zmNg!_WdgDdO}Oz^9-H!H&6#zuZ4LmB;h>(B!XO&S$#|xnv$rV_Mb%-5_f=z3t_IA_ z{t7^NH6A&m0gUYT*sg6n8m0lyvYuhvr16-i1{}!B#KCh~Etb%Q0%}K5l0bA1+7dy7|TOY%;G`hU2}5g)t#l{z2HW|DK*q~zXJq6?{>r3k8dET!oZB>#O#3#pmX zS&7`563~Hk`^`RlI+4mVGGB>osVQF4#1JNjuv8)wUTeBaRXt$b*m_HI=p=oyb% z3T942A8Q^CBwrUIJeF}9ZGo10N|fmF1gqyQ+1L-jFm^Ff$(QOAD4jN zvsq|>nR~-B$Nr(JDtb4h`=mg92Ia>RF?5)_{NG+IK0v5-SqiV15DTH_TpM4 z4t|%MGepj56H;5+inZN(dVk4&S8qF(GH-6Q2~|Gb#PM?3E97ZjgPT`&%^oCxG*q za_r#WJQC34CY7iE)M2r*=Tq3PJjkPZNBmK1)ldum*}b)j_(}-&|Be3u%B*LSTp99> z+o6Q7Ye(w`sVtIy(fqB9Ulj?pCv5DBvj`n3m8^orl0Kx3r~MTbA2Iz@*<-=eyD6@z z{!FsDvCBHYU3Kw>O(V#!Zp0sX;|rIvNfFW{s2u#*Yav!!r7QGX_-_k6PUpTYUxmQz z{qfmWKEoihhe33DyoB3uHWKmTxz?2S2X%wnzdCHhufpKlUn;{!z&{bW_>t-K0Jj3t z7&@$6+~M&TCV*G3UG_sBz7n^5O8)sr`k80_Z&1S=hhYXLWk7NFi-U;k^%29H8Kxvw zqDK0U{~Lra?W3xMTJYAHK3q&rwbt_YgeExQW1W1mlQ?bJ_;$P=#b#Km=1h7_I#Os@ z{%k;eA-5?${}0ptjk*{M5~U=fI#ih)y|8;=^h0tC^jsqU{=pzz(?-8G^4ACwU(#MF zGfaMS;osKB|Gx)u2fSr$#&&y=eHS+Vo8bP9hW{T1a{1Rk59`*zd=dkf@;?sxuUA_y z=%v23`^~CyDW}lz;`3*L+<`W*X_ao!;@{tykw~&lWl-dowjlBL$nx!jiQ6PwK`LJP za~t_}Z!@+5=Bx zdo#9`T$(qIF}|tk17Ltd*c$0+qmEM`ehvk=o2i_@u0<4ZR?8n=(z*WDn+k*7UBaEh z?Gt36*dT(!mWpLYSnu-4bG_>Il&hBCLL<5&cY875+9_lV-!eT-X`$Dp5`c4vpLw{# zbpzQ}@PxH3JyJ7~`j9UV^eb76S0zXle z52_7BZCXqN_wG4ubP(u#(zAK-5Zq!JsB1dyQHPRc;c@{Dg!M6zyd^z~#4RLU>-b)K zfnp`VXWZ#*)+fEHQ{gn8y%C_FCRDk*el+mR$QS(qnZR555U)Q(6YfClMZ3jgRhonY ztqWwrYOR2~41v@~3`Jdh9|WBTImlrr9br`Jve2YWKzQOd8gDQlv#2T&0?;OpZxATY zT<1+KE}V^{{DrdPx{d&$gHSZ%0htw5H(@QBY+4grdHuRNYTR>#q6QGMmLycNx(47m z1A@yR+xl+Rx`1y(k6lFAgYJG#Yn~FccB%ov#RXdR{6*NPBg*)4iniAK&52W#q2d&> zqAVtouOJ@F^;Q7lu+ILd%`KrYh}@gDLtggEZ3(4YO=1U!LoI-x_pxnfAANJq;9kNt`0`=DE9lQO8r(?*PRn`-pT92jg49fYMin<-P* z<F)D~EoG6TFIS)Tj7e@#B(tQgf6e>{@T zwd%VYnF&nOcCNaQU6!A6v_KGEUxp$uJsh-k(js{uDRH&y$E4gS*5_ootcDPQqHUwcm8Wa)J zJ=y6eFW_xjU7qunc|hDjHk7fFDx%@G_C*LpO6<{5^FLT$a3dyR_dA0VvO{2OlmIQ2_F|zp_*hdP2Swdrf9=7Vu1+-5QHkT zQC%Zov8=zEA-J7IYul=>^yHip5OStKyo#a542?ccxrQ`PIOGjFy;yWRkVOr4A_wV{7Xf2Jjhl-N`{B&9m7FhAwBXGLGsv%I7u zBIP6$81Y!%uASXW2N#B9tkfXH?0%jzd6Q0F_wDIp%XW0Xdfszq{I-1Y>Zx81chR0N z?%3wy>8Mcpba3P;k$TbrL{q3g(P&+XK&f}7XR0fA6dnM(jpBu!)j`lQj{+C!Yfc2m zFq@waY9@*_k_t$lXBVC$-0k;kKf8^5@p5B~YV(igDc-j@vVq@gIDV1y>)(dvE`05S zoVaddHAAO$c2)KD-T}d@_)ZPr`s%*EB|nClD7G9`e%)hPdfj(w5Yku`mqgi-&G|G# zb6-TS;)%x+72um~4Odc`msI%8>t0ZgXi8IfR?nL0BY-Clk1A~ zrlKE3Okt=covLFBn?36UV-U(l_uC*tl9VRS;*{U%=?TAI7d~Sb9tFWfp;~<5crfr+ zcCs@9!p*)>tUk2HzV-V<`**uVcLpm`82}lZ)YWY|*=ZMytJ#8QN z4|NsDBe$*bOJJ4U!aEjb+wY3f>QzJfF{Jn*uY)H`4lLAM!z?^VWC zF+pN|Yvi7$iYmD8{+<^SVL)u08ed4B&9`;fQ9~`7XBulFv=Y&CIa62^pwkq!^}Y4U z5gj2}3WI9zG8NxVu}6Q4Z4#@?Ti%nn$5~-e*dHbb0+U!p$hs*Cq68Z`O(&1-#u_`G zch8X>A@}vZp*MACN0rBZC%cM+gX^_j?Db}g{Uk=7`R#19q+Ffd#M_pM*-I4%g^x*G z^0BI5@c`g z++VsauXpRJHj&q{J0a$e-Xkk3Ndd;}?*7U-+j2svj$oH6ulEkRwfQJ*yE9n*U2s@5 z?u;S2WoTjsg%5Fd_Qco|AvGbrdOX{nvms}HR_FeFsMl#vKaGM;I__jsaVU{mT3#L$ zl$z*|oE7@%cwvl`nkK|l5HLc5WSU<%(2|gUEbZ8BECsO|*IWU3qn>C|h>NBdN#B>4 zspCiZwzxou2@p-WVpV_++#*NY&BriL3^G`9bl_4|-f?&KnC=NwezZpc_@-pw$~=Zh zZQ6W6>ZaJWY4IhO#i6J57l38o>67Q6jNbZK&X}><~{5}|Yv)9r@IAsL6{i;%A zbTRRPUVhK+OCgs=a$I>DJyQq|^)MO~*Ei~y&qQ2BC@WtQOHQxm$Brp7&g;C_Exch- zb(jIXWkwj7vt*HBYv;>)mX_1CP7ErO?_5pt3vUH()zNY}HC2R+G0rn!}xs61gky148+hbm+j-sdcd|_?1U6 zl4eI!>-oJ@BKok`z^}ag{GUiC9LTQw`&+B(}H@s^by!S#P$Fd96<}SqTG@7jq?(0UQ3Z?Qe_9C7v)N|80 z97VEVmsp3Z{+mNpHDa|u#sj?;Ahu!H@*Ft|6=&6f7eQinWGf3d-H`KjAt^C&)Dzm1 zDjBnGGi4W(Dl20t!@qyu_MNNcAfETrKCeIh{_fSYL&}EO6Gs5E*gRH6ZY225zEzu;Hoer9 z0y0?$F#&zLBhM|uoV4isH6#X7)5aZrRlUAbv92YD30lH0nh$Mj1}ap0yqxvR2H9xm z*{oPZ^cf-CugMg;0hf8*N&G@}kUtJpY7wpUdHJZ5=|B{as~J0EWHEZXbd1%A-ScH& zg(>ivv&iUO9&RrJF1W-7kjpwxt4d7MGeaiL`ujJiwh8cUhQGl$jGvITe0^k&y8<+u zEpA^%!+gL&;^#mZZ-oNX>(4{2n_WylXYq3sAwM1RG6l1Xg?9Tcy_`p?mmve%nN8Q(Z}c7Q7zfAq;T5Ey{mkE9`U?f zvO;tMxDi)HUtg%^U+kLKR3EQ89gW86FtlR2%ty=c7Evyre2Br2rM2e^Ak#$Kw;73Dt*(LIMptCFZ`$@Xpj z9u&y-?ZWh%{Evw#faRHWg(SNLWx5yK7LUi6`mFm zha2tqB^nS@!>pkQEdyR=VKQbO#LcC^6g8v3&IjoDATNccsNWbAVOXhyq66o1Xab$k zsT871#+HfNVNZT9#+~6ezxFjik_PM)oi5u(sMm= z7Y4>aC_c7;43cRcTb2%Z4pm87b5SR3QZVGV+Sz5W{q(ko#szt&a28cGw542}n`@;2 zzH^#CkH^KqOr$9JZyZ7(MWBef1l;X-YS1y5gJ#2lo0M)Bc-FAr?dd2IQ{~8fOD29r z|Dn0@$?Vz-Ht2IrM))$+6KT?lNo>Ma6Ea19rW!63IaxsnowwY;rLDvbPxB#{ck+>B zwD2n$IQWGddbz{5cd}Fv*o^>~TOItw3fLKA%5%TgdPAx45DjP|!K0(g-lc59%TeRB zt3A_*Ofp$>A(%P=54(z!3?MF`1PrRIs#BDp3T-gURF22T%U0pG-*K$yK}V@-w-@!X zXMeNznLh8H*@WD4B0sA>jmAQsj&Pd9KKFLkuV;~I;UntT;DY!%UX?gk?I-MCVH)F&4UhU}*4cA8 zIBB(5kv9`h!ck2;1~cs$kS{zrs!qzvAm5#nC~wwR_s*Av^QhQtgVMZ){|+`5|J9=X;*I`ae-G8+rZ ztU@ly5nZM-#AOueDi6BkZS1tznY^7#du@GyiGdz3;aFRbosc4!=mQlgq;dx4eT>wV zbL6@A+>gb9x($+1AYbIPC(JniS>1PKq54A3_ONm#wkArbva_ux?NV=~9{(@#ho1Rz z5I7lWx8+lrmCr=SaDm?Fpaq=M;~!TOnzU@(+8;s{&tp@_{0^Huvx9rYp%zij0XqDa zaIkMKxl?!AUXKVT-K^ar!STdLjN&o}Stk0$TBl|3q$YDC`;Yvr8R{~zAg;A||48VG zm-*!eLRp>l0qxT;i`U-}$&g0zYO6z9@gvIZZ96JJh3tNyG-MvHQT*Ti=g5l z16YP~s5w=KF)w@bmz`dT3QJKulIw>Ct#C~S=OzV~F109#%0ws5L}l8>CDHKm{UvBX zwN1C-rk0n>#+3}wlJ-)e`ANAW2!CcI-PUPp4-m&tcf-C$_pdrWBByG?uW5#Y-qiGj~p>t1DI9K1(A)M zRqhxWZ|d3iC1i+_hpt)j(&n21HkUg^@kML&JZ|Zkl?SRen+^p@^KK)n`+_Ah6(=r@ zmG>x1NX&crm)zr7!96D${Sdv9$8<}tKc7)=o%?1k_4q5ZYbO-g>sv+vu9Ks<>|5SOIb z?eq%yWq0Wjr|4X8)U@h0xQEB9?9~d3zU@!Tuj-}46OlvP(=O#WM+zu22G<+u2(zl| zVE!>G^fc8BWe(_wF|RS4>mcT6!12uT^f}EN-5*io3kQ{ia}}T}I!Ju#ljvhw1@vbp zio5J(&Mm@Chc_AOx-5%c3)qOSwz(hcPNjt^Ino+GKTIeHRElfHHN4Fpczr)H^k&rL zvq9WW;o-+KrmFPH7H!CnFN|Q^s|jmOSQFTT=Ngx$`&v+&keFYPN1cIc;P+@Yn7oLK z4D(9!h*64r8m@gvG>W-mfB{&#W3)WAli0tyy033cHHTT0Ac~RrpIIFx#0~w4k`xK%(Rf-JT;PVbPK1?sc76@MZ#Z>bNyYw9Q-^W` zRtg@v9-_|J{LlCQp>BN8QT-i_+Fv*9f1biv!1R4x!<~GJD7$}P%%i3j(qS}iaaAGi zZL{zF_4SIArQeqa?P<|dCL|rfgL)I=q^)OU>rbk(pD^!etVlHp4f&iG`ev#HvSp&7 z;=({V(%lxWjnN5C7E=klbRoKP#~eE}d1F>#UQ*(4vQaDAX@x_y>WS>3u8uPlXXem- zm>`5z4p(iUtQ6WE6Xkj0XbI49M`3O@Un1M>M4;TTLJwrjo7=nH#m|# zlmq(NnSouN6w+DQ|5laq}#*#TU@8szWnTR$7S!*BoAv{c#FzXxXOrhG40VxTu*qk&Z-?RUVqL8clC#@ zxt;0x_N{rcJbRVCUA8TOrw94wVhTHUj76@4Uztjd;KW4N2|$E+Mi!*!-@d9B(0;Q_ z*DYl_=I9b!izWeDNR#KEZf1VB2ulNx?_HQ0S#g#u)m}@@9TqY!arPAE?lluJ4ls?D zNnx@YcC_7Q^qLDa=t44JIZ9(>8oHa6hnHklUlJbGfKWV3Tt=8zok*Ij*K3#);7xT| z0xjsobhG>_qU&$j^|B^q$&tYh37IF)DxJX!Ne)f0&3Z?84R=mw7@4IncH7~4D`sA= z1|GFMRdjx>qxPj*%4+v2P4~&&NMIFI4KoVneek0%kq<69G4=%oD*|jy$thI zyXs7}YzV%9P8@o4{pjCKZLBdQl3U6l1)gs)Dml#*kMPOUc9lyy{4yF;}n0 zo2Wr&pr@XxATSe~3tQDO1IP8dT6h`LcFBqLssaxBCJ8oYsHKHN3Kjb?c+-z{|Bsug zK#zZ2S@C35u7mhiBK0m}Pd^Hv{-)>&#q?y(T`JYXksf0w8e(PT+%c4 zzf8|c4p%3$6vRHfKRfecNL~<6?rbtnhY#7m3hZL5zo!k^y)jzpwP=j0o1Y<0T@mRp%t7^G+J2=qMg={M0w;@2w!|NWCia z7&^s5opVusEvsM$$|gE6S@yQTn^M$dfXTz#QZ4sNXq8IJ%=s_MAYE z(%3*k_0NHdV+gfmfLc#3vf;t6sO1^oEhbQiFP?)$yK2(X0nE26URU{y0rf)6cSSsu z!5plLNa)#OA$1YhObqT_qB%kjRD7l4^s)bOb&G*O)xLUFwmGtCZ(y?ARG)m%NbF3o3tV>b2#n^X6U+ zt!J>sv_@!wvnWFD@}vR`qXO|}b=`;oO0p3hz}SS!GsE&kW8_P4+&Bop4>m5p z7y0eMuc4e-!b=*Iq=Ij$bmC5t1&R)DyKiCLqaU88!Y3LO=An93;nacAT*x%q$&GAv zf=nOe#Mv`SdPY>9Hr9rUQJnDa>-sFftsK$Cy!QJ*@O<*5-+O|J!%RxA}Vzs!;2FxZ& ziwkr)9p;xUiAB>}Ya)P(6EpY!1I~z&boL4V`Shf}(bBpz6d)~0=5k9%uXlcL?>mQG z_dd_74>P{GWTPgWJ2-sp0E_I09@^=D|8Qv}rAY9=h{D?2hh&`zu-s`X<8d0%EK|U{ zBfGIrG^lrt+GWV21Dqz0u|yS3&ZyhwjfXv%@_kT2zD8F~9p7uFMB4+!7^%Zt#wQR?#Z>Q8yoSf8e>xeL zVLUp3Q~pQIPaNLMNmJSw_U^$T4aEewAZgtp{{2(_LXakotgOT5zbmxyuL`AX8H+cu z_%vcJ9H0Mr5T67iq!mrl^as9l<7WBqXX29p1hoOf=+AfzV*9@-10qm;ewKULHs{GA zq=)gI2xV__JcyT&fB(A`@kxMT;-;iWo*0L3F~1i!XAyWxT71w@VBZP-`$qlpLaPP8 z`5kf*<2ihK$h_)*!N*Ms#P@tP$?^#Z;pTcW_jCpc3%k)&{#Qf(Q6S9fuE`_K%6|uJ zz9Qvt73SdaQ6O`K*Z(ko-EiNWE+4w_>TuDdKoVr}Q|+PnB@ENl`I~yL9doX|Y_A_gnkZ(xOP18iXPj&smX;5L~%o4I*CCh4(I`^ocb2KlIS31t~Yp!!)nR08|W-fak?TV6* zmK1@3Cd!Jd*IBjgUxQRv8si|cX1Z(dmii9wh&R3DT1#6#Z08siwieL1GUkp55%O&H zzibNOd>76B@A_=3#&gIvUzf7YvndtHheqIjQtrPp>5r{Vjyj2I&*KCv4OJli&cfU- z>^5+H;Y48@XrdD>+}(H?U9t^L4LG1Ge!$9ttSv7>>||}ZNG_NEH1g}4;dR6{ebC$| z!CZt#(jiPW*3Srd74WZhtoeZ02)oAfKBh3u|A-9!y5rfb=SyH`!&(&dm7}qkSK8Tl zj%**#?;h1wMG<51#oP5q-6NJjj;+5QGFF`Sq;#`{pSn&r$98IDVMq{a2qcE8XXO6~FS=!cUEtvbljvk`2^sTiqO`YO- zG?B_OwMN-h9I`)pjLMp9Jr;csE8FoFbZ)>l2jnmLvjwl*sJ_3Vkf%B{$>e0vic3M- zd>52y#Zr0fZ3|H_Bm38yd6hzwe#7qnM8;ef6 z$l3TC3(foF{SWw$D#(|$2$<|T5RFJ7tL;SH$f2w4W8raDHYQm|_VY(s>|R4Im~T{& zZ!`k-Wq-vBAYEI&xrKeD6<#o4jXGl}8Gq1Yl!8$4r6FmXEGa^5^aw$yMT=aBFHU}l zJ1H%2`lW1E7FOr%`(KJ(Ms zH5(7&kY=a$jhg18dosu&KJr5?g+b`9rJzMAEzeE~&nA4o9Z0jry$6%>It>fbrh3jP zb;NxKVzq%yFX)f2rS|npuuKw&Nx7XD^CwAvY;(vBg-5z?O-mL<=ai&Et7cI1#h1X@6D@u|@q{DIJ1 zC$it&k%K=Rnk$9b?#Lm3P~?jJ!o@KWmVq6X_x{wpNBc?zSm}xdJIxzsns1)x zhAb5vt|)KztUumeRBnm{UJ3p3oXWYERljC2&hE}?UvhQ~l<{%t#jf?Sa@qPkC#?1% zvSPwL$`?>W7bEFrvnyh2vO{>zCHUb7qo1v6J&M*|R6fYTi!*la@`nTW8%b08zx8qM alu)+P6LuagjjAJQoI7jb%o~op=>G#NZWGr4 diff --git a/ansible/roles/soe/files/default-background.svg b/ansible/roles/soe/files/default-background.svg deleted file mode 100644 index 53ce9fb..0000000 --- a/ansible/roles/soe/files/default-background.svg +++ /dev/null @@ -1,5399 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 0110 1001 0011 0101 0010 1101 0110 0110 1001 0011 0101 0010 1101 - - - 1001 0110 1100 1001 0101 0011 0110 1001 0011 0101 0010 1101 0110 - - - - - - 01101001 00110101 00101101 01100110 10010011 01010010 11010110 - - - 11001001 01010011 01101001 00110101 00101101 01101001 00110101 - - - 10110010 01101100 10010101 00110110 10010011 01010010 11010110 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/add-dev-user.sh b/tools/add-dev-user.sh deleted file mode 100755 index 182f02a..0000000 --- a/tools/add-dev-user.sh +++ /dev/null @@ -1,484 +0,0 @@ -#!/bin/bash -# ============================================================================ -# add-dev-user.sh - Add new developer user to Hyperi Developer SOE -# ============================================================================ -# Creates a new developer user with full access to the environment: -# - Sudo access (passwordless) -# - GNOME desktop access -# - RDP access via gnome-remote-desktop -# - Docker group membership -# - Proper home directory setup -# -# USAGE: -# sudo add-dev-user [password] -# -# If password is not provided, it will be set to the username (insecure default). -# -# EXAMPLES: -# sudo add-dev-user john # Creates user 'john' with password 'john' -# sudo add-dev-user john secretpass # Creates user 'john' with password 'secretpass' -# -# SUPPORTED PLATFORMS: -# - Ubuntu 24.04+ -# - Fedora 42+ -# -# LICENSE: -# Licensed under the Apache License, Version 2.0 -# ============================================================================ - -set -euo pipefail - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -print_info() { echo -e "${GREEN}[INFO]${NC} $1"; } -print_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } -print_error() { echo -e "${RED}[ERROR]${NC} $1"; } - -# Check root -if [[ $EUID -ne 0 ]]; then - print_error "This script must be run as root (use sudo)" - exit 1 -fi - -# Help function -show_help() { - echo "Usage: add-dev-user [OPTIONS] [password]" - echo "" - echo "Creates a new developer user with full Hyperi environment access:" - echo " - Passwordless sudo" - echo " - Docker group membership" - echo " - RDP access (if gnome-remote-desktop installed)" - echo " - npm global packages directory (~/.npm-global)" - echo " - Git, AWS, Azure CLI pre-configured directories" - echo " - Properly configured home directory" - echo "" - echo "Options:" - echo " --copy-ssh-keys Copy SSH authorized_keys from current (sudo) user" - echo " --ssh-keys-from Copy SSH keys from specified source:" - echo " - Local file: /path/to/authorized_keys" - echo " - Local user: @username (from /home/username/.ssh/)" - echo " - Stdin: - (read keys from stdin, great for piping)" - echo " - Remote SCP: user@host:/path (requires SSH access)" - echo " -h, --help Show this help message" - echo "" - echo "Arguments:" - echo " username Username for the new developer (required)" - echo " password Password (optional, defaults to username)" - echo "" - echo "Examples:" - echo " sudo add-dev-user john" - echo " sudo add-dev-user john secretpass" - echo " sudo add-dev-user --no-ssh-keys john # Don't copy SSH keys" - echo " sudo add-dev-user --ssh-keys-from /tmp/keys john" - echo " sudo add-dev-user --ssh-keys-from @otheruser john" - echo " cat ~/.ssh/id_rsa.pub | ssh root@srv 'add-dev-user --ssh-keys-from - john'" - exit 0 -} - -# Parse options -# Default: do NOT copy SSH keys (user must explicitly request it) -COPY_SSH_KEYS=false -SSH_KEYS_SOURCE="" -while [[ $# -gt 0 ]]; do - case "$1" in - -h|--help) - show_help - ;; - --copy-ssh-keys) - COPY_SSH_KEYS=true - shift - ;; - --ssh-keys-from) - if [[ -z "${2:-}" ]]; then - print_error "--ssh-keys-from requires a path argument" - exit 1 - fi - SSH_KEYS_SOURCE="$2" - COPY_SSH_KEYS=false # Using explicit source, not default copy - shift 2 - ;; - -*) - print_error "Unknown option: $1" - echo "Run 'add-dev-user --help' for usage information." - exit 1 - ;; - *) - break - ;; - esac -done - -# Check arguments -if [[ $# -lt 1 ]]; then - echo "Usage: add-dev-user [password]" - echo "" - echo "Creates a new user with full Hyperi developer environment access." - echo "If password is not provided, it defaults to the username." - echo "" - echo "Run 'add-dev-user --help' for more information." - exit 1 -fi - -USERNAME="$1" -PASSWORD="${2:-$USERNAME}" - -# Validate username -if [[ ! "$USERNAME" =~ ^[a-z_][a-z0-9_-]*$ ]]; then - print_error "Invalid username. Must start with lowercase letter or underscore," - print_error "and contain only lowercase letters, digits, underscores, or hyphens." - exit 1 -fi - -# Check if user already exists -if id "$USERNAME" &>/dev/null; then - print_error "User '$USERNAME' already exists" - exit 1 -fi - -# Detect distribution -if [[ -f /etc/os-release ]]; then - . /etc/os-release - DISTRO="$ID" -else - print_error "Cannot detect distribution" - exit 1 -fi - -print_info "Creating user '$USERNAME' on $DISTRO..." - -# ============================================================================ -# CREATE USER -# ============================================================================ - -case "$DISTRO" in - ubuntu|debian) - # Create user with home directory and bash shell - useradd -m -s /bin/bash -G sudo "$USERNAME" - - # Add to additional groups if they exist - for group in docker adm plugdev lpadmin; do - if getent group "$group" &>/dev/null; then - usermod -aG "$group" "$USERNAME" - print_info "Added to group: $group" - fi - done - ;; - fedora|rhel|centos) - # Create user with home directory and bash shell - useradd -m -s /bin/bash -G wheel "$USERNAME" - - # Add to docker group if it exists - if getent group docker &>/dev/null; then - usermod -aG docker "$USERNAME" - print_info "Added to group: docker" - fi - ;; - *) - print_error "Unsupported distribution: $DISTRO" - exit 1 - ;; -esac - -# Set password -echo "$USERNAME:$PASSWORD" | chpasswd -print_info "Password set" - -# ============================================================================ -# CONFIGURE PASSWORDLESS SUDO -# ============================================================================ - -SUDOERS_FILE="/etc/sudoers.d/90-$USERNAME-nopasswd" -echo "$USERNAME ALL=(ALL) NOPASSWD: ALL" > "$SUDOERS_FILE" -chmod 440 "$SUDOERS_FILE" -print_info "Passwordless sudo configured" - -# ============================================================================ -# CONFIGURE RDP ACCESS -# ============================================================================ - -# Check if gnome-remote-desktop is installed -if command -v grdctl &>/dev/null; then - print_info "Configuring RDP access..." - - # Set RDP credentials for the new user - if grdctl --system rdp set-credentials "$USERNAME" "$PASSWORD" 2>&1 | grep -q "fallback\|success" || true; then - print_info "RDP credentials set for $USERNAME" - else - # Try anyway, some versions don't output anything on success - grdctl --system rdp set-credentials "$USERNAME" "$PASSWORD" 2>/dev/null || true - print_info "RDP credentials configured (may need service restart)" - fi - - # Restart RDP service to pick up new credentials - systemctl restart gnome-remote-desktop.service 2>/dev/null || true -else - print_warn "grdctl not found - RDP not configured (install gnome-remote-desktop)" -fi - -# ============================================================================ -# COPY SKELETON CONFIG FILES -# ============================================================================ - -USER_HOME="/home/$USERNAME" - -# Copy bashrc/profile if not exists -if [[ ! -f "$USER_HOME/.bashrc" ]] && [[ -f /etc/skel/.bashrc ]]; then - cp /etc/skel/.bashrc "$USER_HOME/" - chown "$USERNAME:$USERNAME" "$USER_HOME/.bashrc" -fi - -# Create .config directory -mkdir -p "$USER_HOME/.config" -chown "$USERNAME:$USERNAME" "$USER_HOME/.config" - -# Create dconf directory (prevents snap Firefox symlink issues) -mkdir -p "$USER_HOME/.config/dconf" -chown "$USERNAME:$USERNAME" "$USER_HOME/.config/dconf" - -# ============================================================================ -# CONFIGURE DEVELOPER TOOLS -# ============================================================================ - -# Create standard directories -mkdir -p "$USER_HOME/.local/bin" -mkdir -p "$USER_HOME/.npm-global" -mkdir -p "$USER_HOME/.aws" -mkdir -p "$USER_HOME/.azure" -mkdir -p "$USER_HOME/.kube" -mkdir -p "$USER_HOME/.docker" -chown -R "$USERNAME:$USERNAME" "$USER_HOME/.local" -chown -R "$USERNAME:$USERNAME" "$USER_HOME/.npm-global" -chown -R "$USERNAME:$USERNAME" "$USER_HOME/.aws" -chown -R "$USERNAME:$USERNAME" "$USER_HOME/.azure" -chown -R "$USERNAME:$USERNAME" "$USER_HOME/.kube" -chown -R "$USERNAME:$USERNAME" "$USER_HOME/.docker" -print_info "Developer directories created" - -# Configure npm to use user-local global directory (avoids sudo for npm -g) -NPMRC="$USER_HOME/.npmrc" -if [[ ! -f "$NPMRC" ]]; then - echo "prefix=\${HOME}/.npm-global" > "$NPMRC" - chown "$USERNAME:$USERNAME" "$NPMRC" - print_info "npm configured for user-local global packages" -fi - -# Configure Git with placeholder (user must set their own name/email) -GITCONFIG="$USER_HOME/.gitconfig" -if [[ ! -f "$GITCONFIG" ]]; then - cat > "$GITCONFIG" << EOF -[user] - # TODO: Set your name and email - # name = Your Name - # email = your.email@example.com -[init] - defaultBranch = main -[pull] - rebase = false -[core] - autocrlf = input - editor = vim -[alias] - st = status - co = checkout - br = branch - ci = commit - lg = log --oneline --graph --decorate -EOF - chown "$USERNAME:$USERNAME" "$GITCONFIG" - print_info "Git configured (user must set name/email)" -fi - -# ============================================================================ -# CONFIGURE SHELL ENVIRONMENT -# ============================================================================ - -# Add common paths to .bashrc if not already present -BASHRC="$USER_HOME/.bashrc" -if ! grep -q "# Hyperi Developer paths" "$BASHRC" 2>/dev/null; then - cat >> "$BASHRC" << 'EOF' - -# Hyperi Developer paths -export PATH="$HOME/.local/bin:$HOME/.npm-global/bin:$HOME/bin:$PATH" - -# npm global packages (user-local, no sudo needed) -export NPM_CONFIG_PREFIX="$HOME/.npm-global" - -# UV Python manager -if [[ -f "$HOME/.local/bin/uv" ]]; then - eval "$(uv generate-shell-completion bash 2>/dev/null)" || true -fi - -# Claude Code CLI -if command -v claude &>/dev/null; then - eval "$(claude completion bash 2>/dev/null)" || true -fi - -# kubectl completion -if command -v kubectl &>/dev/null; then - source <(kubectl completion bash 2>/dev/null) || true -fi - -# helm completion -if command -v helm &>/dev/null; then - source <(helm completion bash 2>/dev/null) || true -fi - -# GitHub CLI completion -if command -v gh &>/dev/null; then - eval "$(gh completion -s bash 2>/dev/null)" || true -fi -EOF - chown "$USERNAME:$USERNAME" "$BASHRC" - print_info "Shell environment configured" -fi - -# ============================================================================ -# COPY SSH AUTHORIZED KEYS (optional) -# ============================================================================ - -# Create .ssh directory with correct permissions -mkdir -p "$USER_HOME/.ssh" -chown "$USERNAME:$USERNAME" "$USER_HOME/.ssh" -chmod 700 "$USER_HOME/.ssh" - -SSH_KEY_COPIED=false - -# Option 1: --ssh-keys-from -if [[ -n "$SSH_KEYS_SOURCE" ]]; then - if [[ "$SSH_KEYS_SOURCE" == "-" ]]; then - # Source is stdin (great for piping over SSH) - cat > "$USER_HOME/.ssh/authorized_keys" - if [[ -s "$USER_HOME/.ssh/authorized_keys" ]]; then - print_info "SSH authorized_keys read from stdin" - SSH_KEY_COPIED=true - else - print_error "No SSH keys received from stdin" - exit 1 - fi - elif [[ "$SSH_KEYS_SOURCE" == @* ]]; then - # Source is a local user (@username) - SOURCE_USER="${SSH_KEYS_SOURCE#@}" - SOURCE_HOME=$(getent passwd "$SOURCE_USER" | cut -d: -f6) - if [[ -n "$SOURCE_HOME" ]] && [[ -f "$SOURCE_HOME/.ssh/authorized_keys" ]]; then - cp "$SOURCE_HOME/.ssh/authorized_keys" "$USER_HOME/.ssh/" - print_info "SSH authorized_keys copied from user $SOURCE_USER" - SSH_KEY_COPIED=true - else - print_error "Cannot find SSH keys for user $SOURCE_USER" - exit 1 - fi - elif [[ "$SSH_KEYS_SOURCE" == *:* ]]; then - # Source is SCP path (user@host:/path) - if scp -q "$SSH_KEYS_SOURCE" "$USER_HOME/.ssh/authorized_keys" 2>/dev/null; then - print_info "SSH authorized_keys copied via SCP from $SSH_KEYS_SOURCE" - SSH_KEY_COPIED=true - else - print_error "Failed to copy SSH keys via SCP from $SSH_KEYS_SOURCE" - exit 1 - fi - else - # Source is a local file path - if [[ -f "$SSH_KEYS_SOURCE" ]]; then - cp "$SSH_KEYS_SOURCE" "$USER_HOME/.ssh/authorized_keys" - print_info "SSH authorized_keys copied from $SSH_KEYS_SOURCE" - SSH_KEY_COPIED=true - else - print_error "SSH keys file not found: $SSH_KEYS_SOURCE" - exit 1 - fi - fi - -# Option 2: --copy-ssh-keys (from sudo user) -elif [[ "$COPY_SSH_KEYS" == "true" ]]; then - SUDO_USER_HOME="" - if [[ -n "${SUDO_USER:-}" ]] && [[ "$SUDO_USER" != "root" ]]; then - SUDO_USER_HOME=$(getent passwd "$SUDO_USER" | cut -d: -f6) - fi - - for SOURCE_HOME in "$SUDO_USER_HOME" /root; do - if [[ -n "$SOURCE_HOME" ]] && [[ -f "$SOURCE_HOME/.ssh/authorized_keys" ]]; then - cp "$SOURCE_HOME/.ssh/authorized_keys" "$USER_HOME/.ssh/" - print_info "SSH authorized_keys copied from $SOURCE_HOME" - SSH_KEY_COPIED=true - break - fi - done - - if [[ "$SSH_KEY_COPIED" == "false" ]]; then - print_warn "No SSH authorized_keys found to copy from sudo user" - fi -fi - -# Set permissions if keys were copied -if [[ "$SSH_KEY_COPIED" == "true" ]]; then - chown "$USERNAME:$USERNAME" "$USER_HOME/.ssh/authorized_keys" - chmod 600 "$USER_HOME/.ssh/authorized_keys" -else - print_info "SSH directory created (add your own keys to ~/.ssh/authorized_keys)" -fi - -# ============================================================================ -# FIX SNAP FIREFOX PERMISSIONS (Ubuntu) -# ============================================================================ - -if [[ "$DISTRO" == "ubuntu" ]] && command -v snap &>/dev/null; then - # Pre-create snap firefox config to avoid broken symlinks - SNAP_FIREFOX_CONFIG="$USER_HOME/snap/firefox/common/.mozilla" - if [[ ! -d "$SNAP_FIREFOX_CONFIG" ]]; then - mkdir -p "$SNAP_FIREFOX_CONFIG" - chown -R "$USERNAME:$USERNAME" "$USER_HOME/snap" - print_info "Snap Firefox directories prepared" - fi -fi - -# ============================================================================ -# SUMMARY -# ============================================================================ - -echo "" -print_info "============================================" -print_info "User '$USERNAME' created successfully!" -print_info "============================================" -echo "" -echo " Username: $USERNAME" -echo " Password: $PASSWORD" -echo " Home: $USER_HOME" -echo " Sudo: Passwordless (NOPASSWD)" -echo " Groups: $(id -nG "$USERNAME")" -echo "" -echo " Developer tools configured:" -echo " - npm global: ~/.npm-global (no sudo needed)" -echo " - Git config: ~/.gitconfig (set name/email!)" -echo " - AWS CLI: ~/.aws" -echo " - Azure CLI: ~/.azure" -echo " - kubectl: ~/.kube" -echo " - Docker: ~/.docker" -echo "" - -if command -v grdctl &>/dev/null; then - # Get IP address - IP_ADDR=$(hostname -I 2>/dev/null | awk '{print $1}') - echo " RDP Access:" - echo " Host: ${IP_ADDR:-$(hostname)}:3389" - echo " User: $USERNAME" - echo " Pass: $PASSWORD" - echo "" -fi - -print_warn "IMPORTANT: User must configure Git identity:" -echo " git config --global user.name \"Full Name\"" -echo " git config --global user.email \"email@example.com\"" -echo "" - -if [[ "$PASSWORD" == "$USERNAME" ]]; then - print_warn "Password is same as username - consider changing it!" - echo " Change password: passwd $USERNAME" - echo " Change RDP pass: sudo grdctl --system rdp set-credentials $USERNAME " - echo "" -fi - -print_info "User can now log in via console, SSH, or RDP"