Sync before Archive

This commit is contained in:
2026-02-25 20:36:50 -06:00
parent 73eee46101
commit 7c2ef04d47
17 changed files with 1464 additions and 191 deletions

View File

@@ -1,162 +1,170 @@
$ANSIBLE_VAULT;1.1;AES256
35616466656362396235346561343838343634666539663537353635316361353566383531623266
3934346664633933666162376430626165626132376637630a356261613130306538633933653931
34383032376664306663353836356165373861383932333737336633366362373962663533366235
6663393939396563660a373031353531646165336239656534613330663266666361613834326532
64313632643565666139303464356339383834303262323933326133663163386465323431633332
38616266353430316133313135643164366464346134316462343536636532323432356362623366
63383331663535663739386338376561383962316462613432323938373437646136613564393464
64633530633635633634366135353730343037306437383861363230333036396164656637373864
39383963623865303630376437663861303935363234383539323263303031373865386539346431
64323335663134333738653732613761353938373830376261353737613865653537326561303964
34613134323963663362303235613962303966323163316535386139366161363831656638383665
31376561303733393464303039636565393537616363333431633863356135353038346562323930
35376462623632633632303533313138373630393331616239656365626164613166663837373938
37393064323761303434333265323039356265356532636133383362656634313431333262633566
31363439656433333562316636636431326564346633623862383463613735396563343164326339
39356337623264353363336538646366356631303438353236656234383836356363303436393137
32633665636266623035616264393463363036373530386431653536306431366234353936373464
64666133303734636135616636393165373530663031396139636561306336366636663335363139
65356130666164353564343733623337393137326463306333323338386536333363313337363234
39383666336535386331316162326264343966646562303030363766623936616263646364316432
31326138323031356235316366313361353235346132383965623431353364623331326162663437
37373630323232343662376437653337663166663562343066623363343064336230373964326132
64383965626533663036616261303039663838623030396633393730336334373236366638633339
61613561626664383063373530393130376539316637363964316532313034313065353530373761
30386338386333323633333961636434316330613065643662356131623536323865393933326537
61633231636638396164373635313434376533613334346238396462656334363036643235333839
36643962353662373439366236333363343432643666363561633931323564316664316538363733
30326632393638313665643562616230373335363831656136633633343234336465616361363537
35623666303636303837623430373832663532323430383330313530646636316535336434613466
35373666363665643536363863663161653330646462633239623466346265376231653363393366
61343233326638386633343135316563653234336538613939623938366164326561323861373166
39323462646530333737663039336530656534333332616661373037636336346137643861613930
35613066346262346232643362373835333337626361316339636564663235323939633234363866
38616662623665373139323031343462393135653463306333373665666431613264666661643434
33393666633464636562393335323064636332656336373661353461323830386166656231383639
33373631396439313265383063613638643633343861323733306335366163653332373865663863
61653532643838636137353031323663613933656462333364656331373763323366316339653038
36323831643566323039653566643635303232313137653130393165613633343364646366366532
31386565366438613866346263653166343934323863303839303531346363663234343265393162
31613936333138616237393065656430303436653466613632633335613136616534396434653235
66373834363764333366343933333362363138303663333932643531363863313136633630343063
36326336313733636564356235303664336131653639393964383132663230613264626131353037
36363866636238353430396461616530356435386265393864343164613434376139333038336339
35313964336462626365343135656466316562613935353431326332313461663937326338393536
61663732313464383734323664663566313732323536666237653662393738333835613831623434
38306430616333356436633330626537356265343936343764633638393262356266313130623632
31616131356461656636396539636134616138306239653232613166333765326364666165623334
62663533313064396635333830616362303332643163646138393761366139626363346537333235
61616130366334366437633039343533626664343538396638633833336136336662643937366636
66356665623361386362643237646464326566323865343437336130353031373663643132333630
65656461643733643534363362336364613164383266393136343830663037313365343632363934
32386335303638313734623633323564373163666465336563653934346435353766303331333032
34303037626266366638663435663532633232343361306636303166373437376439653437626537
65373532386332366530616537363334383362653434333162323533376165376533353263396338
31653338383363316537366334613137666365646237303235303731633362383536353564663535
65653864396465333438323532363731643431373666633830316566343537633337366465376138
35663139303761383935316261636461353936653966303738313130626130613130326332386137
38326464356637333933316264663032303161643034303363326665373163656238663364643233
61373461393330316366373135383532323436313535333535623338353332346364613262616539
32383866636233313461323466336538613165316565646431633632353331383237303437306636
35653566386437333536656630323761636262333333396563303264653166656663636264633933
65343435373038366163386464353562303161613162633330633630306566646430613736396266
38396432646637623837356662626639623361356163346564353238353263363434326465306637
62343464623365633133633539383933313633333664316438313830346335326161393138333139
32363237343133386436396537333639623537656362643134356566326439353237313939376637
35336134383035396637383637356536353064636163333639393763616538313264373930366563
32333933373466336465643030663765373164363732656231626261336665633238623830313163
62343438303936383738303737363338333864666135356336313964626131653663393933653130
33313435653364623531323038393962616432636265666437356365323963636431613136633463
64376235393462633162386366666266353234383936306637663136383830663438636637376532
61313134623233626230653931653131356265353836303064326563303936363734656166386133
38303230366562376566376337376164373335303566386638613839353637323563366463396661
31623134666231316337373539356332616136663761303834373831663433316339363630396131
64303066643063666165326439633133383966663265653133346635636634313135636463343835
36383733383561626239363561653034373636373134633934376437316231323433623733393537
32323330366262383463316564373930663634363231636635353137636330393630333930653439
38663066613139343761353164636537356331656534613637356463633561336663393033333331
38636436646162343630393431316664303738373834326165666366396330316366663838376133
61386631646338653761646432613432383763326537393136616662633135323336643330663938
65373234336136643462363939653734613464393830333566643764313834363836356531386363
39386536323864373863666135633039653966333531633030633362343938313138373764643865
31353437363830633363623861643164333631343431663832663564613161363165373561383533
65373234356337373732303038393364326430646131653536646536393139326138373533663761
34626464663563396631393565626431363066303632306561316336373737313937396563396534
65366337353232616361323963303263343235383432323261373564356261663632623836313266
34326163363562343064623265373562316432663839303662613661616265386263336462633163
63643264303062643264396362353864306562323364323361366463333061366439373339363262
35353331393265316631323039623334616638356439346335333864616132363562373334323039
38363161613261363562623032383263303930383538653365393864663266306130613638333131
32666135643831666531343266386365663563393639656635306338366431313563616632653739
61643263616530383466656265316630386537356438653063643832373464376162643831323836
38376338326239326632616262356366396538656666393365383366393237633361333536326434
31366538396337306632663937343064383836653831383538353037343366393534386437643530
30356237393739353437323438623664376338323865656439313231313062313766383363616530
30336363633437643539663037666331346335373639633539613466666231653131316535326439
32353066393064636262633166643832653938633432633762376435616466336363643131383532
62353337336133666530383865326537623932373163643131353034623964396462633936613630
30353566316531313135353965353130646463343539303031353130633536613835383565643932
33383236656433363762653663383961613164633533303061386334656165366337386235656632
36353537383635633631323161636535643733313366613435313632373230326337616165323838
63383038396663303230666337333264613762393066336134653063663562313130303966643238
37336431666265643231376139386138306261636638616466366461373666393531316139373564
61363631633866396531653336363365656236613266373933376535656565623461653465346333
62376566343530366466613536393938343263303437383334373863626138383764656561333662
37613764353639653838633533316462653165663037376134613730323661383364343438353035
39363634623034633263383063653437613339313762333234643062613035373264326233383935
66643134373735383135353763306165303063383161313135343435386163356466656163636366
35323037303562633863346138616530333932313633343162666662333930663535633661633934
36376637396532313265323066626637333061353165633036333739663632346337643137343165
34653561303864613335396233626130363436353764666365356230316534316365613436323639
32613662353438333362363565346432303333356361653065303236626133353961343834333661
31633238666165633561303639626630323235346635356264323934353034316361636331333461
35356138616332656161343434653638653861373962386436323061356263353064613934656663
34653062383434666462623732386337393038313339626463376631623336666133633663643835
31613438376431613862333564396330346635656231333835383433343832613663643163396334
35653739386264326530393261633864656462636264663832303537333833373037323039373731
65393837656234383530353335343730353535393561346137313436383966396632326437343562
31316237396336666233656637383461303737363565356136396336393864383238396164333163
32646238303430626261646236306664396533313136623764303962333836623933666562663439
35666465613738326165626365343734623131356238616162386233376333663764363038636635
63643531323164323634316130326265623966323033356338663261636136373035303665346537
64663065373366636637303237333666396266636535326563653130613237363833626365623331
66363264353831343264306336313532646637343631656230393466396633336639356431313839
39643630626462616336333166333062373231613039313661646231393834386561373431643561
64313933636430343132613263663936313732343233646631616163366633386164653763313333
62383563303434303830363338666465306463643262623637363939623136366639306330636331
33633462643234656636656634663664616338636332393231343932383363643331396635303466
31353935626461396431626336343466623163323730656131313432313635366365653063623537
61306466393938636261363032353330353134383430363164353230323630363864393234356238
32333865663063353566663038316633666464636433626236343632643864656635373833386338
61366136303863343430393661653738626331343366333965616135663339633334623762373266
36383564663337353935626534366365626238306232633534326266656333613664643736356637
64323030626361356338356165326336626365636666343131306236366630653534376333373037
35623062653032666431643936393337623830646134653034336139363863373931653132663165
65333536343535343463373662373937663133616437636137373632373332323632363465613663
36326636666435353062383433373562643464376365623530663836356663336338346565386535
35643136396130326634386632333739663632616538356434376336393664396332623562356164
39636262323563313862303266663035346132323765613732316434353631383234323036323630
34336165306436633434306333313534333238623963306338616363303632613934393732653962
38323331396664336163346236396536333361376431313461383032363733316133343437376637
30376230366666346363383235333836616539626465636539616131373437336332633633316437
31626538326137656262633332623631643737656632653036376432653333643031663266316338
38353734343761656533383133386634343331383338343333363438386231393332653330303631
30643363346538393532373533376537313831633764366566373539346337623135323161323039
36326139306364326663353233343133356165326362666535336138653663613131363835376533
30366566613265346232323062636435373733646461646639306539323762613932313166666331
37643431363961643832336464646433656664613137303062613037346335323230626464383461
61363535616266626364333633333061633234646638383335616232373166346233306139363239
62373363343836623162313638383434363530343134666666346630363630643633616639356231
35336365376437353935353630333835633033306235653964656163613166643136363165396263
35333732373665346362336333356538313161633032653931393465306430396536333735383237
62313361616530623630653762613430393837366431656139393437643837623135333666393231
31323566663366376666663362656630366135633336323462643936343433613938316432653638
64343637383039373265643963653037343530386465363936343438346538633266663762366536
39393732653637343166336663323363653131653035376464643934353963353935386364376336
35633533346632396237346534303665383365633565663939623438343463613938633863323864
36633538643830373964373864323235393865366364303166653739376563616364303936623733
32333935313537643231653232643463303634366366386534363562333635623730316638346661
37663936366330666463623263326134353331613661363863383361643965316635353663396639
38323538333165623666333933393966343763323536663163383133663362383665616237633239
6665
64393362643437353731353234643535366431613861636131613139636435633465306333656161
3365306632386330373862363637363435633235643336610a663736396537313032336162633334
32626233346233323565383030393130316532653062373730376163326134616239663865363862
3365316365643534610a343932623566356637663136336338386534373532383863363662326438
37393331356632313163643138613330366631643465623633386433663236636334666264383033
34333935633131363364626333313336353733373562326636343633653838616532643737366435
36366330633263613938323566393063373233363538643531636131316335316461656631616362
30343965356363383139366534363664313831363132383337636266316538393139383232386230
65353364313534333632306465393264386466346365303232356263653563653338306131376131
66343764643639396663623330623332333466633737343738386230626463386137373536343430
36636430616132363161303338353033343963643338656639643662636664613965636263366135
64353134376162633162316166316239333963653930363830646165636537653238623537323238
39376338636335336338323935333439306534386539336331613961663261623962383237303632
34326139626366303331363337353432623636626231373731646665623831353865303130663533
37326639626237653361316666616161363531303961613538636663633063396363346337663239
64313333653766383736303161636530316538633033323063323662336335666264646564643465
64396436366131373061326233643562626335376263623031376532313730653363343038356135
30336131646635636638353934636139343662623265336338386535663536393935343132306335
33626632613663353661313061623732643539323637336433666330313463666661623836303462
61383732613139343434363662616539373837633139393764353864613062346237346661633033
61393639326535366266643664653439383238646132306636656130333733316638363830346433
38643430346263663639653762393935356662363533323766343362366532626532633530323630
30643436653130363066373665666434383732663837643839356539366432316539613863623839
35323930383437383535373330326239663966383234663233643337623330353236626464636530
36393735646664366235363831656262383333626265383066393363346165656265363438306135
34633530653837346638636665666162363062663333623263356131646661373234333939333536
30643639333836373439613561346130623239363737626238663436356365633562366465643561
32643039376234323963653733353138643138626430383639313765353035646539653466623539
32366135366266323261333938373837386636626232323661393035613638643335383564663462
31383663663063373935396439653231353962303630346338623938343064643037396562626637
63363363343739626639633934393734396434653262373137373539316536306663336466626639
34646465306439313239323365333761663161313461613766343463666134303036376338366663
64356364653462383534343438343933623766396232336434653765613864376235363735343032
32313133383731333366626534363065333738346230393636393938366633363561346436363338
33393932626333636166313431633339386564616466653165383962656633303161393935366635
65396464326333396433303966316231376432363335643732303438663131653932636564363264
36356663623436643835373538363662643134313030656236326335393334626634663136333137
38363432346663393435366536636335636465343131666562396334636530346235366365396431
64623739373130623436356161666139656330646661396430633264393632663366353037643130
35373839373430643065616630613433646536356563353133633361623235623733313234306435
64356635343361633462376131636362386433373339383365313436333332613333316237323632
33633362376331323930376130393838633333316330363362396131306230643161373636303034
37303738306233363937316332313830396336323639333634666364633566386261373031383563
36633865643634363234613463636437306236376435613034623537356162353235396665636338
31613733363430313532643235343438393137313136653730643364623662336236323464656465
65636431633464613437396561643638346565313937303731633837623930333538383335633938
62666461323033303937653366646432623764653566626333333766656235633662623631636636
35626161653736303261303233643236393038303063386532643563663065303331616637386661
33326637393633616430643665623431616336336666383236326538383535633364613135653131
38383961383264313130383263613763326666663033626338313762376336353866646634323537
39393565643265633437396535643165626165646537373039613061613936356434366238636562
61393639316531316564646334663863383836656261623230646461323566316664653965336136
62353839363664396632306231363031303265343131343739633835353338386335343737326633
36656433616135653663353166636461623337653138613435646663663939323631373063373136
63396331313538636437383635643831643935303932313964336532643366623434316662376632
63666464333736333162373461333563393138366638643039393865613238616531356165346236
65313432383533353738396530356465386263313939393962333637306138653939646638353235
37393733333032623763333632353866633866613162663833346534666237383430663838383965
66663332616164353539323261383364363237383064306132633530326134383561346536346636
32393365316435626464386631663037663934313533663030313466323134336439303362626365
30613764346362326130353333353663316539306437376465306332353464343530663933363562
39646333323631353835336461326233623963353535316633353236353236636462313163633638
35366538366336663534353739353231306164626664383737333565666337636164386539316632
64323966336637626538303830323535373533306362636236303065663161353734653633393064
66353938306238646238313037323163343935643863653632336462363834326634363433383338
35646364353834376439633136313939393064633539643462623562333832303261386331636533
37373837396461373064353565353438633938616162363138323561343662383330346633323133
36626665343636343739353732366133313434623230353732323037633236303237656364323763
30363530306131303630386131623866323861633636313431376161336536373436656334303036
61316639666136313338396233326234386634343863633632626264363336376531363461626564
35336335396561626339616234373265663032353432363832306666353339376338396366383839
62633063326135323539653133626538613331613334353430623232376336633334666433316638
61326563366432333632666436363761376237636434356231613061626633303737626531626236
62373166363432616666616630616565373934356564363266396662323963636434313735626161
61373738623966363032313632376465356235363834633639663733653131636531363563326662
62663365323934363761653536356162336463646566393838346134356536303264323065396534
63346531303764613634646336313530326663373433396436663162343530306131386265303137
32333432383966363735343331646233613631373165346131323632366165346235656330323939
34393030313466666265346163323561353734613434386239333630623762616566616562316265
38633263323339396462336166646431363336616462366463383663313839613638383663303133
32333835623531366236643530623961656631336139313037353962323937666465343430666336
33383464363930663630333164636361326334396163376661666564663538623732663839613237
35623237613761356235383130633733333766333236363537383862306539373665383461386534
32646432363339306433646139393732366464336339346161323736363937383566656663356230
65316562383562366366653466646461613235353061623363386331636139386136306131633232
32326238353861613236373964383131363537653632663532376364336166303662663336623161
37623838616664376561663763393534323931343163376535396662626333383730363232653036
39626266623666346635373630343135333532353866363234396265356631333265663432326235
37346439613363313334633964386632336138316662616661356637363730306164646439643765
62343137663137633031316665363362643165643731326464323962616330383164353861366462
31663965626338636534356461366362333831396464376134613331393664306639386632396236
66633066663831646361333730356361646133383834376230356336613038303665323732663162
37643130313739306638636262656632353431316531336438363636363833626237346363326461
31636262396632666335303566633161333937626330373835613236656130383132663863636364
34383661353966346362386461303062303138626536323163376362326639356336396437333530
66623765313638616430383838396164336565646338636430363262396636663965383531383139
35356663363437383132333566336131666139643639663662633363616133323031353032663438
39393266633639306363313530643239303132303264323063306335346233363233373865653863
65396430346630626566383963356264313630623336316236393730343437656435656664663266
32643639363536396266626435373363303234623230383035326536633631633737653739366563
65653932663539353436366139313635663962663330343461353864323166323733366163653162
66353866376134633534323366656265633930356132316137616235343866653265666161363266
30386638343739353965643466613639303666316432323634383464633431363566333831643134
65363138313439366430613837396337323436636530313664303964353966306565663630323662
33643639623935336235373332633739306539656235323439343331376632373538613534386430
30633832656532623262326662376237393262333764623937343232383861636563633730393765
39663032373132323735633361343933333332623465343863636263363161303165656234313338
65383462626465376162306639626531366161396531643364656539366233306166386234313761
30633666303832636561323236373363373137353032613637353637386238353234646431333661
32313834666237626333626437663562646438363561393364373565313536363535323536363537
35633834616136656261643130656131306264333131326431626439343765393031313964616639
33643933653033336436616635346335383335333334343836343638613264396462633530623866
30303462653130353430663862623261343866383335343239393435633962383864396430313536
66643535303437383232323564326266356636376464623563636139633237313661356330633931
66376631373366613731633863666132626366393532666331343361323764626539666238656262
66356332383235353864303562356638636130343938383530376432663866316238333434616233
32316432333064663764363831343464326334353737346632383565643737366233396139333639
35656435346335323030636363356633633332376138653930613037313537373038353433363532
39346161336261353463656430663033623036396365346638323832313361633866363134396165
65356632366463393435386366643232383162623536653965643235323934633464373061333237
32636564386662626365613235333664323563633466383238343336343063376531396161343530
61306632646133626133343132666534666337336239306137663931623637643164326538646138
63313037336235316164316232636262316331356363356438653235346539643065636537366661
37313437386432316336663366633366666434346135356462623635313531333530653866663863
31646438316435373637303733646564316261336233623035353564363664303437373132353166
33646534663130356330663565656663333765653961663835623235633665623464353862616138
37343531366462616439333539306265626164636233616262616563386566396536386264343137
30396434303231366664656334656635616334633066323062313738363431646335643132626331
33663038316165626365346366363731323639653837616163653561623034393064303563353232
30613939353336396365613662393938663933363662656634663465303134393964623738633765
37633832626631363736383436666263356531366237356261666538303863343033356333656138
64366537363939346535313732643965623332396265386636353364316630333130643833383331
34643563386539383235386130323065353835376564613835313934333636316464636463376537
32363565333038643230656266393761313064616537393830343163643535646436616230626166
36373531646536363664663330353864636533656261353331316364633361633934326436323933
39636631623430313934393033373630656132623734363835353735353935393063356261323764
66346265376339623265376666343865343763393833323564643161613861303065346137653339
34326432383230656638303963373832316438666131623539613464636631653365353331346262
37626130343831636133646135323564306538353439636265313239326235343232633136383663
62306561616564623038393631373862346535366135633836353363323330346430613466393463
39313766613064306566316561303761626135613063326536363761626635646134303732356130
38333266363639636565393737323938663938633662653231366164316262666538356162323665
38383263366133326333636466343835373737613333623464383139343863336234373932393239
36653736393732353466656334613364626339356533343363353731353033363730376565353236
66343332306330303662373363326236393333663565383661643763363662396265313037643432
63343336623663326237326365333565346335346630356439303534363561626362363833313239
62366436313466633534343430306461313266376363336536666162306135363434643266373338
65323866323537636465306636646533316466303735386336663234386538303939343661653562
34353564313738643665636337336536343735336436626438653335376532343137613837356363
31353861363733373232363865323164663532646235623533336536333932363133613830373937
38616137646332303934303839633336313239653064626331383432633935353538636132633134
61393230663536633335393330386363333162636661373938343837323736663539393636366532
35623637623262373332373335303833373239323430393766633939633665643236623139363834
30636135303634643765393433393962303138666630343936653234333730336234356234396566
35346331336639333237323136616337623938666561343861393563393633313261633333333434
38633064633538396566373730636632346234653339303533343431643266373266633836633139
33313234366236626338636331346565336138313136623632343735363132623964353066346233
66363833383432316238353364363963323762666562303030663939303162656261663664616632
66396466643763393130313831313438356635346230646335306237363262366132323133646535
30313338653262636136393133306663653331333830626534356536303532633031356435663734
32383035643637313863653537656665366138333933333364646561353333653661306133646361
32326535393333383033313765383031353233323138386365623132646636383037633537386361
65306166613030353033666438343530333330306532323135306363653764613638383461633964
63666239366638663537643636373432303164623735626634383636643836343436346161393365
62336462636534383766656632653833333832393263316633356235373335643436363333393335
62643838303131643265613861373964653464623766363664383330343138653632396365633533
39383535616630663564326536623537323966616436353439343630363738626131326365656132
32383737303733623830353366383062313134396531303831323336326137396335353763353631
36663336353865303562316233643762643563386665393664623138643836633165

