📚 Update README for public release + installation docs

This commit is contained in:
2026-02-06 07:49:34 -03:00
parent a94809c812
commit fc4f98c359
3 changed files with 789 additions and 37 deletions

View File

@@ -0,0 +1,251 @@
%PDF-1.4
%“Œ‹ž ReportLab Generated PDF document (opensource)
1 0 obj
<<
/F1 2 0 R /F2 3 0 R /F3 6 0 R
>>
endobj
2 0 obj
<<
/BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font
>>
endobj
3 0 obj
<<
/BaseFont /Helvetica-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font
>>
endobj
4 0 obj
<<
/Contents 18 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
5 0 obj
<<
/Contents 19 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
6 0 obj
<<
/BaseFont /Courier /Encoding /WinAnsiEncoding /Name /F3 /Subtype /Type1 /Type /Font
>>
endobj
7 0 obj
<<
/Contents 20 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
8 0 obj
<<
/Contents 21 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
9 0 obj
<<
/Contents 22 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
10 0 obj
<<
/Contents 23 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
11 0 obj
<<
/Contents 24 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
12 0 obj
<<
/Contents 25 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
13 0 obj
<<
/Contents 26 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
14 0 obj
<<
/Contents 27 0 R /MediaBox [ 0 0 595.2756 841.8898 ] /Parent 17 0 R /Resources <<
/Font 1 0 R /ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
>> /Rotate 0 /Trans <<
>>
/Type /Page
>>
endobj
15 0 obj
<<
/PageMode /UseNone /Pages 17 0 R /Type /Catalog
>>
endobj
16 0 obj
<<
/Author (\(anonymous\)) /CreationDate (D:20260206074725-03'00') /Creator (\(unspecified\)) /Keywords () /ModDate (D:20260206074725-03'00') /Producer (ReportLab PDF Library - \(opensource\))
/Subject (\(unspecified\)) /Title (\(anonymous\)) /Trapped /False
>>
endobj
17 0 obj
<<
/Count 10 /Kids [ 4 0 R 5 0 R 7 0 R 8 0 R 9 0 R 10 0 R 11 0 R 12 0 R 13 0 R 14 0 R ] /Type /Pages
>>
endobj
18 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 406
>>
stream
Gat%\d;$NP'Sc)R'^*mRN&bTUc0dKW9UJa]fR9hu45*0Ql58mHGM:<!6T7IW"O8+'n,*H]%Q8No"5IVS%1uEe?33_G5sN6"%^lCe-Y'u%,nrN%L^ap[>;/-#Qf2Ae%@Bs)EBjgGEAcYer$ig+[eq`j.jqoY0WsY,e81(2VF%71Tbl(D9HQ`fV^p,tTWdV+acno#k?T:.N\2^30.Jl]Aoh:bH#rn@J/__.ZeP;o_IQtV^Gka@9<39(Au8`mT/SO5:$6]LS[pcGm/k;181WlP@WcYg7?38"DD!jc$#B^ui8Adi7p@%"gm6P0Rpp"c=BHCTAS!W\)#(M$jN.1k#VQO=rI,^\B:gj.Qc9%]%NdC3HYP)(%KmU<Z,h&fD9A>ScY_74.p1eO2YTGK+nu0G<M7D~>endstream
endobj
19 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 829
>>
stream
GatU19iKe#&A@7.lk*E?/Rp/JDBUTn)*S+AHfCd@S$6:)7ZoQEIskC9?msJISn'tDOY(k9gUD+Q!^aUhHWMN/Ba.qi"Gd>h-&=O:+hNDG=mrmK2CJB!cqgE9^`XKt,42<+*H)0[)@J:\,=)s>__;;$l>\ZN$G`?-%NYYCio!\p6Q_*aIZTg5cI'_m&@+gI5'b(N^A`m+S\.5tg[4`+@KXSpKP_c[Tl+HYe!k,<BM&SR+e;kQ_oj#c0.`R">Ym_soZoBq@!,rn_K1@&FLe&:6Aa!LP4f.g]s8X#)6)!Zr>4`(<&lLCKp<hgdPtDCY6q5)i;gG5Vi<74EZ/\fV5(F.[ccIB_gh4e66QR3"G5h>U#S'.@@R5>&2U=4=h$iL(oqKYe3UT5mE"0ke.uuP5)-+t=C,B.efegWIk[:=5D$N;eId0TX#."7a8<aa>a#*S>UI$I-b3WjOp,"\SD"T*/d*,SI`oBf+E=bM#u6j&=YpW[ei6X22Qe06[!*Xl:*cRmmNa\r0[V`mg&Xk<+ItGF9ZM[l7W2<S.Qd.X!O4GAET?]]"Ypjoi!X'(.\6a*hj<+5WbkGtO@@"*l(Ue[LKEXbG:JOZ1sRkGG/;IPm:D%n(aR!^*',mCPB*HL:Oo(gA2Ug?UL_V]nUmeCLZE!\3AG_U4[Fh&dbGs]a:=RbgLg!]H(Qi3<r!$H2,Au`>+k+8%2+fkNd54n=4Dk/j%gIR=td^)aF;Z!=,(JA!C'9Oagk='=#TeOB*:#-h9+[Rp6&QP$;sY9]!39U*N*A-R4-SfNr8gO%d&cVKAE5uit:)95BT)Bo3$5V^Oq0q+%Cr!.K~>endstream
endobj
20 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 596
>>
stream
Gatn#?#Q2d'Sc)J/)JIX;-_j`Y]JDQ>rO34BcqW5+[A,--!'iORJ,Zb+T#iaBsNoEP(CO:o:,od/\l(VE@u!6Ol?4jJ<7hn+@6hf>N%'$4AWmkAL(DhU_/D_b_1f]XeXKARSX8a&uN1d4@Jd#Tkr^IJ5Xp^>_5q>>fn5_M.B^icb414k?=)[WGT8Ic;0RN6$>/jmqDWW0>eTRic64%8:en_TYn#f4ec;&DsYd#Y4[>9f?ds=VTE6bEV(-fLtd,7_e$-A6_\Nojai9t59.)F\=$:Mf*`*a*$*=-g9ttl6#jS'RP$aBFE]G,2P"?am<;i3.`T@TcEXIZ2W'X;l2d76h)r$H$<L<@1,%nNrZl2_fb_325P6FWRj23,SU9'])0Ma7o[M&S8rKHm,WMEB4%Vm2q`%01PH`2-%qKY?R?P.Xb?JdDqddJ'Aa]-l\Rt-Q3GTf[lO\!<KVpse/.IkQ=rRn_ZNs9ZLU/]i<>uc(<;b?\U1KdhA%_oe:p+F-H8X:o1L)2tYeE^cHq2!J&6\/_kH2psP!UW,,_Zl_G)o@_hQ82<p9Mjh>C?D5qR3,#'Z:3^?QIU%.dc!i1&1j0qK&e~>endstream
endobj
21 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 674
>>
stream
GatUp?Z4CI'ZJu,.F-dX;VfuBd^X3!NDVF]1*U$9%pn8&7SV[k.0>>:cZRrZ<C&GM7EQ^k^;##tn$sDM?+dl6(%<]ji!fo-a@bq6)^2i0<RuN\nbpTuYXAi?0oj;5b='cBqTX[5ELtSk(.U->7W?Nl7H9F/$<9rB!Eqq.Ka=AZ$lNZbDq%tPb2Q059VGc:qhj_qE'M_B-h]5X@RohS;kDY385.Njg$tpfXfE-cANWSMRl(N^ZV/-N@_R(KS)6t%j<-E$53\D*1epP#I8X*gaFNp'P,5-OOg5ZrUV(F';Se)cn9Fl#"PVCefNuQ/18kJ*K8b3Df'&J"isf$`Zgj6q@&Y)W2_/BRAh8Dj?MW,s'oA/F.fQ9-o0_%8lX67J:pM@+cbMrY*GGA,f#K0*9PO':8=o,@YVk8ooNG@Aiu;9HkaQ,,T:`o7]@IGM:#36SDDf6Fr)Q*b)lJ+N"NWFG:>f;;_WOZ1]$=#`@'>o$V``J;Z'B(&3gHieh'%j,n:(dBQR75')I(Q#fT:seAod3!TZ+I%q[7^N)cH*sYZ\"r[0P([)')eLP<%YWY/&JA]I.kLD*=?S4\EL;MmA`J8\5L&AJ'?f8OoD#^A*<5qo/IcS).aY'3oI@UQM<*?-Me5s+()dmV1s;k$Mh;[15oB*bXKOM*1EZ!Mi\"EW~>endstream
endobj
22 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 847
>>
stream
Gaua<gMY_1&;KY!MReNU&rFT>p_X=:,]Q_^&5mJ:Rn1rH?=6ubLt>*qlGIg^B^DB=Z)FZ0$*\V9s313J!sK-@[!_U8J27_IQP:hMD['/g3dB97HEF(\h+!ilQk"0c=GB8C@ljB)*Y[]"PhHs@%*c%7*R]3@ZdECd9GM#W"rN'9)(SUoFTTHOAUMUJ*lEe(3F<h[pC4d!6ME:MrhRg2RPnnqPZjpbKY8P0QTa#+=o)>]Ko=U`0%0Jo:"pgleZiV!QEA'm-Pd6o/KWFOLY0%F"#CO".U[Et-EbmSERZ1DNA`4YlX';#.4W<>H4H^)L#:<=ZrJ0c^lo2t,iG)@_m84o+ZpjfZCrRdIXn&g)iR3UmG\I61Guk#7@#7b[+h.0N!*_L`/d:\$#3>VQPjijdP)0(_lmG]#mXh7m\Bk2_lRk3b8ge">cuJDna4BUpniUSO4L56\Mo?%I+9/TcPfnAQPoSA3"cs4R4\!M!c@[/cEhoSNK]'T,D$.X?NSm8I_S+bZ2]",HZ1#r1HEc[hI+tFM\5!!!VI*K,$GS`k$bP0j[FkTi_`t:HFjPPX*(,$a1K":L0%Mb_/$BEgd'k[N%8$#<:Z<9lEl*^eZb0!T_48\aB,%nqI!$rN@.d<2hR7I5FU^Sgb;<Ri^X`m_8U)4oAGW5_s9Js65b1_S![Y[GJe;'e*5\5Em[r4>4Bfg:,>bdI(JnjVXF8up%epfm5P]?;G0Q+K_o4%f$Iq$a7&':/ZXVAYG'NeND!V:R:tF+p7(8tHf`LFl8r$h1pS."X[cUAg=m'oTT`Iagu6Td)O/II(ZW+4+9T?8<6h;s#SGAN?N5!E!)]J6l@meBlJ2Y!~>endstream
endobj
23 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 807
>>
stream
GatUq;,>q#'SYHA/$?5q`Y?I:&gupJffBG!M2dfmH^[Xfd]au$gY"jGO5E[[d89%_5`o6L\\@8%42*<LM@]#:ZO5W($3!F!N5KZ>/0lAi:LLo,ge?@t;K*gXShc+sR'9Pc\.2jZSq`1M=@+4#-8YjH3PfV"?3"20fUN%E@<9`Kecue<j4ZOsb"QQk29[[QmG>_N$C6ILnlL41;@fLQ3pg8B.e6mX[mRdpoSTQ["=P[E@2)]VA29KZQ2+G@g;$FXi0V_'jN=JQ$'hY$Vi<NDKJgmo=<j'8=@>FLJ!bn[_k_?5!&A>[Y,!R'q7Nk$+qe\o8Hk*;&9bh96JV]/nL,\TOsZ9P"H7r_@Fl;)#:X:_r.lc(ngN0f%3TL>[qf3o=^t(n<d&HaCZhju^;$&-H].^Q\)S!sB@DM\eF.[LSo"39]7rOX)l.s,m<Z_E,!OZ9l`bi(FX,'ARPZ%VnaT0?FRfI]LCh#[+`>rgZ[>:b%c5!`/8h<KI'uL'PVr5q21DM\=o&q'mHa(\U$J<9^J,a8N?QoglVbp]qV;4f/F)BKQW5ZTa.7P0Fes/(G<89<5KkMkYFCIE\m?,<NThYZQ-2&iqL+Ge=cJ4oU4PcdM,Z/Qp-spP;iHR?]jR(mDUDpde%HF$/X+f*O.Y]T$B+MD2u@X^I@>X-jJ0mrAI_QG3Z#1k0o>9"C:?E/b*aH[K0iS]Mc/Y8E2HLY!t=3t!:U.H0%rrVdpVXG;cQ"J0mMXkih2!P,@`G77n)!8;8(T*Q&nXmIg2KAm0IPPmSrjQiTY@9WPr)`\AtFM,V]$%i9'8l~>endstream
endobj
24 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 417
>>
stream
Gas2E?YdM4'ZJu,.5'u+$-"=#:%ILYJkUn<Aa`c]?"RrbZk_AohbDW]XGhi1iVr7*-\OgBK6D%="*d@F4JtF^U`5s=M'-*@@iB^uoL($b,a(_+4Q_=>6t.7($'Pst!YH'#;M5Xl4?te#COf;E'PDq1MDOCk#75sLh5PF3CR?[ipQ0hj3qS^k3,[@q#q,:Q/!H'Q#d/A.07iuN.$d7,.=b(.^hMF045iEWOQ.K"0qTT*`u<8O+FQk0c9sE+F$-uQ#.F@^[Y24hY(8Z:PU83/6*8u"A@Cpcqtq8W<lhD-qi>do/GQ6i;=]I)C>'Sg2sjA,*`L_h9_`,$hH"FBBI'HLWs\HH_rb69gX\ld3WH>D[7@4=N4/S5fX'BaR'%4oU^ql)f4?`n-,qMDYBg%[^tG!UIN*k\aF(0e~>endstream
endobj
25 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 679
>>
stream
GatUq;/ao;&BE]*.IM2F[*3\5-_A7DMjP=q1tG41m)=+\bg=;1iuh(U_fO,CecOPl.SGe2qsO3no3F\6i1U%MCOfOoB,;71KCTd+:H4S[GZRYK'DcrOYXD#/.HFX':am[DiHE'`VmO5a8Od5V3;@6?hWPUQ?.J//!M2X@N()>gGle@PF^?q/*CKW3b*0pDK&^33`cmfk,*_46K7ppgj*`IIO.1=/1r3q'PoG5uqm\WZ3@mog#a7`)cpM'9nDS-hV>G/!(,j;ckh8dWlWUeY>,h45l',Q2*5=*m82=Mio]d&QReoS]Wl!\hJ3+GFMt^/9M*Vbp0j_^jqtj*4&C?jMd3q8l2W0]`E1S+okLV1#R+p=!gJe9"9I/kD>t[KSK#=3V6oRB+.F2O&'XE65.DQn44mDp>cr;chjaZA!X\K2&n$T#8UXWrr[E`&hRrcZtdIsZM%K)/dG`F[mBBc_$9H05^f:Os-%kX"0:1tkMH0&<cfK(_XfLTu?]J]krq*+MeasVhoYq"BJ=?%f5l^/i?"3\+,G/h,'7PhjT]AVBD@Q6A%#B"D=(F4SKZ(;1S)&]&s:U[O9MshQg8-e2"O>)M.O.;\ibuuXP[CTQmE(b+"'qD`8K&r.99ZG6q6dCV[jNh+K]\<Gspci`6`rk5u^.g<K`b;F(0>M#e$cFX>>6~>endstream
endobj
26 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 647
>>
stream
Gatn"?#S1G'Sc)R.unf%Fs:gojhi..`*euu63>jTDCS@el?nQ/c=.UB^ZWQ#[SdQ8!K*+$naUn^pT[*%a,@NUh?(@8@!5+m#*9Qb6P;`Z*n"kH4/1KP3$9pd3/&VM#j!e]FZ<(s*`C.bKLA":IL(?^_J]!3!*ck`492J"k!:].ShL4KY;b'm1mQY#<ok%$)p"$EePCEQV&Y.Mb,FN&R`#f"i")QU9>m@a)m-3?Q0\r.TqPM0?AnN&iL"VJ4@\J<T<Jn#TBJQA*L;El-]E$L6&[(9$,s/b]OMQ>BL84`7\%*DjU(Fm/-\2p!K@^3od*;_3r^[VaE?6O,GEM]EL$jUpQOab=P:R&fU42(Wt*2d`B2cP!pY%[Q$#31X^l=g!LbBXpBVeb'9U8KjiMK0!1`k^DkODE4.XV3l-`e3o?ZkX50Qfjchpol7:WAgMDok1/(*Fd!H/(OX(nb!i?EWfo1:1Prp@ePV3+g:#"qr&&F6c*#H/sMM>dV7?dV#rqgn@)qu1T#5@b6`Z=PZuFQO?)0"2t>bMd.1n_uZ(@:P&LEfjt\$"L^8IXP3&;o..8ge$A[F`oV[/,`1eNlUnui(dMpgbSeV?&Vk6eJ,a1:$3tH<n%SK_:UJhj^&7^)S\Dg!skZo>FmiJ~>endstream
endobj
27 0 obj
<<
/Filter [ /ASCII85Decode /FlateDecode ] /Length 380
>>
stream
Gat=f?VeNm'ZJu(.F'0*d.MR3TKF)9MMV[p4n?J0KGqjLFDCaGh@0O"8/-*.Rl!8k^XLpM,T"uoaad\#pQe&Od0n#35,&;S,Nm=FSMF.ge4LD.6!KE\24roGTsRVF@>P8cmRSG=ggN.q"5#)5Es5UL\Pe]86OSjrF^E_-M<G]%<CM8s3^r[m,GM9KIo97rC(0!Nl8rf:/W>Z`]3&1IhK3$^?S>*e&kS[O\G-;3dH0GY4P:^q1L>oZnZmR'rm'.^)'8q(NEqcg`HG`I\)ldj(k9R3[<HnTIPs(,/iMJ)^-6T>U$)$^nnRf2JPpj2l"guI+&*eFRl$:"PEW$Y_pRCkpk0D(Vm@'Z4=DcPpCq4n?8;C6b?mQoHijWc_<M~>endstream
endobj
xref
0 28
0000000000 65535 f
0000000061 00000 n
0000000112 00000 n
0000000219 00000 n
0000000331 00000 n
0000000536 00000 n
0000000741 00000 n
0000000846 00000 n
0000001051 00000 n
0000001256 00000 n
0000001461 00000 n
0000001667 00000 n
0000001873 00000 n
0000002079 00000 n
0000002285 00000 n
0000002491 00000 n
0000002561 00000 n
0000002842 00000 n
0000002962 00000 n
0000003459 00000 n
0000004379 00000 n
0000005066 00000 n
0000005831 00000 n
0000006769 00000 n
0000007667 00000 n
0000008175 00000 n
0000008945 00000 n
0000009683 00000 n
trailer
<<
/ID
[<e008cf68dc688c141bb85a7c4e11c678><e008cf68dc688c141bb85a7c4e11c678>]
% ReportLab generated PDF document -- digest (opensource)
/Info 16 0 R
/Root 15 0 R
/Size 28
>>
startxref
10154
%%EOF

422
docs/gerar_manual_pdf.py Normal file
View File

@@ -0,0 +1,422 @@
#!/usr/bin/env python3
"""
🐍 OPHION - Gerador de Manual PDF
"""
from fpdf import FPDF
from datetime import datetime
import os
class OphionManualPDF(FPDF):
def __init__(self):
super().__init__()
self.set_auto_page_break(auto=True, margin=15)
# Adicionar fonte Unicode
self.add_font('DejaVu', '', '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', uni=True)
self.add_font('DejaVu', 'B', '/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf', uni=True)
self.add_font('DejaVuMono', '', '/usr/share/fonts/truetype/dejavu/DejaVuSansMono.ttf', uni=True)
def header(self):
self.set_font('DejaVu', 'B', 10)
self.set_text_color(100, 100, 100)
self.cell(0, 10, 'OPHION - Manual de Instalação', new_x='RIGHT', new_y='TOP')
self.cell(0, 10, f'v1.0 | {datetime.now().strftime("%d/%m/%Y")}', new_x='LMARGIN', new_y='NEXT', align='R')
self.line(10, 18, 200, 18)
self.ln(5)
def footer(self):
self.set_y(-15)
self.set_font('DejaVu', '', 8)
self.set_text_color(128, 128, 128)
self.cell(0, 10, f'Página {self.page_no()}/{{nb}}', new_x='RIGHT', new_y='TOP', align='C')
def titulo(self, texto):
self.set_font('DejaVu', 'B', 18)
self.set_text_color(75, 0, 130)
self.cell(0, 15, texto, new_x='LMARGIN', new_y='NEXT')
self.ln(2)
def subtitulo(self, texto):
self.set_font('DejaVu', 'B', 14)
self.set_text_color(50, 50, 50)
self.cell(0, 10, texto, new_x='LMARGIN', new_y='NEXT')
self.ln(1)
def subtitulo2(self, texto):
self.set_font('DejaVu', 'B', 12)
self.set_text_color(70, 70, 70)
self.cell(0, 8, texto, new_x='LMARGIN', new_y='NEXT')
def paragrafo(self, texto):
self.set_font('DejaVu', '', 11)
self.set_text_color(0, 0, 0)
self.multi_cell(0, 6, texto)
self.ln(2)
def codigo(self, texto):
self.set_font('DejaVuMono', '', 9)
self.set_fill_color(245, 245, 245)
self.set_text_color(0, 100, 0)
self.multi_cell(0, 5, texto, fill=True)
self.ln(3)
def item(self, texto, bullet="-"):
self.set_font('DejaVu', '', 11)
self.set_text_color(0, 0, 0)
self.cell(8, 6, bullet, new_x='RIGHT', new_y='TOP')
self.multi_cell(0, 6, texto)
def alerta(self, texto):
self.set_fill_color(255, 243, 205)
self.set_font('DejaVu', 'B', 10)
self.set_text_color(133, 100, 4)
self.cell(0, 8, f'[!] {texto}', new_x='LMARGIN', new_y='NEXT', fill=True)
self.ln(2)
def sucesso(self, texto):
self.set_fill_color(212, 237, 218)
self.set_font('DejaVu', 'B', 10)
self.set_text_color(21, 87, 36)
self.cell(0, 8, f'[OK] {texto}', new_x='LMARGIN', new_y='NEXT', fill=True)
self.ln(2)
def gerar_manual():
pdf = OphionManualPDF()
pdf.alias_nb_pages()
# ========== CAPA ==========
pdf.add_page()
pdf.ln(40)
pdf.set_font('DejaVu', 'B', 36)
pdf.set_text_color(75, 0, 130)
pdf.cell(0, 20, 'OPHION', new_x='LMARGIN', new_y='NEXT', align='C')
pdf.set_font('DejaVu', '', 16)
pdf.set_text_color(100, 100, 100)
pdf.cell(0, 10, 'Open Source Observability Platform', new_x='LMARGIN', new_y='NEXT', align='C')
pdf.cell(0, 10, 'AI-Powered Monitoring', new_x='LMARGIN', new_y='NEXT', align='C')
pdf.ln(20)
pdf.set_font('DejaVu', 'B', 20)
pdf.set_text_color(50, 50, 50)
pdf.cell(0, 15, 'Manual de Instalação', new_x='LMARGIN', new_y='NEXT', align='C')
pdf.ln(40)
pdf.set_font('DejaVu', '', 12)
pdf.set_text_color(128, 128, 128)
pdf.cell(0, 8, f'Versão 1.0 | Fevereiro 2026', new_x='LMARGIN', new_y='NEXT', align='C')
pdf.cell(0, 8, 'https://ophion.com.br', new_x='LMARGIN', new_y='NEXT', align='C')
# ========== ÍNDICE ==========
pdf.add_page()
pdf.titulo('Índice')
indice = [
('1. Visão Geral', 3),
('2. Requisitos do Sistema', 3),
('3. Instalação Rápida', 4),
('4. Instalação Manual', 5),
('5. Configuração', 7),
('6. Instalação do Agent', 9),
('7. Primeiros Passos', 11),
('8. Comandos CLI', 12),
('9. Segurança', 13),
('10. Troubleshooting', 14),
('11. Suporte', 15),
]
for item, pag in indice:
pdf.set_font('DejaVu', '', 12)
pdf.cell(160, 8, item, new_x='RIGHT', new_y='TOP')
pdf.cell(0, 8, str(pag), new_x='LMARGIN', new_y='NEXT', align='R')
# ========== 1. VISÃO GERAL ==========
pdf.add_page()
pdf.titulo('1. Visão Geral')
pdf.paragrafo('OPHION é uma plataforma de observabilidade open source que combina métricas, logs e traces com inteligência artificial para monitoramento proativo de infraestrutura.')
pdf.subtitulo('Principais Recursos')
pdf.item('Métricas de sistema (CPU, RAM, Disco, Rede)')
pdf.item('Coleta e análise de logs centralizados')
pdf.item('Distributed tracing para microserviços')
pdf.item('OPHION Copilot - Chat com IA especialista')
pdf.item('Auto-Healing - Correção automática de problemas')
pdf.item('Smart Alerts - Alertas inteligentes sem ruído')
pdf.item('Predictions - Previsões de capacidade')
pdf.ln(5)
pdf.subtitulo('Stack Tecnológico')
pdf.item('Backend: Go (Fiber)')
pdf.item('Frontend: Next.js 14 + TypeScript')
pdf.item('Banco de dados: PostgreSQL + ClickHouse')
pdf.item('Cache: Redis')
pdf.item('IA: OpenAI GPT-4')
# ========== 2. REQUISITOS ==========
pdf.add_page()
pdf.titulo('2. Requisitos do Sistema')
pdf.subtitulo('Requisitos Mínimos')
pdf.item('CPU: 2 cores')
pdf.item('RAM: 4 GB')
pdf.item('Disco: 20 GB SSD')
pdf.item('OS: Ubuntu 20.04+ / Debian 11+ / CentOS 8+')
pdf.ln(3)
pdf.subtitulo('Requisitos Recomendados (Produção)')
pdf.item('CPU: 4+ cores')
pdf.item('RAM: 8+ GB')
pdf.item('Disco: 100+ GB SSD')
pdf.item('OS: Ubuntu 22.04 LTS')
pdf.ln(3)
pdf.subtitulo('Software Necessário')
pdf.item('Docker 24.0+')
pdf.item('Docker Compose 2.0+')
pdf.item('curl, git (para instalação)')
pdf.ln(3)
pdf.subtitulo('Portas Utilizadas')
pdf.codigo('8080 - API REST\n3000 - Dashboard Web\n5432 - PostgreSQL (interno)\n9000 - ClickHouse (interno)\n6379 - Redis (interno)')
# ========== 3. INSTALAÇÃO RÁPIDA ==========
pdf.add_page()
pdf.titulo('3. Instalação Rápida')
pdf.paragrafo('A forma mais fácil de instalar o OPHION é usando nosso instalador interativo:')
pdf.codigo('curl -fsSL https://get.ophion.io | bash')
pdf.paragrafo('O instalador irá:')
pdf.item('Verificar os requisitos do sistema')
pdf.item('Coletar informações da sua empresa')
pdf.item('Gerar credenciais seguras automaticamente')
pdf.item('Configurar todos os serviços')
pdf.item('Iniciar a plataforma')
pdf.ln(3)
pdf.subtitulo('Informações Solicitadas')
pdf.item('Nome da empresa/organização')
pdf.item('Email do administrador')
pdf.item('Senha do administrador (mín. 8 caracteres)')
pdf.item('Domínio (opcional, padrão: localhost)')
pdf.item('Portas do servidor e dashboard')
pdf.item('Configuração do Telegram para alertas (opcional)')
pdf.ln(3)
pdf.alerta('IMPORTANTE: Guarde a API Key exibida ao final da instalação!')
# ========== 4. INSTALAÇÃO MANUAL ==========
pdf.add_page()
pdf.titulo('4. Instalação Manual')
pdf.subtitulo('4.1 Instalar Docker')
pdf.codigo('# Ubuntu/Debian\nsudo apt update\nsudo apt install -y curl\ncurl -fsSL https://get.docker.com | sh\nsudo usermod -aG docker $USER')
pdf.alerta('Faça logout e login novamente após adicionar o usuário ao grupo docker.')
pdf.subtitulo('4.2 Baixar OPHION')
pdf.codigo('git clone https://github.com/bigtux/ophion.git\ncd ophion')
pdf.subtitulo('4.3 Configurar Variáveis de Ambiente')
pdf.codigo('cp .env.example .env\nnano .env')
pdf.paragrafo('Edite as seguintes variáveis:')
pdf.codigo('ORG_NAME="Sua Empresa"\nADMIN_EMAIL=admin@empresa.com\nADMIN_PASSWORD=senha-forte-aqui\nDOMAIN=ophion.empresa.com\nJWT_SECRET=$(openssl rand -hex 32)')
pdf.add_page()
pdf.subtitulo('4.4 Iniciar os Serviços')
pdf.codigo('docker compose up -d')
pdf.subtitulo('4.5 Verificar Status')
pdf.codigo('docker compose ps')
pdf.paragrafo('Todos os serviços devem estar com status "running":')
pdf.codigo('ophion-server running 0.0.0.0:8080->8080/tcp\nophion-web running 0.0.0.0:3000->3000/tcp\nophion-postgres running 5432/tcp\nophion-clickhouse running 9000/tcp\nophion-redis running 6379/tcp')
pdf.sucesso('Acesse o dashboard em http://localhost:3000')
# ========== 5. CONFIGURAÇÃO ==========
pdf.add_page()
pdf.titulo('5. Configuração')
pdf.subtitulo('5.1 Arquivo .env')
pdf.paragrafo('Todas as configurações são feitas via variáveis de ambiente no arquivo .env:')
pdf.subtitulo2('Organização')
pdf.codigo('ORG_NAME="Minha Empresa"\nADMIN_EMAIL=admin@empresa.com\nADMIN_PASSWORD=senha-segura')
pdf.subtitulo2('Rede')
pdf.codigo('DOMAIN=localhost\nSERVER_PORT=8080\nDASHBOARD_PORT=3000')
pdf.subtitulo2('Segurança')
pdf.codigo('JWT_SECRET=<64-caracteres-aleatorios>\nAPI_KEY=ophion_<64-caracteres-hex>')
pdf.alerta('Nunca compartilhe o JWT_SECRET ou API_KEY!')
pdf.add_page()
pdf.subtitulo2('Banco de Dados')
pdf.codigo('POSTGRES_USER=ophion\nPOSTGRES_PASSWORD=senha-segura\nDATABASE_URL=postgres://ophion:senha@postgres:5432/ophion')
pdf.subtitulo2('Alertas - Telegram')
pdf.codigo('TELEGRAM_ENABLED=true\nTELEGRAM_BOT_TOKEN=123456:ABC...\nTELEGRAM_CHAT_ID=-100123456789')
pdf.subtitulo2('IA (OpenAI)')
pdf.codigo('OPENAI_API_KEY=sk-...')
pdf.subtitulo('5.2 Gerar Credenciais Seguras')
pdf.codigo('# JWT Secret\nopenssl rand -hex 32\n\n# API Key\necho "ophion_$(openssl rand -hex 32)"')
# ========== 6. AGENT ==========
pdf.add_page()
pdf.titulo('6. Instalação do Agent')
pdf.paragrafo('O Agent é instalado em cada servidor que você deseja monitorar.')
pdf.subtitulo('6.1 Instalação Automática')
pdf.codigo('curl -fsSL http://SEU-SERVIDOR:8080/install-agent.sh | sudo bash')
pdf.subtitulo('6.2 Instalação Manual')
pdf.subtitulo2('Baixar o binário')
pdf.codigo('curl -o /usr/local/bin/ophion-agent \\\n http://SEU-SERVIDOR:8080/downloads/agent/linux/amd64/ophion-agent\nchmod +x /usr/local/bin/ophion-agent')
pdf.subtitulo2('Criar configuração')
pdf.codigo('mkdir -p /etc/ophion\ncat > /etc/ophion/agent.yaml << EOF\nserver:\n url: http://SEU-SERVIDOR:8080\n api_key: SUA-API-KEY\n\ncollection:\n interval: 30s\n\nmetrics:\n enabled: true\n include:\n - cpu\n - memory\n - disk\n - network\n\nlogs:\n enabled: true\n paths:\n - /var/log/syslog\n - /var/log/auth.log\nEOF')
pdf.add_page()
pdf.subtitulo2('Criar serviço systemd')
pdf.codigo('cat > /etc/systemd/system/ophion-agent.service << EOF\n[Unit]\nDescription=OPHION Monitoring Agent\nAfter=network.target\n\n[Service]\nType=simple\nExecStart=/usr/local/bin/ophion-agent -config /etc/ophion/agent.yaml\nRestart=always\nRestartSec=10\n\n[Install]\nWantedBy=multi-user.target\nEOF')
pdf.subtitulo2('Iniciar o serviço')
pdf.codigo('sudo systemctl daemon-reload\nsudo systemctl enable ophion-agent\nsudo systemctl start ophion-agent')
pdf.subtitulo2('Verificar status')
pdf.codigo('sudo systemctl status ophion-agent\nsudo journalctl -u ophion-agent -f')
# ========== 7. PRIMEIROS PASSOS ==========
pdf.add_page()
pdf.titulo('7. Primeiros Passos')
pdf.subtitulo('7.1 Acessar o Dashboard')
pdf.item('Abra o navegador em http://localhost:3000')
pdf.item('Faça login com o email e senha do administrador')
pdf.subtitulo('7.2 Adicionar Hosts')
pdf.item('Instale o Agent em cada servidor')
pdf.item('Os hosts aparecerão automaticamente no dashboard')
pdf.subtitulo('7.3 Configurar Alertas')
pdf.item('Acesse Settings > Alerts')
pdf.item('Crie regras de alerta (ex: CPU > 90%)')
pdf.item('Configure canais de notificação (Telegram, Slack, Email)')
pdf.subtitulo('7.4 Usar o Copilot')
pdf.item('Clique no ícone do chat no canto inferior')
pdf.item('Faça perguntas sobre sua infraestrutura')
pdf.item('Exemplo: "Por que o servidor X está lento?"')
pdf.subtitulo('7.5 Configurar Auto-Healing')
pdf.item('Acesse Settings > Auto-Healing')
pdf.item('Comece no modo dry-run (apenas sugestões)')
pdf.item('Revise e aprove ações antes de habilitar automação total')
# ========== 8. CLI ==========
pdf.add_page()
pdf.titulo('8. Comandos CLI')
pdf.paragrafo('O OPHION inclui uma CLI para gerenciamento:')
pdf.codigo('ophion start # Iniciar todos os serviços\nophion stop # Parar todos os serviços\nophion restart # Reiniciar serviços\nophion status # Ver status dos containers\nophion logs # Ver logs do servidor\nophion logs ophion-web # Ver logs do dashboard\nophion update # Atualizar para última versão\nophion backup # Criar backup dos dados\nophion api-key # Gerar nova API Key\nophion agent-install # Ver comando de instalação do agent')
pdf.subtitulo('Exemplos')
pdf.subtitulo2('Ver logs em tempo real')
pdf.codigo('ophion logs -f')
pdf.subtitulo2('Criar backup')
pdf.codigo('ophion backup\n# Backup criado em /opt/ophion/backups/20260206_120000/')
pdf.subtitulo2('Atualizar')
pdf.codigo('ophion update\n# Baixa novas imagens e reinicia os serviços')
# ========== 9. SEGURANÇA ==========
pdf.add_page()
pdf.titulo('9. Segurança')
pdf.subtitulo('9.1 Autenticação')
pdf.item('JWT Tokens para usuários (acesso ao dashboard)')
pdf.item('API Keys para agents e integrações')
pdf.item('Bcrypt para hash de senhas (cost 12)')
pdf.subtitulo('9.2 Rate Limiting')
pdf.codigo('Login: 5 requisições/minuto\nAPI: 100 requisições/minuto\nIngestão: 1000 requisições/minuto')
pdf.subtitulo('9.3 Proteção contra Brute Force')
pdf.item('5 tentativas de login = bloqueio de 15 minutos')
pdf.item('Tracking por IP + email')
pdf.subtitulo('9.4 Política de Senha')
pdf.item('Mínimo 12 caracteres')
pdf.item('Letra maiúscula obrigatória')
pdf.item('Letra minúscula obrigatória')
pdf.item('Número obrigatório')
pdf.item('Caractere especial obrigatório')
pdf.subtitulo('9.5 HTTPS')
pdf.paragrafo('Em produção, sempre use HTTPS. Recomendamos Cloudflare ou Let\'s Encrypt.')
# ========== 10. TROUBLESHOOTING ==========
pdf.add_page()
pdf.titulo('10. Troubleshooting')
pdf.subtitulo('Containers não iniciam')
pdf.codigo('# Ver logs de erro\ndocker compose logs\n\n# Verificar recursos\ndocker system df\ndf -h')
pdf.subtitulo('Agent não conecta')
pdf.codigo('# Testar conectividade\ncurl http://SEU-SERVIDOR:8080/health\n\n# Ver logs do agent\njournalctl -u ophion-agent -f')
pdf.subtitulo('Erro de SSL (Cloudflare)')
pdf.item('Verifique se o modo SSL está em "Flexible" ou "Full"')
pdf.item('Se "Full (Strict)", precisa de certificado válido no servidor')
pdf.subtitulo('Resetar senha do admin')
pdf.codigo("docker compose exec postgres psql -U ophion -c \\\n \"UPDATE users SET password_hash = \\\n crypt('nova-senha', gen_salt('bf')) \\\n WHERE email = 'admin@email.com';\"")
pdf.subtitulo('Limpar dados e recomeçar')
pdf.codigo('ophion stop\nrm -rf /opt/ophion/data/*\nophion start')
pdf.alerta('Isso apaga todos os dados! Use apenas em último caso.')
# ========== 11. SUPORTE ==========
pdf.add_page()
pdf.titulo('11. Suporte')
pdf.subtitulo('Documentação')
pdf.item('Site: https://docs.ophion.com.br')
pdf.item('GitHub: https://github.com/bigtux/ophion')
pdf.subtitulo('Comunidade')
pdf.item('Discord: https://discord.gg/ophion')
pdf.item('Email: suporte@ophion.com.br')
pdf.subtitulo('Reportar Bugs')
pdf.item('GitHub Issues: https://github.com/bigtux/ophion/issues')
pdf.subtitulo('Segurança')
pdf.item('Vulnerabilidades: security@ophion.com.br')
pdf.alerta('NAO abra issues publicas para vulnerabilidades de segurança!')
pdf.ln(10)
pdf.set_font('DejaVu', '', 10)
pdf.set_text_color(128, 128, 128)
pdf.cell(0, 10, '(c) 2026 OPHION - Made with love in Brazil', new_x='LMARGIN', new_y='NEXT', align='C')
# Salvar
output_path = '/home/kernelpanic/projetos_jarvis/ophion/docs/OPHION_Manual_Instalacao.pdf'
pdf.output(output_path)
print(f'PDF gerado: {output_path}')
return output_path
if __name__ == '__main__':
gerar_manual()