View File

@@ -13,7 +13,7 @@ proxmox_clone_node: "fantasyland"
# VM Configuration
vm_os_distribution: "ubuntu"
vm_os_version: "24.04"
vm_size: "medium"
vm_size: "small"
vm_storage: "general"
# Proxmox HA Configuration
@@ -22,12 +22,12 @@ proxmox_host_target: "pve02"
# Network Configuration
# IP address for the Traefik load balancer
ip_address: 10.1.71.80
vm_mac_address: 'BC:24:11:50:00:80'
ip_address: 10.1.71.24
#vm_mac_address: 'BC:24:11:50:00:80'
# Software Configuration
# Traefik will be installed and configured on this host
# VM Template Configuration
vm_clone_source: "{{ vm_os_distribution }}-{{ vm_os_version }}-{{ vm_size }}"
#vm_clone_source: "{{ vm_os_distribution }}-{{ vm_os_version }}-{{ vm_size }}"
hostname: "{{ inventory_hostname }}.{{ base_domain }}"

View File

@@ -25,6 +25,11 @@ prometheus_nodes:
hosts:
cinderella-castle:
load_balancers:
hosts:
lightning-lane:
ansible_host: 10.1.71.24
ansible_become: true
# node_explorer:
# hosts:
# cinderella-castle:
@@ -78,37 +83,37 @@ terraform_server:
hosts:
infra01:
hub_cluster:
hosts:
ocp-hub:
# hub_cluster:
# hosts:
# ocp-hub:
internal_cluster:
hosts:
int-master01:
int-master02:
int-master03:
# int-worker01:
int-worker02:
# internal_cluster:
# hosts:
# int-master01:
# int-master02:
# int-master03:
# # int-worker01:
# int-worker02:
talos_cluster:
hosts:
splash:
# talos_cluster:
# hosts:
# splash:
fastpass_control_plane:
hosts:
space-mountain:
big-thunder-mountain:
splash-mountain:
# fastpass_control_plane:
# hosts:
# space-mountain:
# big-thunder-mountain:
# splash-mountain:
fastpass_workers:
hosts:
haunted-mansion: # backstage
peter-pans-flight: # backstage
# fastpass_workers:
# hosts:
# haunted-mansion: # backstage
# peter-pans-flight: # backstage
fastpass:
children:
fastpass_control_plane:
fastpass_workers:
# fastpass:
# children:
# fastpass_control_plane:
# fastpass_workers:
# sql_servers:
# hosts:

View File

@@ -0,0 +1,177 @@
---
# ansible/playbooks/deploy-haproxy-cloudflare.yml
- name: Deploy HAProxy with Cloudflare DNS certificates
hosts: lightning-lane
become: true
vars:
# Certbot Cloudflare configuration
haproxy_certbot_enable: true
haproxy_certbot_challenge_method: "dns-cloudflare"
haproxy_certbot_email: "ryan@mk-labs.cloud"
haproxy_certbot_staging: false # Set to true for testing
haproxy_certbot_cloudflare_api_token: "{{ vault_cloudflare_api_token }}"
# Request wildcard certificate
haproxy_certbot_domains:
- domain: "*.local.mk-labs.cloud"
include_base: true # Also include local.mk-labs.cloud
# HAProxy Stats
haproxy_stats_password: "{{ vault_haproxy_stats_password }}"
# Frontend configuration
haproxy_frontends:
- name: https_front
bind: "*:443 ssl crt {{ haproxy_ssl_cert_dir }}/live crt {{ haproxy_ssl_default_crt }} alpn h2,http/1.1"
mode: http
options:
- "http-server-close"
- "forwardfor"
acls:
- "netbox hdr(host) -i fire-station.local.mk-labs.cloud"
- "wordpress hdr(host) -i be-our-guest.local.mk-labs.cloud"
- "plane hdr(host) -i people-mover.local.mk-labs.cloud"
- "minecraft hdr(host) -i arcade.local.mk-labs.cloud"
use_backends:
- "netbox_back if netbox"
- "wordpress_back if wordpress"
- "plane_back if plane"
- "minecraft_back if minecraft"
# Backend configuration
haproxy_backends:
- name: netbox_back
mode: http
balance: roundrobin
options:
- "httpchk GET /api/"
servers:
- name: fire-station
address: 10.1.71.102:8000
check: true
- name: wordpress_back
mode: http
balance: roundrobin
servers:
- name: be-our-guest
address: 10.1.71.101:80
check: true
- name: plane_back
mode: http
balance: roundrobin
servers:
- name: people-mover
address: 10.1.71.112:8080
check: true
- name: minecraft_back
mode: http
balance: roundrobin
servers:
- name: arcade
address: 10.1.71.111:25565
check: true
# TCP services
haproxy_tcp_services:
- name: postgres
frontend_port: 5432
backend_port: 5432
balance: leastconn
timeout_client: 1h
timeout_server: 1h
servers:
- name: netbox-db
address: 10.1.71.102
check: true
- name: ssh_jump
frontend_port: 2222
backend_port: 22
balance: source
servers:
- name: main-street-usa
address: 10.1.71.11
check: true
- name: tomorrowland
address: 10.1.71.12
check: true
- name: fantasyland
address: 10.1.71.13
check: true
- name: minecraft_java
frontend_port: 25565
backend_port: 25565
balance: roundrobin
servers:
- name: arcade
address: 10.1.71.111
check: true
# Firewall configuration
haproxy_firewall_allowed_ports:
- 80/tcp
- 443/tcp
- 2222/tcp
- 5432/tcp
- 8404/tcp
- 25565/tcp
pre_tasks:
- name: Ensure required groups exist
ansible.builtin.group:
name: "{{ item }}"
state: present
loop:
- haproxy
roles:
- haproxy
post_tasks:
- name: Wait for HAProxy to be ready
ansible.builtin.wait_for:
host: "{{ ansible_default_ipv4.address }}"
port: 443
timeout: 60
- name: Display deployment summary
ansible.builtin.debug:
msg: |
╔════════════════════════════════════════════════════════════╗
║ HAProxy Deployment Complete - lightning-lane ║
╚════════════════════════════════════════════════════════════╝
Stats Interface: http://{{ ansible_default_ipv4.address }}:8404/stats
Username: {{ haproxy_stats_username }}
HTTPS Services:
{% for frontend in haproxy_frontends %}
{% if frontend.acls is defined %}
{% for acl in frontend.acls %}
- {{ acl.split()[1] | regex_replace('hdr\\(host\\)', '') | regex_replace('-i', '') | trim }}
{% endfor %}
{% endif %}
{% endfor %}
TCP Services:
{% for tcp in haproxy_tcp_services %}
- {{ tcp.name }}: {{ ansible_default_ipv4.address }}:{{ tcp.frontend_port }}
{% endfor %}
Certificates:
{% for domain in haproxy_certbot_domains %}
- {{ domain.domain }}{% if domain.include_base | default(false) %} + base domain{% endif %}
{% endfor %}
Next steps:
1. Verify certificate: certbot certificates
2. Test renewal: certbot renew --dry-run
3. Check HAProxy stats interface
4. Test HTTPS endpoints

View File

@@ -0,0 +1,147 @@
---
# ansible/roles/haproxy/defaults/main.yml
# HAProxy version and installation
haproxy_version: "3.2"
haproxy_install_method: "package" # package or source
# System configuration
haproxy_user: haproxy
haproxy_group: haproxy
haproxy_chroot_dir: /var/lib/haproxy
haproxy_config_dir: /etc/haproxy
haproxy_log_dir: /var/log/haproxy
# Global settings
haproxy_global_maxconn: 4096
haproxy_global_log_facility: local0
haproxy_global_log_level: info
haproxy_global_nbthread: "{{ ansible_processor_vcpus }}"
# Default timeouts (milliseconds)
haproxy_timeout_connect: 5000
haproxy_timeout_client: 50000
haproxy_timeout_server: 50000
# Stats interface
haproxy_stats_enable: true
haproxy_stats_port: 8404
haproxy_stats_uri: /stats
haproxy_stats_refresh: 30s
haproxy_stats_username: admin
haproxy_stats_password: "{{ vault_haproxy_stats_password | default('changeme') }}"
# SSL/TLS configuration
haproxy_ssl_cert_dir: "{{ haproxy_config_dir }}/certs"
haproxy_ssl_default_crt: "{{ haproxy_ssl_cert_dir }}/default.pem"
haproxy_ssl_ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384"
haproxy_ssl_options: "ssl-min-ver TLSv1.2 no-tls-tickets"
# Health check defaults
haproxy_health_check_interval: 2000
haproxy_health_check_timeout: 1000
haproxy_health_check_rise: 2
haproxy_health_check_fall: 3
# Service discovery integration
haproxy_netbox_integration: false # true
haproxy_netbox_url: "http://fire-station.local.mk-labs.cloud:8000"
haproxy_netbox_token: "{{ vault_netbox_token | default('') }}"
# Frontends configuration
haproxy_frontends: []
# - name: http_front
# bind: "*:80"
# mode: http
# redirect: "scheme https code 301"
#
# - name: https_front
# bind: "*:443 ssl crt {{ haproxy_ssl_cert_dir }}"
# mode: http
# options:
# - "http-server-close"
# - "forwardfor"
# acls:
# - "netbox hdr(host) -i fire-station.local.mk-labs.cloud"
# - "wordpress hdr(host) -i be-our-guest.local.mk-labs.cloud"
# use_backends:
# - "netbox_back if netbox"
# - "wordpress_back if wordpress"
# Backends configuration
haproxy_backends: []
# - name: netbox_back
# mode: http
# balance: roundrobin
# options:
# - "httpchk GET /"
# servers:
# - name: fire-station
# address: 10.1.71.102:8000
# check: true
# TCP services configuration
haproxy_tcp_services: []
# - name: postgres
# frontend_port: 5432
# backend_port: 5432
# balance: leastconn
# servers:
# - name: netbox-db
# address: 10.1.71.102
# Firewall configuration
haproxy_configure_firewall: true
haproxy_firewall_allowed_ports:
- 80/tcp
- 443/tcp
- 8404/tcp
# Monitoring and observability
haproxy_prometheus_exporter: false
haproxy_prometheus_port: 9101
# Logging
haproxy_rsyslog_config: true
haproxy_log_rotation: true
# Certificate management - Certbot with Cloudflare DNS
haproxy_certbot_enable: true
haproxy_certbot_challenge_method: "dns-cloudflare" # or "webroot" for HTTP-01
haproxy_certbot_email: "ryan.blundon@protonmail.com"
haproxy_certbot_staging: false # Set to true for testing with Let's Encrypt staging
# Cloudflare DNS configuration
haproxy_certbot_cloudflare_api_token: "{{ vault_cloudflare_api_token }}"
haproxy_certbot_cloudflare_credentials_file: "/etc/letsencrypt/cloudflare.ini"
# Certificate domains - DNS-01 supports wildcards
haproxy_certbot_domains:
- domain: "*.mk-labs.cloud"
include_base: true
- domain: "*.local.mk-labs.cloud"
include_base: true # Also include local.mk-labs.cloud
- domain: "lightning-lane.local.mk-labs.cloud"
include_base: false
# Alternative: specific domains without wildcard
# haproxy_certbot_domains:
# - domain: "lightning-lane.local.mk-labs.cloud"
# - domain: "fire-station.local.mk-labs.cloud"
# - domain: "be-our-guest.local.mk-labs.cloud"
# Certbot renewal settings
haproxy_certbot_renewal_cron_minute: "0"
haproxy_certbot_renewal_cron_hour: "3" # 3 AM daily
haproxy_certbot_renewal_cron_day: "*"
haproxy_certbot_post_hook: "{{ haproxy_config_dir }}/certbot-post-hook.sh"
# Certificate storage
haproxy_certbot_cert_dir: "/etc/letsencrypt/live"
haproxy_certbot_archive_dir: "/etc/letsencrypt/archive"
# DNS propagation wait time (seconds)
haproxy_certbot_dns_propagation_seconds: 60
# Fallback to self-signed if Certbot fails
haproxy_certbot_fallback_selfsigned: true

View File

@@ -0,0 +1,26 @@
---
# ansible/roles/haproxy/handlers/main.yml
- name: Reload haproxy
ansible.builtin.systemd:
name: haproxy
state: reloaded
listen: reload haproxy
- name: Restart haproxy
ansible.builtin.systemd:
name: haproxy
state: restarted
daemon_reload: true
listen: restart haproxy
- name: Reload systemd
ansible.builtin.systemd:
daemon_reload: true
listen: reload systemd
- name: Restart rsyslog
ansible.builtin.systemd:
name: rsyslog
state: restarted
listen: restart rsyslog

View File

@@ -0,0 +1,202 @@
---
# ansible/roles/haproxy/tasks/certbot-cloudflare.yml
- name: Install Certbot and Cloudflare DNS plugin
ansible.builtin.package:
name:
- certbot
- python3-certbot-dns-cloudflare
state: present
- name: Create Let's Encrypt configuration directory
ansible.builtin.file:
path: /etc/letsencrypt
state: directory
owner: root
group: root
mode: '0755'
- name: Create Cloudflare credentials file
ansible.builtin.template:
src: cloudflare-credentials.ini.j2
dest: "{{ haproxy_certbot_cloudflare_credentials_file }}"
owner: root
group: root
mode: '0600'
no_log: true
- name: Create Certbot post-renewal hook script
ansible.builtin.template:
src: certbot-post-hook.sh.j2
dest: "{{ haproxy_certbot_post_hook }}"
owner: root
group: root
mode: '0755'
- name: Create Certbot renewal hooks directory
ansible.builtin.file:
path: /etc/letsencrypt/renewal-hooks/deploy
state: directory
mode: '0755'
- name: Link post-hook to renewal hooks directory
ansible.builtin.file:
src: "{{ haproxy_certbot_post_hook }}"
dest: /etc/letsencrypt/renewal-hooks/deploy/haproxy-reload.sh
state: link
force: true
- name: Check for existing certificates
ansible.builtin.stat:
path: "{{ haproxy_certbot_cert_dir }}/{{ item.domain | regex_replace('\\*\\.', '') }}"
register: existing_certs
loop: "{{ haproxy_certbot_domains }}"
loop_control:
label: "{{ item.domain }}"
- name: Build certificate request commands
ansible.builtin.set_fact:
certbot_commands: "{{ certbot_commands | default([]) + [command_item] }}"
vars:
cert_name: "{{ item.item.domain | regex_replace('\\*\\.', '') }}"
domain_list: >-
{{ [item.item.domain] +
(item.item.include_base | default(false) | ternary(
[item.item.domain | regex_replace('\\*\\.', '')],
[]
))
}}
command_item:
domain: "{{ item.item.domain }}"
cert_name: "{{ cert_name }}"
domains: "{{ domain_list }}"
exists: "{{ item.stat.exists }}"
loop: "{{ existing_certs.results }}"
loop_control:
label: "{{ item.item.domain }}"
- name: Display certificate request plan
ansible.builtin.debug:
msg: |
Will request certificates for:
{% for cmd in certbot_commands %}
- {{ cmd.cert_name }} ({{ cmd.domains | join(', ') }}) - {{ 'EXISTS' if cmd.exists else 'NEW' }}
{% endfor %}
- name: Request certificates from Let's Encrypt via Cloudflare DNS
ansible.builtin.command: >
certbot certonly
--non-interactive
--agree-tos
--email {{ haproxy_certbot_email }}
--dns-cloudflare
--dns-cloudflare-credentials {{ haproxy_certbot_cloudflare_credentials_file }}
--dns-cloudflare-propagation-seconds {{ haproxy_certbot_dns_propagation_seconds }}
--cert-name {{ item.cert_name }}
{% for domain in item.domains %}
--domain {{ domain }}
{% endfor %}
{% if haproxy_certbot_staging %}
--staging
{% endif %}
--deploy-hook {{ haproxy_certbot_post_hook }}
loop: "{{ certbot_commands }}"
loop_control:
label: "{{ item.cert_name }}"
when: not item.exists
register: certbot_result
failed_when:
- certbot_result.rc != 0
- "'Certificate not yet due for renewal' not in certbot_result.stdout"
- "'too many certificates already issued' not in certbot_result.stderr"
- name: Display certificate request results
ansible.builtin.debug:
msg: "Certificate for {{ item.item.cert_name }}: {{ 'SUCCESS' if item.rc == 0 else 'SKIPPED/FAILED' }}"
loop: "{{ certbot_result.results }}"
loop_control:
label: "{{ item.item.cert_name }}"
when: certbot_result.results is defined
- name: Run post-hook to combine certificates for HAProxy
ansible.builtin.command: "{{ haproxy_certbot_post_hook }}"
changed_when: true
when: certbot_result.changed
- name: Setup automatic certificate renewal via cron
ansible.builtin.cron:
name: "Certbot certificate renewal"
minute: "{{ haproxy_certbot_renewal_cron_minute }}"
hour: "{{ haproxy_certbot_renewal_cron_hour }}"
day: "{{ haproxy_certbot_renewal_cron_day }}"
job: "/usr/bin/certbot renew --quiet --deploy-hook {{ haproxy_certbot_post_hook }} 2>&1 | logger -t certbot"
user: root
state: present
- name: Create systemd timer for certificate renewal (alternative to cron)
when: ansible_service_mgr == "systemd"
block:
- name: Create certbot renewal service
ansible.builtin.copy:
content: |
[Unit]
Description=Certbot Renewal
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet --deploy-hook {{ haproxy_certbot_post_hook }}
StandardOutput=journal
StandardError=journal
dest: /etc/systemd/system/certbot-renewal.service
mode: '0644'
- name: Create certbot renewal timer
ansible.builtin.copy:
content: |
[Unit]
Description=Certbot Renewal Timer
[Timer]
OnCalendar=daily
RandomizedDelaySec=1h
Persistent=true
[Install]
WantedBy=timers.target
dest: /etc/systemd/system/certbot-renewal.timer
mode: '0644'
- name: Enable and start certbot renewal timer
ansible.builtin.systemd:
name: certbot-renewal.timer
enabled: true
state: started
daemon_reload: true
- name: Test certificate renewal (dry-run)
ansible.builtin.command: certbot renew --dry-run --dns-cloudflare --dns-cloudflare-credentials {{ haproxy_certbot_cloudflare_credentials_file }}
register: renewal_test
changed_when: false
failed_when: false
- name: Display renewal test results
ansible.builtin.debug:
msg: |
Certificate renewal dry-run: {{ 'SUCCESS ✓' if renewal_test.rc == 0 else 'FAILED ✗' }}
{% if renewal_test.rc == 0 %}
Your certificates will renew automatically.
{% else %}
Please check the output above for errors.
{% endif %}
- name: List all certificates
ansible.builtin.command: certbot certificates
register: cert_list
changed_when: false
- name: Display certificate information
ansible.builtin.debug:
msg: "{{ cert_list.stdout_lines }}"

View File

@@ -0,0 +1,78 @@
---
# ansible/roles/haproxy/tasks/certificates.yml
- name: Check if default certificate exists
ansible.builtin.stat:
path: "{{ haproxy_ssl_default_crt }}"
register: default_cert
- name: Generate self-signed certificate for development
when: not default_cert.stat.exists
block:
- name: Generate private key
openssl_privatekey:
path: "{{ haproxy_ssl_cert_dir }}/default.key"
size: 2048
mode: '0600'
owner: "{{ haproxy_user }}"
group: "{{ haproxy_group }}"
- name: Generate certificate signing request
openssl_csr:
path: "{{ haproxy_ssl_cert_dir }}/default.csr"
privatekey_path: "{{ haproxy_ssl_cert_dir }}/default.key"
common_name: "lightning-lane.local.mk-labs.cloud"
subject_alt_name:
- "DNS:lightning-lane.local.mk-labs.cloud"
- "DNS:*.local.mk-labs.cloud"
owner: "{{ haproxy_user }}"
group: "{{ haproxy_group }}"
- name: Generate self-signed certificate
openssl_certificate:
path: "{{ haproxy_ssl_cert_dir }}/default.crt"
privatekey_path: "{{ haproxy_ssl_cert_dir }}/default.key"
csr_path: "{{ haproxy_ssl_cert_dir }}/default.csr"
provider: selfsigned
selfsigned_not_after: "+3650d"
owner: "{{ haproxy_user }}"
group: "{{ haproxy_group }}"
- name: Combine certificate and key for HAProxy
ansible.builtin.shell: |
cat {{ haproxy_ssl_cert_dir }}/default.crt \
{{ haproxy_ssl_cert_dir }}/default.key \
> {{ haproxy_ssl_default_crt }}
args:
creates: "{{ haproxy_ssl_default_crt }}"
- name: Set permissions on combined certificate
ansible.builtin.file:
path: "{{ haproxy_ssl_default_crt }}"
owner: "{{ haproxy_user }}"
group: "{{ haproxy_group }}"
mode: '0600'
- name: Create certificate directory structure
ansible.builtin.file:
path: "{{ haproxy_ssl_cert_dir }}/{{ item }}"
state: directory
owner: "{{ haproxy_user }}"
group: "{{ haproxy_group }}"
mode: '0755'
loop:
- live
- archive
- name: Deploy additional certificates
when: haproxy_ssl_certificates is defined
block:
- name: Copy certificate files
ansible.builtin.copy:
src: "{{ item.src }}"
dest: "{{ haproxy_ssl_cert_dir }}/live/{{ item.name }}.pem"
owner: "{{ haproxy_user }}"
group: "{{ haproxy_group }}"
mode: '0600'
loop: "{{ haproxy_ssl_certificates }}"
notify: Reload haproxy

View File

@@ -0,0 +1,94 @@
---
# ansible/roles/haproxy/tasks/configure.yml
- name: Fetch services from NetBox
when: haproxy_netbox_integration
block:
- name: Query NetBox for service configurations
ansible.builtin.uri:
url: "{{ haproxy_netbox_url }}/api/ipam/services/"
method: GET
headers:
Authorization: "Token {{ haproxy_netbox_token }}"
Accept: "application/json"
return_content: true
register: netbox_services
changed_when: false
- name: Parse NetBox services
ansible.builtin.set_fact:
haproxy_frontends: "{{ haproxy_frontends | default([]) + netbox_parsed_frontends }}"
haproxy_backends: "{{ haproxy_backends | default([]) + netbox_parsed_backends }}"
vars:
netbox_parsed_frontends: "{{ netbox_services.json.results | map(attribute='custom_fields') | list }}"
netbox_parsed_backends: "{{ netbox_services.json.results | map(attribute='custom_fields') | list }}"
when: netbox_services.json.results is defined
- name: Generate HAProxy main configuration
ansible.builtin.template:
src: haproxy.cfg.j2
dest: "{{ haproxy_config_dir }}/haproxy.cfg"
owner: root
group: root
mode: '0644'
backup: true
validate: 'haproxy -c -f %s'
notify: reload haproxy
- name: Configure rsyslog for HAProxy
when: haproxy_rsyslog_config
block:
- name: Create rsyslog configuration for HAProxy
ansible.builtin.copy:
content: |
# HAProxy logging configuration
$ModLoad imudp
$UDPServerRun 514
# Create separate log files for HAProxy
local0.* {{ haproxy_log_dir }}/haproxy.log
local0.info {{ haproxy_log_dir }}/haproxy-info.log
local0.notice {{ haproxy_log_dir }}/haproxy-notice.log
local0.err {{ haproxy_log_dir }}/haproxy-error.log
# Stop processing HAProxy logs
& stop
dest: /etc/rsyslog.d/49-haproxy.conf
mode: '0644'
notify: restart rsyslog
- name: Configure logrotate for HAProxy
when: haproxy_log_rotation
ansible.builtin.template:
src: logrotate.j2
dest: /etc/logrotate.d/haproxy
mode: '0644'
- name: Create HAProxy systemd override directory
ansible.builtin.file:
path: /etc/systemd/system/haproxy.service.d
state: directory
mode: '0755'
- name: Configure HAProxy systemd service overrides
ansible.builtin.copy:
content: |
[Service]
# Increase file descriptor limits
LimitNOFILE=65536
# Runtime directory
RuntimeDirectory=haproxy
RuntimeDirectoryMode=0755
# Security hardening
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths={{ haproxy_log_dir }}
dest: /etc/systemd/system/haproxy.service.d/override.conf
mode: '0644'
notify:
- Reload systemd
- Restart haproxy

View File

@@ -0,0 +1,128 @@
---
# ansible/roles/haproxy/tasks/install.yml
- name: Install HAProxy repository (Ubuntu)
when: ansible_os_family == "Debian"
block:
- name: Add HAProxy PPA
ansible.builtin.apt_repository:
repo: "ppa:vbernat/haproxy-{{ haproxy_version }}"
state: present
update_cache: true
- name: Install HAProxy
ansible.builtin.apt:
name: haproxy
state: present
update_cache: true
- name: Install HAProxy (Fedora/RHEL)
when: ansible_os_family == "RedHat"
block:
- name: Install HAProxy
ansible.builtin.dnf:
name: haproxy
state: present
- name: Install additional packages
ansible.builtin.package:
name:
- rsyslog
- logrotate
- socat # For HAProxy socket communication
state: present
- name: Create HAProxy system user
ansible.builtin.user:
name: "{{ haproxy_user }}"
group: "{{ haproxy_group }}"
system: true
shell: /usr/sbin/nologin
home: "{{ haproxy_chroot_dir }}"
create_home: true
- name: Create required directories
ansible.builtin.file:
path: "{{ item }}"
state: directory
owner: "{{ haproxy_user }}"
group: "{{ haproxy_group }}"
mode: '0755'
loop:
- "{{ haproxy_config_dir }}"
- "{{ haproxy_ssl_cert_dir }}"
- "{{ haproxy_log_dir }}"
- "{{ haproxy_chroot_dir }}"
- /var/lib/haproxy/dev
- name: Create HAProxy socket directory
ansible.builtin.file:
path: /run/haproxy
state: directory
owner: "{{ haproxy_user }}"
group: "{{ haproxy_group }}"
mode: '0755'
- name: Configure firewall rules
when: haproxy_configure_firewall
block:
- name: Open HAProxy ports (UFW)
when: ansible_os_family == "Debian"
community.general.ufw:
rule: allow
port: "{{ item.split('/')[0] }}"
proto: "{{ item.split('/')[1] }}"
loop: "{{ haproxy_firewall_allowed_ports }}"
- name: Open HAProxy ports (firewalld)
when: ansible_os_family == "RedHat"
ansible.posix.firewalld:
port: "{{ item }}"
permanent: true
state: enabled
immediate: true
loop: "{{ haproxy_firewall_allowed_ports }}"
- name: Install Prometheus HAProxy exporter
when: haproxy_prometheus_exporter
block:
- name: Download HAProxy exporter
ansible.builtin.get_url:
url: "https://github.com/prometheus/haproxy_exporter/releases/download/v0.15.0/haproxy_exporter-0.15.0.linux-amd64.tar.gz"
dest: /tmp/haproxy_exporter.tar.gz
mode: '0644'
- name: Extract HAProxy exporter
ansible.builtin.unarchive:
src: /tmp/haproxy_exporter.tar.gz
dest: /usr/local/bin/
remote_src: true
extra_opts:
- --strip-components=1
- --wildcards
- '*/haproxy_exporter'
- name: Create HAProxy exporter systemd service
ansible.builtin.copy:
content: |
[Unit]
Description=HAProxy Exporter
After=network.target
[Service]
Type=simple
User={{ haproxy_user }}
ExecStart=/usr/local/bin/haproxy_exporter --haproxy.scrape-uri=unix:/run/haproxy/admin.sock
Restart=on-failure
[Install]
WantedBy=multi-user.target
dest: /etc/systemd/system/haproxy-exporter.service
mode: '0644'
- name: Enable and start HAProxy exporter
ansible.builtin.systemd:
name: haproxy-exporter
state: started
enabled: true
daemon_reload: true

View File

@@ -0,0 +1,40 @@
---
# ansible/roles/haproxy/tasks/main.yml
# - name: Include OS-specific variables
# include_vars: "{{ ansible_os_family }}.yml"
# tags: [haproxy, always]
- name: Include installation tasks
ansible.builtin.include_tasks: install.yml
tags: [haproxy, install]
- name: Include Certbot with Cloudflare DNS tasks
ansible.builtin.include_tasks: certbot-cloudflare.yml
when:
- haproxy_certbot_enable
- haproxy_certbot_challenge_method == "dns-cloudflare"
tags: [haproxy, certificates, certbot, cloudflare]
- name: Include fallback self-signed certificate tasks
ansible.builtin.include_tasks: certificates.yml
when:
- not haproxy_certbot_enable
- haproxy_certbot_fallback_selfsigned | default(false)
tags: [haproxy, certificates, selfsigned]
- name: Include configuration tasks
ansible.builtin.include_tasks: configure.yml
tags: [haproxy, configure]
- name: Include validation tasks
ansible.builtin.include_tasks: validate.yml
tags: [haproxy, validate]
- name: Ensure HAProxy is started and enabled
ansible.builtin.systemd:
name: haproxy
state: started
enabled: true
daemon_reload: true
tags: [haproxy, service]

View File

@@ -0,0 +1,47 @@
---
# ansible/roles/haproxy/tasks/validate.yml
- name: Validate HAProxy configuration syntax
command: haproxy -c -f {{ haproxy_config_dir }}/haproxy.cfg
register: haproxy_validation
changed_when: false
failed_when: haproxy_validation.rc != 0
- name: Display validation results
debug:
msg: "{{ haproxy_validation.stdout_lines }}"
when: haproxy_validation.stdout_lines is defined
- name: Check HAProxy service status
systemd:
name: haproxy
state: started
register: haproxy_status
changed_when: false
- name: Verify HAProxy is listening on configured ports
wait_for:
host: "{{ ansible_default_ipv4.address }}"
port: "{{ item }}"
timeout: 10
loop:
- 80
- 443
- "{{ haproxy_stats_port }}"
when: haproxy_status.status.ActiveState == "active"
- name: Test stats interface accessibility
uri:
url: "http://localhost:{{ haproxy_stats_port }}{{ haproxy_stats_uri }}"
user: "{{ haproxy_stats_username }}"
password: "{{ haproxy_stats_password }}"
force_basic_auth: true
status_code: 200
register: stats_test
changed_when: false
failed_when: false
- name: Display stats interface status
debug:
msg: "Stats interface is {{ 'accessible' if stats_test.status == 200 else 'not accessible' }}"

View File

@@ -0,0 +1,107 @@
#!/bin/bash
# {{ ansible_managed }}
# Certbot post-renewal hook for HAProxy
# Combines certificate and private key for HAProxy consumption
set -euo pipefail
# Configuration
LETSENCRYPT_LIVE="/etc/letsencrypt/live"
HAPROXY_CERT_DIR="{{ haproxy_ssl_cert_dir }}/live"
HAPROXY_USER="{{ haproxy_user }}"
HAPROXY_GROUP="{{ haproxy_group }}"
LOG_FILE="{{ haproxy_log_dir }}/certbot-hook.log"
# Ensure HAProxy cert directory exists
mkdir -p "$HAPROXY_CERT_DIR"
# Logging function
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}
log "Starting certificate deployment for HAProxy"
# Track if any certificates were updated
CERTS_UPDATED=false
# Process each certificate in Let's Encrypt live directory
for cert_dir in "$LETSENCRYPT_LIVE"/*; do
if [ ! -d "$cert_dir" ] || [ "$(basename "$cert_dir")" = "README" ]; then
continue
fi
CERT_NAME=$(basename "$cert_dir")
# Check if certificate files exist
if [ ! -f "$cert_dir/fullchain.pem" ] || [ ! -f "$cert_dir/privkey.pem" ]; then
log "WARNING: Missing certificate files for $CERT_NAME, skipping"
continue
fi
log "Processing certificate: $CERT_NAME"
# Create combined PEM file (fullchain + privkey)
# HAProxy requires the certificate chain and private key in a single file
COMBINED_PEM="$HAPROXY_CERT_DIR/${CERT_NAME}.pem"
# Combine certificates
cat "$cert_dir/fullchain.pem" "$cert_dir/privkey.pem" > "$COMBINED_PEM.tmp"
# Check if certificate actually changed
if [ -f "$COMBINED_PEM" ] && cmp -s "$COMBINED_PEM" "$COMBINED_PEM.tmp"; then
log "Certificate $CERT_NAME unchanged, skipping"
rm "$COMBINED_PEM.tmp"
continue
fi
# Move new certificate into place
mv "$COMBINED_PEM.tmp" "$COMBINED_PEM"
# Set proper permissions
chown "$HAPROXY_USER:$HAPROXY_GROUP" "$COMBINED_PEM"
chmod 600 "$COMBINED_PEM"
log "Created/Updated: $COMBINED_PEM"
CERTS_UPDATED=true
done
# Create/update default certificate symlink
# Use the first wildcard cert or the first available cert as default
DEFAULT_CERT="{{ haproxy_ssl_default_crt }}"
WILDCARD_CERT="$HAPROXY_CERT_DIR/local.mk-labs.cloud.pem"
if [ -f "$WILDCARD_CERT" ]; then
ln -sf "$WILDCARD_CERT" "$DEFAULT_CERT"
log "Updated default certificate symlink to wildcard cert"
elif [ -n "$(ls -A "$HAPROXY_CERT_DIR" 2>/dev/null)" ]; then
FIRST_CERT=$(ls "$HAPROXY_CERT_DIR"/*.pem 2>/dev/null | head -n1)
ln -sf "$FIRST_CERT" "$DEFAULT_CERT"
log "Updated default certificate symlink to $FIRST_CERT"
fi
# Only reload HAProxy if certificates were actually updated
if [ "$CERTS_UPDATED" = true ]; then
log "Certificates updated, validating HAProxy configuration"
# Validate HAProxy configuration
if haproxy -c -f {{ haproxy_config_dir }}/haproxy.cfg >/dev/null 2>&1; then
log "HAProxy configuration valid, reloading service"
if systemctl reload haproxy; then
log "HAProxy reloaded successfully"
else
log "ERROR: Failed to reload HAProxy"
exit 1
fi
else
log "ERROR: HAProxy configuration validation failed"
haproxy -c -f {{ haproxy_config_dir }}/haproxy.cfg 2>&1 | tee -a "$LOG_FILE"
exit 1
fi
else
log "No certificates were updated, skipping HAProxy reload"
fi
log "Certificate deployment complete"
exit 0

View File

@@ -0,0 +1,12 @@
# {{ ansible_managed }}
# Cloudflare API credentials for Certbot DNS-01 challenge
# This file contains sensitive information and should be protected
# Cloudflare API Token (RECOMMENDED)
# Create at: https://dash.cloudflare.com/profile/api-tokens
# Required permissions: Zone:DNS:Edit for specific zone
dns_cloudflare_api_token = {{ haproxy_certbot_cloudflare_api_token }}
# Alternative: Global API Key (NOT RECOMMENDED - too permissive)
# dns_cloudflare_email = your-email@example.com
# dns_cloudflare_api_key = your-global-api-key

View File

@@ -0,0 +1,188 @@
{# ansible/roles/haproxy/templates/haproxy.cfg.j2 #}
#---------------------------------------------------------------------
# HAProxy Configuration for {{ inventory_hostname }}
# Generated by Ansible - DO NOT EDIT MANUALLY
# Magic Kingdom Labs - lightning-lane load balancer
#---------------------------------------------------------------------
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
log 127.0.0.1 {{ haproxy_global_log_facility }} {{ haproxy_global_log_level }}
chroot {{ haproxy_chroot_dir }}
pidfile /var/run/haproxy.pid
maxconn {{ haproxy_global_maxconn }}
user {{ haproxy_user }}
group {{ haproxy_group }}
daemon
nbthread {{ haproxy_global_nbthread }}
# Runtime socket for management
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
# SSL/TLS configuration
ssl-default-bind-ciphers {{ haproxy_ssl_ciphers }}
ssl-default-bind-options {{ haproxy_ssl_options }}
ssl-default-server-ciphers {{ haproxy_ssl_ciphers }}
ssl-default-server-options {{ haproxy_ssl_options }}
# Performance tuning
tune.ssl.default-dh-param 2048
tune.ssl.cachesize 100000
tune.ssl.lifetime 600
#---------------------------------------------------------------------
# Common defaults
#---------------------------------------------------------------------
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option redispatch
retries 3
timeout connect {{ haproxy_timeout_connect }}
timeout client {{ haproxy_timeout_client }}
timeout server {{ haproxy_timeout_server }}
timeout http-request 10s
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
# Error pages
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
#---------------------------------------------------------------------
# Stats interface
#---------------------------------------------------------------------
{% if haproxy_stats_enable %}
listen stats
bind *:{{ haproxy_stats_port }}
mode http
stats enable
stats uri {{ haproxy_stats_uri }}
stats refresh {{ haproxy_stats_refresh }}
stats realm Magic\ Kingdom\ Labs\ -\ HAProxy\ Statistics
stats auth {{ haproxy_stats_username }}:{{ haproxy_stats_password }}
stats admin if TRUE
{% endif %}
#---------------------------------------------------------------------
# HTTP Redirect Frontend (HTTP -> HTTPS)
#---------------------------------------------------------------------
frontend http_front
bind *:80
mode http
# Redirect all HTTP traffic to HTTPS
redirect scheme https code 301
#---------------------------------------------------------------------
# HTTPS Frontend with SNI
#---------------------------------------------------------------------
frontend https_front
bind *:443 ssl crt {{ haproxy_ssl_cert_dir }}/live crt {{ haproxy_ssl_default_crt }} alpn h2,http/1.1
mode http
# Security headers
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
http-response set-header X-Frame-Options "SAMEORIGIN"
http-response set-header X-Content-Type-Options "nosniff"
http-response set-header X-XSS-Protection "1; mode=block"
# Logging
option httplog
option forwardfor
{% if haproxy_frontends is defined and haproxy_frontends | length > 0 %}
{% for frontend in haproxy_frontends %}
{% if frontend.acls is defined %}
# ACLs for {{ frontend.name }}
{% for acl in frontend.acls %}
acl {{ acl }}
{% endfor %}
{% endif %}
{% endfor %}
{% for frontend in haproxy_frontends %}
{% if frontend.use_backends is defined %}
# Backend routing for {{ frontend.name }}
{% for use_backend in frontend.use_backends %}
use_backend {{ use_backend }}
{% endfor %}
{% endif %}
{% endfor %}
{% endif %}
# Default backend
default_backend no_match_back
#---------------------------------------------------------------------
# Backends
#---------------------------------------------------------------------
{% for backend in haproxy_backends %}
backend {{ backend.name }}
mode {{ backend.mode | default('http') }}
balance {{ backend.balance | default('roundrobin') }}
{% if backend.options is defined %}
{% for option in backend.options %}
option {{ option }}
{% endfor %}
{% endif %}
{% if backend.http_check is defined %}
option httpchk {{ backend.http_check }}
{% endif %}
{% if backend.servers is defined %}
{% for server in backend.servers %}
server {{ server.name }} {{ server.address }}{% if server.check | default(false) %} check{% endif %}{% if server.backup | default(false) %} backup{% endif %}{% if server.weight is defined %} weight {{ server.weight }}{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
# Default backend for unmatched requests
backend no_match_back
mode http
http-request deny deny_status 404
#---------------------------------------------------------------------
# TCP Services
#---------------------------------------------------------------------
{% for tcp_service in haproxy_tcp_services %}
# {{ tcp_service.name | upper }} Service (TCP)
frontend {{ tcp_service.name }}_front
bind *:{{ tcp_service.frontend_port }}
mode tcp
option tcplog
{% if tcp_service.timeout_client is defined %}
timeout client {{ tcp_service.timeout_client }}
{% endif %}
default_backend {{ tcp_service.name }}_back
backend {{ tcp_service.name }}_back
mode tcp
balance {{ tcp_service.balance | default('roundrobin') }}
{% if tcp_service.timeout_server is defined %}
timeout server {{ tcp_service.timeout_server }}
{% endif %}
{% if tcp_service.timeout_connect is defined %}
timeout connect {{ tcp_service.timeout_connect }}
{% endif %}
{% if tcp_service.servers is defined %}
{% for server in tcp_service.servers %}
server {{ server.name }} {{ server.address }}:{{ tcp_service.backend_port }}{% if server.check | default(true) %} check{% endif %}
{% endfor %}
{% endif %}
{% endfor %}

View File

@@ -0,0 +1,14 @@
{# ansible/roles/haproxy/templates/logrotate.j2 #}
{{ haproxy_log_dir }}/*.log {
daily
rotate 14
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
/bin/kill -HUP `cat /var/run/rsyslog.pid 2> /dev/null` 2> /dev/null || true
/bin/kill -HUP `cat /var/run/haproxy.pid 2> /dev/null` 2> /dev/null || true
endscript
}