From 307413f3f21694cbafa60d7cf027d72cdbd6c1a1 Mon Sep 17 00:00:00 2001 From: Ryan Blundon Date: Sun, 22 Mar 2026 18:15:55 -0500 Subject: [PATCH] Ansible deployed via boilerplates and playbooks --- ansible/group_vars/all/vault | 467 ++++++++++-------- ansible/inventory.yml | 21 +- ansible/playbooks/day1_deploy_semaphore.yml | 23 + .../roles/semaphore/defaults/main.yml | 4 + .../roles/semaphore/handlers/main.yml | 7 + .../playbooks/roles/semaphore/tasks/main.yml | 212 ++++++++ .../roles/semaphore/templates/env.j2 | 3 + boilerplates/semaphore/.env | 3 + boilerplates/semaphore/compose.yaml | 44 ++ boilerplates/semaphore/project-config.json | 107 ++++ boilerplates/traefik/dynamic/semaphore.yml | 17 + docs/{decisions => }/PROJECT_TASKS.md | 88 ++-- .../hosts/tfvars/guest-relations.tfvars | 4 +- .../proxmox/hosts/tfvars/imagineering.tfvars | 24 + .../hosts/tfvars/lightning-lane.tfvars | 4 +- .../proxmox/hosts/tfvars/turnstile.tfvars | 6 +- 16 files changed, 760 insertions(+), 274 deletions(-) create mode 100644 ansible/playbooks/day1_deploy_semaphore.yml create mode 100644 ansible/playbooks/roles/semaphore/defaults/main.yml create mode 100644 ansible/playbooks/roles/semaphore/handlers/main.yml create mode 100644 ansible/playbooks/roles/semaphore/tasks/main.yml create mode 100644 ansible/playbooks/roles/semaphore/templates/env.j2 create mode 100644 boilerplates/semaphore/.env create mode 100644 boilerplates/semaphore/compose.yaml create mode 100644 boilerplates/semaphore/project-config.json create mode 100644 boilerplates/traefik/dynamic/semaphore.yml rename docs/{decisions => }/PROJECT_TASKS.md (58%) create mode 100644 terraform/proxmox/hosts/tfvars/imagineering.tfvars diff --git a/ansible/group_vars/all/vault b/ansible/group_vars/all/vault index 15c94ca..a485a5d 100644 --- a/ansible/group_vars/all/vault +++ b/ansible/group_vars/all/vault @@ -1,217 +1,252 @@ $ANSIBLE_VAULT;1.1;AES256 -30386133633263613032383565326536626539353036313638383635623737356636643565366566 -3563653933613063333537636166613661666663646234330a643731336366306564626135626165 -38386663353234643066376365653862396462393063396633613436356566616338353339626165 -3131346263633531660a346634623165323136663039313565336661393861373930633234336336 -62633932663730646435343738353463373939363665303662653865386432653632666562353439 -38356661316534343263613561633362326564626362623763643663363736303832326161356339 -65366530386165383635303365613933623062623937333434303335363830313538336636343937 -66316264363063363036656532376461633831366361396232326264666361386266643837386666 -65666566636638316133613464613839306161636665356266346665336139616664356335343434 -37613039346437633934656432643234663564616365653633323734666537656666306235633461 -39316137333033363833626363386231626138613161383132386438613239346430393464633165 -32393864643538323830303162363765386662303661343737376462616532346464333533633231 -65643334666665353533643564656534373039323638393339386466316661646438626463643538 -34396535343966326533333133353430393766633065303961396664336165353962613432376133 -38616363396664383364623536373363353430323261303639316466393139333332366431666638 -34626233343366366563373030356538636238343938656463643864653566353466643437613739 -66313935613235353239306566303265316338386662653634633564663137353539663866383362 -38663335643636613336353030626563376638393234326536656562323164646465356162393233 -64343834633961613036343330373436316664316536343063333964623433666336303237363139 -37326631666661623139376164666430633664343761366463383366346437376166633630306631 -66303964373336613930663730336233383132393138343637636130306530656537363836626266 -37383135613865363634623436323339336161343536393936653039326631336366363165303837 -39343365373338373961623561366362653632646131386661613662386336326664313737326463 -63636665356464656533613366393939393334396339303062643133653434376431343237633763 -63663939363562373533386233326265393161653762363861393065653637373463366664356338 -38626536316262623035303863333532373938396266646165313533316434396437666138363831 -38396564376332343264343365336461633662326531356531643064306632306166383462666466 -38343566623330366262333637626261626231396163636566326136303062623266623534343939 -39343433626635616666303638646431616434363665346465646361353361353239643663303663 -36343731343561626136343432363639373831346331366163653166303432323761616165653838 -30636332343361326461656231663433373836303666316261623430333661343335656437393136 -62303166626331363434383939346166393161336165346661633032363436393735613461376234 -66643534353066396262356233373462373362623336343834613437636332343764393439653162 -32353366313534373265336362623165383730356161316238336532633533646330336435326534 -61643466643835623733303538316166646233643136653664653530376664333464393863366365 -63613738393732393739393762613638383239303537353236636463663033396530376465333932 -37326135336238396631333930373561646438313430323733353638356336636338656462613139 -36373432633439613931656562316336653965313066386332643432653435643034376466343031 -39633136656433336233393730356263376538656130353762303034336339356633656464393837 -37623233613932383536623536653435396661313336326331653064616635316238373136623533 -39653763393739373234346136353861383938353232336366336165333139323435636333656335 -65373631396438633936643865323665653465666434373166363863626534323566663663323561 -30353238636437653635386363363263376330323732613630613266343530393734383565643435 -62356133633662393165313766323732386231333737613236373533383932623634336435363235 -62353964636266336562353736386665646539323564633666316265313438326333653632313564 -36356334386132393562663566386365623765363633313937333062393238393735383731653165 -61646364633537363065366633646165643930353532633433656564333336376335353864623766 -30316536613635373733303163326662363435336165346134303036383161396366636135623562 -31393036323339373865633163643330393731386433613930633866393731373133383835346236 -62356363663062373938636532343239366438396337313632616636333961306234663830313866 -62646337353037666564653336376138326439633533396531393936313030333435383630316631 -35353634663131343235616635386138306435303432653363363930656136356361663136376131 -33373434616433366436326365616163313563343664623734306564623162623266326537636165 -31633336366438343363393032323838383237323664653038376362643565653361646466623438 -62323833386331323264616633653836343764663662646166383163653234333266353531343137 -39613962316335326435356632626430363065316439623861303930643462666662663839643263 -36666233373034363262656138626662383532393733396432363964653839303463376561306433 -35643036633731613565323439643637336566396632663335393036663432653664333232346338 -36343338333236663764643136373164373931653630626639306663333562323231643630343539 -37303965393537636130356437393164366435633734613037306664346464663935346165373461 -35313330316232333664356162383235653135623361386363643235366134373162633739393531 -32613134633331376236373636636639333331353037343134346232636432306230346139343631 -37613431616565363735656166333437343433306535613732653866653635633432353166313834 -32623133363664653131636466343361616130353635303663663837396664626338393239343938 -64383534316265623836316162383164636636306631373739313263653664306437313932316166 -62363936613230316638643762366231653931643461323539613964346138366539303865303334 -64393238306439616161316539346632626262653734383239343135323732653731333763656634 -34306661613065633137643966333334666531653862623933383937646136343339323866383361 -35366637373930613165646537653231343266613338373363303334316136633565383732373865 -39373636373635626231666130343335323265626632303239393334643963616666343930323461 -62393937643533376230313937663032326664636532616333623763326461363638303930666234 -31663362393333356565343230633239646130356530623137333332383332316261646531633336 -35393038386332353230633635353465616630306465613766636366613833376661633961623733 -32316134323062366436363661343931306135316631666339313439653035613239383265386438 -33363864366330626264643731663439303662646562396431373231353138363330663238313562 -35663330303338633234653736386364346135616536613939366330343838616330613162303565 -61356666376534636465323266396162383538636230616337656464343339353732386665393261 -35303834653666616530393730626237386164343835613538333230636163653935353537623931 -39613062323337353133653932326633633833396639633239346330613934626164333336353730 -39613639386161393436356162633334643663623461323932633662336236363334373935613164 -35313832653033356634316663396533386133353663383163333934376633393033613037353439 -64643765366136643166343563646232386566636635363766616339386530346134323366666438 -62623139663632373534353731326636386138393936316266393634383234613063633036366663 -63346230373134626362323438656535393434666638306136356639303931313163613963623137 -34366332646135633133316638323434653033633964356430626564666130633633613165373762 -39613337663634373433633637653534643164636330396630313861316563663963363238333531 -61613432373366396637643239613935636436353433323132663165633934353063623830363262 -37613733613561623165383734313037303730346237626163616535313934616139373431613034 -31333239653632643163366562373164386366343464393138303364343735643331633538373334 -36343930663334366231363563316531313866616232643664633533343739306462323661313464 -30313533356333333131656366643161373134613164303831636363306435336263363733303535 -33383730626337343963323663313432646437323237363035376633613361313762356137636336 -63383132363566303930306332363563303362333232313462326434643361643738373938663732 -66663438666264383038346563306365363730323236613037376566303430353330613866646338 -32386430636339663863623439323831656565373735666130616439316137373632326364613538 -31623037386464313830336638646531633031623666313965323266373337643433643739643638 -31663432653263636266666161636134643865383466366163303230653635383266346163643335 -30333365616337323163363430323661383464613135376661623662346665623135373430333362 -31346632333835653364633431616439633930303937643837633937663766656461326536613931 -35323964393030363666353836316436343533393030653433353162366463326635396436363631 -33333238646131343635313234353939393766656162313933353038313961343561653932353037 -61356162633362386530376464663038343263383631343730343937326334333964623339316334 -36323330333237643231646666626635646365383337323361336563663264643161643165363830 -37323736353566316634396662663032633438386632333764663534306662383530316139393537 -36633432613635346633656336626238346665646566313435393261333632336661383536656265 -36326231626432656233363866646539363538393162623361333238396234393266653631353236 -39383461326132663566306262623934313437663036386233316635343737346637623639323535 -64326361313034376636366335383963643833353231353835303237343834303061343162363632 -63393836363762643136666433353739393763663431656366336664383531323936323162623837 -35323361623666356461623164373531363665343630316662343266323933333463653834336566 -65333234363235333838316662383738333238363064373361333834316332636438613431363538 -38333435643136353861666634373066346139336433303962313438613038326361653864343932 -33396138663532646165653361653333393734626662343562666438363338383135323339386331 -34616338346639376431303932333836363863343730383066383561393661626137343230363163 -31663737333936396333636536643736356232666465373436306232323733353865393630303861 -31356164643631643635323530633936323735643437613737383231326532373233396334616366 -32663832626631636262326461663436353231366230313365353735363736626539643262393862 -36636437663338356137303165613461663062646134303062616265613033363366303437616334 -33353239303133613464376363383132373339306634313033663431636631393361643362343230 -33353031393233363736313938643564376338303364343437656264633065356438386539633761 -33346131303461616437303731373166303538323136373939366362616434393634383637353563 -30303961316630623939663862623361386361666435303931626237393930313833333239393939 -31376235346461353661363232616264656561333339633062623438613934313837653939643665 -33653861373732393832343736646364343831323938386432643534313938393235323533633465 -66623434613134303036636436383638666137623532306139346666623764623566393436333661 -36336136656134316561666539323237646362616436346464656264666331613730623734393030 -63626130303235633835633262373633363735346165303262306539663339663163343365353730 -39386437623030643532306337373330613839393631653232666661613066393439646664306431 -33616265356361613138333635613536336639326661653434353031323265636438343466353366 -31666237646265373961663764313236663432373834616136363135353366666534336631636431 -30353033393432366130313936363565323161316639343135613030373039383933376237303733 -64396661376463626134333365623033306235353533303336643366366633306564626431346531 -39393735363961356163666465396134653639626665353861626531333464373365653539303339 -31643834373161373665383366336139313431366163343363626263333363626139646238313035 -66343463336336376139333663303332626233356337653361616437363736313137303162666133 -61656530646533353763316562363538333435636366653137303333666463646430333265626334 -30313062393936393032323466396232643734383631656631393931393233346539373435323935 -38303739353535656661333037616639313965393733316339316130626136383132323437373836 -37356539663037646335376639303837393433613238636136633762616362366538383337343138 -30613337653631303938363430326566613536653839363362633631306361386530646362343030 -65663637306663383731646566626462376631303137383839363962376435623861616463623035 -30353635663633653462373664326130396432393238663938393037383136303662366262376166 -63613334653934656263396562643032646630333536633861336337306236313663653932646232 -62346264393932323532373865643966393031303731663033383738393466366632373464376131 -35336265626639336633323531636563376335386632376265333431363932633961326536336331 -64656161393130613134646664656437383030613437646438383835663063313565613932383231 -30626334313332363466333935343064613836623766353130336662383431623139333264393431 -38343565613639636236393730643961623432316531663361383832313166396561393434356131 -35366436616530313265346165653830323463323963663637366566613664666362333462356262 -32646237663465306365313130386462356530343737306337623135303166373963613863326263 -64323832663366346363326161313331316439313633643066326166626639373962393139383432 -33643533666531666539663638613732346134633765333031626362336366666666633135313031 -65633264396532363462373339366463383564646137663864386230343661633866353431623632 -34376638343837306331356463626663376462316132396164643265346334346463393933393734 -33313039333036616562643064396433666464326536393230393364343539306630323833653730 -63626566366436626661656436613737376231346631646639326534643537636136616434316232 -36306131636138663630646138326463623936623532303839623165623137363732343363383930 -66333736336563616462346533393837396637663937376631346431373533316561356664383263 -61663635663131666436373539646166373934333863323338626238633635396362663038623639 -30396165353437663130613537313464333030353836346632313232353837626231303835666266 -32633766323365303564313436346561626165386165623830393164333038306433316563323236 -34343435306236386532346235643961343538383435333430366433346163353862366161613464 -30316634313933613061636532353432626539316134636330623362613534376239643133363136 -39613931303731333633646436623438363362386163643236613963313131383466306461366436 -32353265643533636238646431353466306530303238323131653336396361303262356262613230 -35353739653530646231313062643235623230363465333763333966356534373565326334306336 -30336433363036626566613634303162376264333838653932396561383438316466383966343663 -31626331623332316139376361366231343334356630653236333135626463336664323637306638 -37303134666232303966613638616361613961356365613538323164343337386261643133393634 -31306565373639323031346236633837306132373264643462613433393961303931376538356339 -38633066313833383664393036333939333066633463333065396633313936306131366364303135 -31613761616131616362633639363764376464646266323530616265363339363036653662643439 -31313536646333393639346433336562643938646164636662316132326436616135303432386334 -65663062653931643663636666313835646138323432373138353939613330613461643133613138 -66636361643533386630316133356331623466663636333961633438613233353036666635376534 -35383365376265383939303636316265663630333935623131303738376631656537656138343765 -36643431623939633632323535363837363331323331393035366664316232343861626665633061 -34346434666638393934643162653733323935646262396661363966643062346562613336333061 -38363336366339633661666165383436663031306631643831643463663937653031393061306438 -63656338323363336332353232373966363436646538343562393932653539316565656163386634 -35306265393662326361393166373935356633323638663465616233376534646131353132663866 -38346163613131326239636365343937653833356138393838316137313063653238376631346461 -32323331626365323130613866653465353565343863636630366465383962623238636434663565 -64343762623530623365383739326562616632626166613635383937343839626666306135333934 -38336461373730633233373131323365613139616439636365383762663237383631353165336232 -61613464386630396437393162653530396139636632393336623562303536353233633034366365 -31396139646334376631316265393663316537643737383630643262613036326137366463623161 -30346361383132373336616132383665333265363231303334623661336537343837656331613561 -32343135383635356463663065346561303034663262643735646664303536363833383630623461 -37616336386432313535373233386433663363623761313331633438363563396563626631336662 -38653235633838613630623438373661333563623436383833333235326334386163663037386636 -33303631616135396130663735353333346564656537393937613638616239663161313962613631 -38386537653466353966346430633361303136643836326332633631336232646265613034326161 -65633033393337363336326633306262316636663461346162633234376232646563363032343632 -39643062313532646633343133313330316537343936646561613430303034303765633565396132 -37636165373335303133316233363132303339626635663461366263366162643736616533313338 -31353433363937343465346530306630393236636138643231393761623661326336356263306634 -36643234326538316432363864666138643139313334393265623761626162306632386135336161 -34326266306565343731626161643937663665366537643536636135613532643862353633333836 -64356337313064663339333163613862393761356339633033346338353865303038323833373461 -31346364663662316134383061313930323033356538626630373761613737343133303337613036 -37373261303066313035663139653237336236643036323732313763343866393736383937363733 -30393135653662666630353666316532303538366138386264663161656362633135343333613134 -62633139613130666566383361366637633632663166643336303730616237626430623863363963 -62316366633130343061366636393037323433643739646331306539376564666364383934383935 -63376633343364326430373130316264393866373438653964373663653737633533393139363564 -39336635386433343766353166323531633731616333666463323538393135636538383230633939 -63363061623432346437303565626637326561306162613830363835373830383631636338376538 -33343931353631393538306138393039626635666366363836333438663333323636623037303331 -31663237343965663364643139306632666166616138316363316334613134343864316335383631 -33323331336462656566613039313631643137363336643833646637383430363863373633633738 -63666336643938663064613538373434636234373935383736373739363430343765393463626231 -31643131636633386135366563316232343132376662643364626537656333643736626530653036 -37653636646534353634633734373463313031626363376538316634383863393035353835643836 -63353036633933323932646135396337393735383931373638643064626334366139623133386662 -35626464653162396132 +63636261313935343763663833386261356237343435326535383634373830393664383632656231 +6266353261613865333336383335316136336266383934300a306634626139626263623933363335 +36366539373734373936626463333534333139303664303662333364363232313834313635346532 +6434383839336566310a623131656336393739376137366564316461623737623835373033393864 +65303139643034633039306335633530383831363538326435336338633430323038626665356439 +30333061373437323937343335656363396639393736336237663061353362613432643563343261 +36343734636136626337313461383938613331656634663764353838396532613461616636653361 +61633735346331633764303339653566343132326537656233366637323238366234343232363336 +66313734646232616332326634396233373831303162343964633139366564663062333565343736 +38636238643636616238643037366537353831333033626562363164363334626335613832353035 +38616361346438656535316566316632653239373665646136326130363538313836653061363736 +37653062343039353931386132616330313864366364396461373936353131393764393137323362 +36326635326261353263663435396566643063383238373362393831636666333461303031623264 +61653863666262333862323336663064376535643735663131386162376561363037316361663239 +64316664363666323962343033353834326362313864353665613031343231656461353330613438 +64366335333961356363663934636534303361343864363639396364653234663862643830636439 +36666330326638353163383038306461326534613836326235366162633965636537393265646366 +66393537366661666166396165373636633534366134373632306637653533613761383664383238 +31616661333063303061623864373837383235623065373431313064396165386665363431393330 +33366665363062616463623664656362386238653435613037376362303938663036373864343036 +66313835323635323865613265313133383235643161336637646265316634383361376464633162 +63373236373238626333376164616333303664636363303063666330623666663765646438366461 +37363362643263366361613334393866356662323439313861373434313864333261636434333166 +31643832653463613765333162373635333463366365306463323364353965336561363363643737 +64643535313065353036386638636134643037626538353332376136393430326338383233373864 +37336435626536303030323164316432656533343430336665363633396439623636653864396638 +30336564313230373161376435393265333637333039663939653438386133663238633463663762 +63636362666266376330383739356138643334636263353137613065373034383463386463373231 +34393863626532313132333333653963613532313035376365613635353831666135323164653365 +35633665396666613166333561376265646533613262353865623665626565353061373764643963 +31393737623537636538306365356334353562383334623033623666363162636230383630643862 +37633038383962343337373630363162346230373835623237393136323566653733613465343866 +62643436346530346639376432316563656631306634643830373634623734656333666632646530 +66633034646335343031313662653439303162633533363164666530386632656235363835316431 +32313033656561333762353136656464613365666263373565383336646463323630623738666563 +39363931373964313732306535616139623637353165363330663566396232646336303039623066 +39346133326437333664366561316466306336333532363164373839336535646265613633636438 +64366465346536613862636136363634353831353439353833393339343032626565373466623835 +39383862306430353131323438656437383332363037393765626561393238313331333237336239 +39623262613862333038393338666237643830326432656266336235326237396561373035656563 +64613632393665653866353037396330346161386133643665336233616330393237643836363737 +65396638646431326134623961316564313730353637653138646134306565326332346532363836 +35663035346238383963376634393062663761653035636639653632643466346266623965303865 +36393865326362316434616166393835643136663565373231626437333334336464343661363765 +38376538616138626261313935333231376566306262613034323535383139623162353837356334 +38666637613466623930306535313439373965653235343830336237306366303161336666376566 +31376637393033363636663330613861633862636664653933623039376633323363636330633365 +36386637376336336631376437623233643537383333623334303166626139363936376163616265 +66373163306365626461373239333533656237376265303865633138633463396233333738396662 +64316464653137373332633233663031346633353139313533633638333465656232636433623464 +38366637353031636166353561666262643035343636663736386333323235376131633534663432 +62393837353035646237613136333530346131303931653961633238316235313361323731646138 +32383363326136636235373237306230633737346130633266643035636666373435663236396139 +36386231393562386233643634363435663639383765653335623531616331383136333538303636 +62363833626531626333386332376236326361313465316261646566393938323331326331616264 +64666439383565613239333334333134623233316533316432376630633834353033386239396662 +34333332646666353965643539353238656430666138316563373530373739363839323564373632 +35313837323864663737306431643961653330656463613238626564303333313230386165366564 +31313965363234613564646663336463633231396238383532343236616363323230346563343363 +31636437396634363037303661303432313766333032303134646265313233323737316437366663 +32613933303633303432613862333135313363303062616134643963353133613736626331646530 +66356464656162313034633530393533313432633735313435623437633361623334373663353131 +64306136316464376131393539333233386364613831383930633963333736363339393134373538 +34633762636337366231323561306562303833356163356431646437363662356132306666656139 +39313532333139383861313230373330373430623835636530326339383036323038363665663934 +38346566613937356362616365663237373730326337646535373233313837613138386134653561 +65613238313730646133386339653731383739643232633238653561666539653866623233343466 +34306261636263616363346235613166633439326131623231393931663539333962373961363231 +38393062613338353439643936313632316238333438386666303164346331306639626335393332 +36623535343862383963393937333430646339633335323735663262373638616130316239373632 +35303139613966613561313133653463636264623430396562646464323230636166326362363365 +32343630626238396661313864346163356339623565613361356635633961623163623734363465 +63646237343637646630613465656535313964613861653336616335346137306161343733653162 +34306435663963373030383334333766656661643934376634313535373131356261626632356334 +30396163653530656165633361383635363634366431383963376566353165393962636434636132 +32316638653237623965623934616662623736613534343132373965336234343032316431643263 +64306165343238636432613161366632633166313666616135383234636364663561363536346462 +65363863623931346134663834663635303665633230386164653039643566313234303339383665 +34633234386630376239313661383862306131386161623339643035373661306561316538646239 +63643338386663633364366336646336356530363465386138343930376432336337313366613036 +34663966633037373364376663653131326361333063616665326233623736626436643963306465 +30363432383531333637313365333436346664613535313730656332316261666238623165653431 +38656661326430633435393538633036313438326464626265313030613233653239346166636539 +33383934373634356561396235616565623865616362626534663536666562386539663063613963 +39393230643465316133663931313436666666376434386564323063353038333964653537383566 +32326663666136653338326535313963313661623765623035393030326566383633313532346635 +37363065653430363632353762303230646238653533383631336631613833363230333936336264 +61663463303333303739303830343534663865363732383130373735633234323530386665346234 +32356636633839376130316161643433306637653234373238343063386237376433666262656135 +36363362386538613736653132396334656331393139343533393634626634333532316366353036 +33653165386630626234623435323865353435616663363162643736313964303538303661643434 +62633131373137383135643639386431316139393230623764356431336538313538313933376638 +34363336373234666632636462306238366235336133373335353037613136383037343131623239 +30373162643861356266663431626566316439643362333731366632646663626238613831343739 +63643664353030343331656566656139383366333730636234653264643330366131646666376166 +30633331393966373166313163396532396238393338363432656466636434313232353863343532 +61663366346232646433393536393565633339633034306135393063646161323361363662646137 +32353330666664343233336531326566363131633533636630303335663662383936363436356161 +32633337323735323563323565333564613761646336383663373964373239306533336338313539 +61346137643434326235383034323039316138343735316634636132323039383865383866326561 +35323733633939313535303637303634323638386361656133346532336338326464653030386131 +31626334396131393763353832393938346139636631656531646365636432376431666233616136 +61303437383031363836316336363835613237666433303737616365386235373261623566386164 +37326238333036306266393861303961336266626434653361623230366161633234663361653835 +62346335303965323263613536363662623531316537306636313862336433363032613466646463 +38313262306336353565663831663363393735353339613430656635623438643265613164366532 +63363561636664343034386634653861333262393164386234616331316132396562643730356531 +39663537643937633631663135313164366563303063343565323564303366623030303762356162 +34313264333537393462363839343737653632653137666436646333326664653265323835333336 +63333136383338313631636530303863363334363835333565663033373132613961313734666433 +66313933383334623762373731316238663030323662636532633761633737623936336161323033 +30316633666134643163393834666337633036353234346230313263313565643433663838346565 +32336636333563663639363961636230336666313939333137393434633338636434373235326464 +38666635396431623835393463613366616632656330653233363061343835616134663538396661 +64663838623330616635393136353862306331323761376262653130306366373037363866376365 +37383265663532383032373834623234616539343839353531373862393937653834343332303535 +61363264663530366161666265663065383038313634376138373335663631353632646534643930 +34613366313538373565383332613863333130613538363065346437316466666131616465366265 +34363663663439663430396361353164363338386232626432613831616531376637613431656461 +61343237323533333563363130333864386536343937613636353639663235303663653838306563 +63313035356230336338343630333365656536346637306161393339666238366139353863633231 +37653333643938633463346232326430343332666136633835316464666165333239356132333032 +61366130383435396165383930393735393635653366363962326663633639343265373566313635 +32326538343637623561663734356635353363643863393639656638376339616365343731353734 +34666462383231356665376565363634353364383537636131306561373438616532313539323165 +33623662666335343133386562663434323963383731383633316434626662346136373235356264 +61316135613839316365336166376235643466653436623065313766376565323732626537656336 +32376239633039393830643539643537396533326264353135373062303537356439303532643537 +38326131323635613062366635303264633239633861333336643237386631393665323833303962 +32313964666363346533353961666135626262623034343261643461643137653934636232306136 +36313137626266326339376639613031356331393763663836613363616536613937313835613763 +32646332323435306466303238663533393566333930633539303765646430333737373932326639 +65633339303865623538353865346533633338393836386530393236316435623263646431616636 +32363636643137323530336532333166656231346161663864363562646562376631653037326364 +35643261623130363839623032616432646164373538373131653932363162613361666432643064 +33373361393535343766626331303133366435643366613733363661396463303430616439643336 +62653262393366353263393232303931373864323534396530623464623138333365336331386230 +66393535613365656466363565333536363032306562373031636263333732383465626533383537 +64663538333837376232313063623961396635356138356236303062386461663165663765353232 +64336632343530356432616265666237623965333532333563646364323435336561303066333063 +36613661383730383533333036306464633865653539313939383637353031613330343162383632 +30313164333264376266353536343738656137326332636361326562333764393961373365333234 +31356566646231353236663365356166656164313263663335343633336437306463343131623735 +38393264393464303832633964393831303432363362653939316462303964343565383330616232 +33316261376137643866636461393662386661636632626235616634396161333935633033306430 +39316233333230623061303238303935323833393065373364393733303831313339346230656434 +38353966306632663865316637346263323836633339623265393464393664646636373136656238 +32306539386338346438343166353034316266326161653738346666346337623864316632333861 +61323861313965343439383636306438666539396531313833306333306136333563643265333961 +30643133616366333463316130303661373630623537363931303137343537626266316137333064 +39643665386139666339623032386133333932376535323638626630363764326538633136366663 +36653163653138393863396135343139333764393635336138653464383836353434633531626534 +66316166356637333335623861333235343231323531663561393062336332376633333661663066 +63343930343830346365323530303030396538666334653231336637353033633435386637306264 +31663535313839383561353335316462386166386233653431363630643630376334643735636535 +31633431383139303663646464383834303537343330373930393438356463303234363963616337 +33613834373032346533653266346663316131343464386261336564363163333066353037643661 +63323730353364316164653534333435636261643565303835336262616336336230353165653966 +35343638616463336634333139396234663836393837383234633231376434663264633733343035 +66643037633666326236663237303239353936633164656536336638323134356462363731373262 +31666165383463633135613730656237336234666232656334663461316266353131376161376133 +33363034383833313030656234666633636337333065636434323363323637376166626633663561 +35613338623235393838626361356363653266626536663462363463356135633830383364386436 +35613262366632366536643864653862353836383763323566323639313030306131343666643334 +39306634373730656131666666623836616632366634346231313638393531363462353535343433 +30363637396539393562616166386662663236636139623465653937316232656562303333343832 +32653636646135383865343234383266336135616133666364306338353566356133663266396537 +36613161663538316664613838313131326635303365313132383364646162346136623464383362 +39393138666431356530373061393236633965326365653636303237393435366235393132393363 +33613761353835643234356661363163306431613931626433353833326334336238663766396237 +66316638343765363730393331623639303634316139623639346632313032613536323433303331 +39393331636136636438323939326338336461653565393732633061623336363238653736663832 +61353166663732383965396562343061323039313532323766623063633932363239383733313838 +31636566303039663238323934346531323661633861613535396434363434366663366330333533 +30333031393465303538623530343037363034323235663334353763343233343265633930376466 +32666563623635616461366639616164666265363561313966623264616535636566666634366638 +31613034353230336631353734333034386535366562666430626336666333613966333738313031 +30353031393333353132656465326239326432373364643662343839653263323961323164363861 +66653736353961336163333230663862326333653634663438346665333335343063626663303366 +65653138633433313133303931636533646663316362666333366561633434386563306631336266 +66356434666230353936326163363265303163633134353665666335393631363838616330626338 +37316466326133313832663832353533633066626165323031636230616336373931643963303237 +64643765363766386331613731356633323531386230626634316464376533623462316134343138 +34366332303232646432343563396637356133313732663864613833613031633635356463313032 +64393136353031373739333534396231363565316265353935616339353161626264383234316334 +38633636353530323432613362633764363161373738363638616131643234366365363233333064 +38373636336430376231633538336163616232393438366634336466663034393738653462353033 +34633565323832633366373035343039643635643866356133626339336332306435653832356534 +65623832363461313062653636626232366230623361383564373261646334346634616237306462 +63643434366238316432623234353963383231613537386562343537396430373338333065326663 +30373563636331663634613461653962393131666564353130353330363966323662373839373565 +34326564623662383264616363663665643238363565303965613034613036326238326532306462 +62353936666136643962643536353561363830656666633334343261663465363463303161343832 +30333130326333646635653631643665643336616334616332353266653539316261366431636134 +66626135383265666562306264636361613430303266633137386666343562666562646132656330 +65643333386565303766303562616262373137666130653866313362373137346165373930653539 +32666238663865616136326538383431313130316331353264636136383534613031313337343266 +38646565376535356636336538323833373464323535626466643430386433366665326564616431 +31623631353032656632613738393865343133303663353563376436393562353763613331343338 +61366161633562353835323938616435663535316438366361343963323636653732313665653939 +39663438663235303932373865616261643133393530376432666132636161326261386132316537 +39616232666465633866303437383762623465623765363939363531343636363461376365623632 +65653866346666666166386263326264393233666564646538303663653137366234373863643065 +32646439343336666233623662626334343530353137376236373964616661656231336638376661 +34346639323865636537316636393165303665336438653535363434326662346666326631613333 +39393262343937663635643864616134613632376132393239386336356564376131363733366131 +33616565383838393561396162373861613463636365353435643736656532666635346262663864 +34396366613535353538626661613631333463646462396537383538366133303561663337316438 +39626365303937336465353232353234643937396565383835303364393339623834666163653338 +61613131333364613037666461616136383865393465373833633162366434633236323666663965 +32643864653439386235303138326261303965386264323463646163643261666538653837373135 +62363538366231643030386439326166643438393431363664353431313735613361393932623033 +64326439663238353234323438396539613738663235653262643639363833633562353962313933 +32306439303631383033353534343539663734333132633534366337646634616263383335623761 +32643039383733313538393130333063333438343335616465663964356338383937626338366535 +66393034633364363862613530666138326332313436303934616639386634373765663166343739 +32303963306235663264643332343063313139346239663461316234366163343335643632663033 +66656162373436346538356162376266333763393866663965396533343939373733306465613135 +35313836303064663336623564376230366231353130373237643064333539323066353362343463 +65656534623438383738656234303034626133643431313035303762636336666335363236393163 +66336666623465666130343732383463316531373235353063653630343330333064666365633864 +65323266336233626239376338336430333834623835663064373534633233396131353338643563 +39376534393730666335383438633561633433333030343435306533623563313463373138306463 +64613066656338316466343464363365303366636463616239656262393639303738356637363464 +34313332623466323135383562316566386535373265343539643665353531663231303739613837 +36326633663432313333376237373230353039326461333331333430633737353066353433636633 +31383736633535343465623461666638313337666435393535393666363266623866363566336635 +64393232633032383963643830646138623630626536336164626663366131653038343437373965 +31663039383339383039656438396539366234396664636461313636613362333832303265326634 +65326234303162666131323065656237336635636236643139323337653033646232343537316631 +64653636306236383661323238396232336433323530393266316564373430633939643233316237 +64653034626636393365356438323165363265346235303734316334353136323439313830663136 +64643232653137633833643235346561633763316232623566653065353431626637633732396530 +65613765336461653165323266663662316431643361393261313263613765343139343038386637 +64323863646430356264353230313165623338656332346430376266376134313236623832306134 +62393033333136613637363239653334323531383234376261363038313465333466336538383737 +61316637633232363230366135636265633339323465643039366238626439656134333962383664 +62393632313436363866613236393461366262613135663039653136323038343061343166626536 +66303461323962626361326465616231313134393636343437376566306438663437653234613639 +31356563393338653561386235386562323038633630313932643162366631646534316334623638 +36613366303435336365623939376166396334346264646133323338353234316234343463623630 +66646437333461363766623339656233363434633538343033393237346239313536383763666430 +33613266626135613833616433326461313764376334623833346530343063333338663461646134 +64613030363339633738333338386261366361313037323034613561633766613933623030393131 +37636266323562326437613839656332643630663337326163373865356337363534623833316336 +63623461643832303163643133333938653864666639613761303461646533376138336562656166 +36626334323135373864636666636562643030356332306534613334313030363337643864306666 +31393039336665366138306361626232303662636432663464383361656537393037323266623736 +61383031346539383932653462373562303035303462666432643330643632666263313439316230 +37383664313439383035343266383138383765393363373565653739343036363661373731613433 +323130373039366635353462613536643830 diff --git a/ansible/inventory.yml b/ansible/inventory.yml index 07a3550..c9db72b 100755 --- a/ansible/inventory.yml +++ b/ansible/inventory.yml @@ -25,21 +25,28 @@ ntp_servers: load_balancers: hosts: lightning_lane: - ansible_host: 10.1.71.35 ansible_become: true step_ca_server: hosts: turnstile: - ansible_host: 10.1.71.34 ansible_become: true authentik_server: hosts: guest-relations: - ansible_host: 10.1.71.40 ansible_become: true +semaphore_server: + hosts: + imagineering: + ansible_host: 10.1.71.37 + ansible_become: true + +n8n_server: + hosts: + tiki-room: + prometheus_server: hosts: cinderella-castle: @@ -69,14 +76,6 @@ dev_servers: hosts: scrim: -semaphore_server: - hosts: - imagineering: - -n8n_server: - hosts: - tiki-room: - # dhcp_server: # hosts: # matchbox: diff --git a/ansible/playbooks/day1_deploy_semaphore.yml b/ansible/playbooks/day1_deploy_semaphore.yml new file mode 100644 index 0000000..b4324d8 --- /dev/null +++ b/ansible/playbooks/day1_deploy_semaphore.yml @@ -0,0 +1,23 @@ +--- +# ------------------------------------------------------------------------------ +# FILE: playbooks/day1_deploy_semaphore.yml +# DESCRIPTION: Deploys Semaphore on imagineering +# Runs: common → docker-host → semaphore +# +# USAGE: +# ansible-playbook -i inventory.yml playbooks/day1_deploy_semaphore.yml +# +# SECRETS REQUIRED IN VAULT (group_vars/all/vault): +# vault_semaphore_database_password +# vault_semaphore_admin_password +# vault_semaphore_access_key_encryption +# ------------------------------------------------------------------------------ + +- name: Deploy Semaphore + hosts: semaphore_server + become: true + + roles: + - common + - docker-host + - semaphore diff --git a/ansible/playbooks/roles/semaphore/defaults/main.yml b/ansible/playbooks/roles/semaphore/defaults/main.yml new file mode 100644 index 0000000..b110971 --- /dev/null +++ b/ansible/playbooks/roles/semaphore/defaults/main.yml @@ -0,0 +1,4 @@ +--- +# file: roles/semaphore/defaults/main.yml + +semaphore_compose_dir: /opt/docker/semaphore diff --git a/ansible/playbooks/roles/semaphore/handlers/main.yml b/ansible/playbooks/roles/semaphore/handlers/main.yml new file mode 100644 index 0000000..7df1109 --- /dev/null +++ b/ansible/playbooks/roles/semaphore/handlers/main.yml @@ -0,0 +1,7 @@ +--- +# file: roles/semaphore/handlers/main.yml + +- name: Restart Semaphore + community.docker.docker_compose_v2: + project_src: "{{ semaphore_compose_dir }}" + state: restarted diff --git a/ansible/playbooks/roles/semaphore/tasks/main.yml b/ansible/playbooks/roles/semaphore/tasks/main.yml new file mode 100644 index 0000000..2a5114a --- /dev/null +++ b/ansible/playbooks/roles/semaphore/tasks/main.yml @@ -0,0 +1,212 @@ +--- +# file: roles/semaphore/tasks/main.yml + +- name: Create Semaphore directory + ansible.builtin.file: + path: "{{ semaphore_compose_dir }}" + state: directory + owner: wed + group: docker + mode: '0755' + +- name: Copy Compose file from boilerplate + ansible.builtin.copy: + src: "{{ playbook_dir }}/../../boilerplates/semaphore/compose.yaml" + dest: "{{ semaphore_compose_dir }}/compose.yaml" + owner: wed + group: docker + mode: '0644' + +- name: Deploy Semaphore .env file + ansible.builtin.template: + src: env.j2 + dest: "{{ semaphore_compose_dir }}/.env" + owner: wed + group: docker + mode: '0600' + +- name: Start Semaphore containers + community.docker.docker_compose_v2: + project_src: "{{ semaphore_compose_dir }}" + state: present + register: semaphore_compose + +- name: Wait for Semaphore to be ready + ansible.builtin.uri: + url: "http://localhost:3000/api/ping" + method: GET + status_code: 200 + register: semaphore_health + retries: 24 + delay: 5 + until: semaphore_health.status == 200 + +# ── Post-deploy: Restore project config via API ── + +- name: Authenticate to Semaphore API + ansible.builtin.uri: + url: "http://localhost:3000/api/auth/login" + method: POST + body_format: json + body: + auth: "admin" + password: "{{ vault_semaphore_admin_password }}" + status_code: 204 + return_content: false + register: semaphore_auth + no_log: true + +- name: Set auth cookie fact + ansible.builtin.set_fact: + semaphore_cookie: "{{ semaphore_auth.cookies_string }}" + no_log: true + +- name: Check if mk-labs project already exists + ansible.builtin.uri: + url: "http://localhost:3000/api/projects" + method: GET + headers: + Cookie: "{{ semaphore_cookie }}" + return_content: true + register: semaphore_projects + +- name: Set project exists flag + ansible.builtin.set_fact: + project_exists: "{{ semaphore_projects.json | selectattr('name', 'equalto', 'mk-labs') | list | length > 0 }}" + +- name: Read project config from boilerplate + ansible.builtin.slurp: + src: "{{ playbook_dir }}/../../boilerplates/semaphore/project-config.json" + delegate_to: localhost + become: false + register: project_config_raw + when: not project_exists + +- name: Restore project via API + ansible.builtin.uri: + url: "http://localhost:3000/api/projects/restore" + method: POST + headers: + Cookie: "{{ semaphore_cookie }}" + Content-Type: "application/json" + body: "{{ project_config_raw.content | b64decode | string }}" + body_format: raw + status_code: [200, 201] + return_content: true + register: restore_result + when: not project_exists + +- name: Display restore result + ansible.builtin.debug: + msg: "Project '{{ restore_result.json.name | default('mk-labs') }}' restored successfully (ID: {{ restore_result.json.id | default('unknown') }})" + when: not project_exists and restore_result is defined + +- name: Skip restore — project already exists + ansible.builtin.debug: + msg: "Project 'mk-labs' already exists, skipping restore" + when: project_exists + +# ── Push secrets: DELETE empty shells, POST with actual values ── + +- name: Get project ID + ansible.builtin.set_fact: + semaphore_project_id: >- + {{ (semaphore_projects.json | selectattr('name', 'equalto', 'mk-labs') | first).id + if project_exists else restore_result.json.id }} + +- name: Get existing keys + ansible.builtin.uri: + url: "http://localhost:3000/api/project/{{ semaphore_project_id }}/keys" + method: GET + headers: + Cookie: "{{ semaphore_cookie }}" + return_content: true + register: semaphore_keys + +- name: Find wed-ssh-key ID (if exists) + ansible.builtin.set_fact: + wed_ssh_key_id: "{{ (semaphore_keys.json | selectattr('name', 'equalto', 'wed-ssh-key') | first).id | default(omit) }}" + ignore_errors: true + +- name: Find ansible-vault-password ID (if exists) + ansible.builtin.set_fact: + vault_password_key_id: "{{ (semaphore_keys.json | selectattr('name', 'equalto', 'ansible-vault-password') | first).id | default(omit) }}" + ignore_errors: true + +- name: Check if wed-ssh-key is empty + ansible.builtin.set_fact: + wed_ssh_key_empty: "{{ (semaphore_keys.json | selectattr('name', 'equalto', 'wed-ssh-key') | first).empty | default(true) }}" + ignore_errors: true + +- name: Check if ansible-vault-password is empty + ansible.builtin.set_fact: + vault_password_empty: "{{ (semaphore_keys.json | selectattr('name', 'equalto', 'ansible-vault-password') | first).empty | default(true) }}" + ignore_errors: true + +# -- wed-ssh-key: delete empty shell if needed, then create with value -- + +- name: Delete empty wed-ssh-key shell + ansible.builtin.uri: + url: "http://localhost:3000/api/project/{{ semaphore_project_id }}/keys/{{ wed_ssh_key_id }}" + method: DELETE + headers: + Cookie: "{{ semaphore_cookie }}" + status_code: [200, 204] + when: wed_ssh_key_id is defined and wed_ssh_key_empty | bool + +- name: Build wed-ssh-key payload + ansible.builtin.set_fact: + wed_key_payload: >- + {{ {"name": "wed-ssh-key", + "type": "ssh", + "project_id": semaphore_project_id | int, + "ssh": {"login": "", "passphrase": "", "private_key": vault_wed_ssh_private_key}} | to_json }} + no_log: true + when: wed_ssh_key_empty | bool + +- name: Create wed-ssh-key with private key + ansible.builtin.uri: + url: "http://localhost:3000/api/project/{{ semaphore_project_id }}/keys" + method: POST + headers: + Cookie: "{{ semaphore_cookie }}" + Content-Type: "application/json" + body: "{{ wed_key_payload }}" + body_format: raw + status_code: [200, 201] + no_log: true + when: wed_ssh_key_empty | bool + +# -- ansible-vault-password: delete empty shell if needed, then create with value -- + +- name: Delete empty ansible-vault-password shell + ansible.builtin.uri: + url: "http://localhost:3000/api/project/{{ semaphore_project_id }}/keys/{{ vault_password_key_id }}" + method: DELETE + headers: + Cookie: "{{ semaphore_cookie }}" + status_code: [200, 204] + when: vault_password_key_id is defined and vault_password_empty | bool + +- name: Build ansible-vault-password payload + ansible.builtin.set_fact: + vault_key_payload: >- + {{ {"name": "ansible-vault-password", + "type": "login_password", + "project_id": semaphore_project_id | int, + "login_password": {"login": "", "password": vault_ansible_vault_password}} | to_json }} + no_log: true + when: vault_password_empty | bool + +- name: Create ansible-vault-password with value + ansible.builtin.uri: + url: "http://localhost:3000/api/project/{{ semaphore_project_id }}/keys" + method: POST + headers: + Cookie: "{{ semaphore_cookie }}" + Content-Type: "application/json" + body: "{{ vault_key_payload }}" + body_format: raw + status_code: [200, 201] + no_log: true + when: vault_password_empty | bool diff --git a/ansible/playbooks/roles/semaphore/templates/env.j2 b/ansible/playbooks/roles/semaphore/templates/env.j2 new file mode 100644 index 0000000..6eee83d --- /dev/null +++ b/ansible/playbooks/roles/semaphore/templates/env.j2 @@ -0,0 +1,3 @@ +DATABASE_PASSWORD={{ vault_semaphore_database_password }} +SEMAPHORE_ADMIN_PASSWORD={{ vault_semaphore_admin_password }} +SEMAPHORE_ACCESS_KEY_ENCRYPTION={{ vault_semaphore_access_key_encryption }} diff --git a/boilerplates/semaphore/.env b/boilerplates/semaphore/.env new file mode 100644 index 0000000..7f26081 --- /dev/null +++ b/boilerplates/semaphore/.env @@ -0,0 +1,3 @@ +DATABASE_PASSWORD=cVMGmtkCcOsMReHi99GHBIWNmNTUQPfZ +SEMAPHORE_ADMIN_PASSWORD=4U+gEcm0aUby+5q5 +SEMAPHORE_ACCESS_KEY_ENCRYPTION=6APgfDAgWtqg0XBXPKPyG7N3evwksB6u diff --git a/boilerplates/semaphore/compose.yaml b/boilerplates/semaphore/compose.yaml new file mode 100644 index 0000000..5eb7768 --- /dev/null +++ b/boilerplates/semaphore/compose.yaml @@ -0,0 +1,44 @@ +services: + semaphore: + image: docker.io/semaphoreui/semaphore:v2.17.2 + restart: unless-stopped + environment: + - SEMAPHORE_DB_DIALECT=mysql + - SEMAPHORE_DB_HOST=semaphore_db + - SEMAPHORE_DB=semaphore + - SEMAPHORE_DB_USER=semaphore + - SEMAPHORE_DB_PASS=${DATABASE_PASSWORD} + - SEMAPHORE_ADMIN=admin + - SEMAPHORE_ADMIN_NAME=Administrator + - SEMAPHORE_ADMIN_EMAIL=ryan.blundon@protonmail.com + - SEMAPHORE_ADMIN_PASSWORD=${SEMAPHORE_ADMIN_PASSWORD} + - SEMAPHORE_PLAYBOOK_PATH=/tmp/semaphore/ + - SEMAPHORE_ACCESS_KEY_ENCRYPTION=${SEMAPHORE_ACCESS_KEY_ENCRYPTION} + - ANSIBLE_HOST_KEY_CHECKING=False + networks: + - semaphore_backend + ports: + - "3000:3000" + depends_on: + - semaphore_db + + semaphore_db: + image: docker.io/library/mysql:8.1 + restart: unless-stopped + environment: + - MYSQL_USER=semaphore + - MYSQL_PASSWORD=${DATABASE_PASSWORD} + - MYSQL_DATABASE=semaphore + - MYSQL_ROOT_PASSWORD=${DATABASE_PASSWORD} + networks: + - semaphore_backend + volumes: + - semaphore_db:/var/lib/mysql + +volumes: + semaphore_db: + driver: local + +networks: + semaphore_backend: + driver: bridge diff --git a/boilerplates/semaphore/project-config.json b/boilerplates/semaphore/project-config.json new file mode 100644 index 0000000..6f0570f --- /dev/null +++ b/boilerplates/semaphore/project-config.json @@ -0,0 +1,107 @@ +{ + "environments": [ + { + "env": "{}", + "json": "{}", + "name": "Production" + } + ], + "integration_aliases": [], + "integrations": [], + "inventories": [ + { + "become_key": "wed-ssh-key", + "inventory": "ansible/inventory.yml", + "name": "foundation", + "ssh_key": "wed-ssh-key", + "type": "file" + } + ], + "keys": [ + { + "name": "git-public", + "owner": "", + "type": "none" + }, + { + "name": "wed-ssh-key", + "owner": "", + "type": "ssh" + }, + { + "name": "ansible-vault-password", + "owner": "", + "type": "login_password" + } + ], + "meta": { + "alert": false, + "max_parallel_tasks": 0, + "name": "mk-labs", + "type": "" + }, + "repositories": [ + { + "git_branch": "main", + "git_url": "https://github.com/rblundon/homelab.git", + "name": "homelab", + "ssh_key": "git-public" + } + ], + "roles": [], + "schedules": [], + "secret_storages": [], + "templates": [ + { + "allow_override_args_in_task": true, + "autorun": false, + "description": "Post-provisioning OS baseline: common role, DNS registration, NetBox status update", + "environment": "Production", + "inventory": "foundation", + "name": "day0-baseline", + "playbook": "ansible/playbooks/day0_baseline.yml", + "repository": "homelab", + "suppress_success_alerts": false, + "survey_vars": [], + "type": "task", + "vault_key": "ansible-vault-password" + }, + { + "allow_override_args_in_task": true, + "autorun": false, + "description": "Deploy Semaphore on imagineering", + "environment": "Production", + "inventory": "foundation", + "name": "day1-deploy-semaphore", + "playbook": "ansible/playbooks/day1_deploy_semaphore.yml", + "repository": "homelab", + "suppress_success_alerts": false, + "survey_vars": [], + "type": "task", + "vault_key": "ansible-vault-password" + }, + { + "allow_override_args_in_task": false, + "autorun": false, + "description": "Sync Traefik dynamic configs and create DNS CNAMEs for all services", + "environment": "Production", + "inventory": "foundation", + "name": "add-service-route", + "playbook": "ansible/playbooks/add_service_route.yml", + "repository": "homelab", + "suppress_success_alerts": false, + "survey_vars": [], + "type": "task", + "vault_key": "ansible-vault-password" + } + ], + "views": [ + { + "hidden": false, + "position": 0, + "sort_reverse": false, + "title": "All", + "type": "all" + } + ] +} diff --git a/boilerplates/traefik/dynamic/semaphore.yml b/boilerplates/traefik/dynamic/semaphore.yml new file mode 100644 index 0000000..450ca8d --- /dev/null +++ b/boilerplates/traefik/dynamic/semaphore.yml @@ -0,0 +1,17 @@ +http: + routers: + semaphore: + rule: "Host(`semaphore.local.mk-labs.cloud`)" + entryPoints: + - websecure + service: semaphore + tls: + certResolver: cloudflare + middlewares: + - security-headers + + services: + semaphore: + loadBalancer: + servers: + - url: "http://imagineering.local.mk-labs.cloud:3000" diff --git a/docs/decisions/PROJECT_TASKS.md b/docs/PROJECT_TASKS.md similarity index 58% rename from docs/decisions/PROJECT_TASKS.md rename to docs/PROJECT_TASKS.md index 2570cd1..f474202 100644 --- a/docs/decisions/PROJECT_TASKS.md +++ b/docs/PROJECT_TASKS.md @@ -8,14 +8,14 @@ --- -## Phase 0: Repository Restructuring +## Phase 0: Repository Restructuring ✅ | # | Task | Done By | Status | |---|------|---------|--------| -| 0.1 | Create `archive/pre-mk-labs` branch from current `main` | — | `[ ]` | -| 0.2 | Restructure repo to new directory layout (terraform/, ansible/, n8n/, netbox/, boilerplates/) | — | `[ ]` | -| 0.3 | Validate existing Terraform modules and Ansible roles still work from new paths | — | `[ ]` | -| 0.4 | Update `ansible.cfg` roles_path for new directory structure | — | `[ ]` | +| 0.1 | ~~Create `archive/pre-mk-labs` branch from current `main`~~ | — | `[x]` | +| 0.2 | ~~Restructure repo to new directory layout (terraform/, ansible/, n8n/, netbox/, boilerplates/, packer/, talos/, docs/)~~ | — | `[x]` | +| 0.3 | ~~Validate existing Terraform modules and Ansible roles still work from new paths~~ | — | `[x]` | +| 0.4 | ~~Update `ansible.cfg` roles_path for new directory structure~~ | — | `[x]` | --- @@ -23,25 +23,29 @@ > **Depends on:** Phase 0 -### 1A: Deploy NetBox (`fire-station`) +### 1A: Deploy NetBox (`fire-station`) ✅ + +> **Note:** `fire-station` LXC deployed via Proxmox helper script. NetBox is configured and working. | # | Task | Done By | Status | |---|------|---------|--------| -| 1.1 | Provision `fire-station` VM (10.1.71.102) — manual for now (this is a pipeline prerequisite) | Terraform | `[ ]` | -| 1.2 | Generate NetBox Compose stack via Boilerplates CLI | Boilerplates | `[ ]` | -| 1.3 | Deploy NetBox containers on `fire-station` | Ansible | `[ ]` | -| 1.4 | Add Traefik dynamic config for `netbox.local.mk-labs.cloud` → `fire-station` | Ansible | `[ ]` | -| 1.5 | Create DNS record on `monorail` pointing to `lightning-lane` (10.1.71.35) | Ansible | `[ ]` | -| 1.6 | Verify NetBox accessible via `netbox.local.mk-labs.cloud` | Manual | `[ ]` | +| 1.1 | ~~Provision `fire-station` (10.1.71.34)~~ — LXC already running | Helper script | `[x]` | +| 1.2 | ~~Deploy NetBox on `fire-station`~~ — installed via helper script | Helper script | `[x]` | +| 1.3 | ~~NetBox configured and operational~~ | Manual | `[x]` | +| 1.4 | Add Traefik dynamic config for `netbox.local.mk-labs.cloud` → `fire-station` | Ansible | `[-]` | +| 1.5 | Create DNS CNAME on `monorail` pointing to `lightning-lane` | Ansible | `[-]` | +| 1.6 | Verify NetBox accessible via `netbox.local.mk-labs.cloud` | Manual | `[-]` | + +> **Note:** Tasks 1.4–1.6 deferred. Helper-script Apache install conflicts with Traefik reverse proxy (double Host header issue). NetBox accessible directly at `fire-station.local.mk-labs.cloud`. Will resolve when NetBox is rebuilt as a Compose stack (see P.10). ### 1B: Configure NetBox Data Model | # | Task | Done By | Status | |---|------|---------|--------| -| 1.7 | Create `netbox/initializers/custom_fields.yml` in repo | Manual | `[ ]` | -| 1.8 | Add custom fields to VM object: `proxmox_template` (selection), `proxmox_node` (selection), `vm_role` (text) | NetBox | `[ ]` | -| 1.9 | Create `netbox/initializers/vlans.yml` — define all VLANs from master table | Manual | `[ ]` | -| 1.10 | Create `netbox/initializers/prefixes.yml` — define IP prefixes | Manual | `[ ]` | +| 1.7 | ~~Create `netbox/initializers/custom_fields.yml` in repo~~ | Manual | `[x]` | +| 1.8 | ~~Add custom fields to VM object: `proxmox_template` (selection), `proxmox_node` (selection), `vm_role` (text)~~ — applied from initializers | NetBox | `[x]` | +| 1.9 | ~~Create `netbox/initializers/vlans.yml` — define all VLANs from master table~~ | Manual | `[x]` | +| 1.10 | ~~Create `netbox/initializers/prefixes.yml` — define IP prefixes~~ | Manual | `[x]` | | 1.11 | Import existing infrastructure into NetBox (Proxmox hosts, existing VMs, IPs) | Manual | `[ ]` | | 1.12 | Configure NetBox webhook: `VM Staged Trigger` — POST to `http://tiki-room:5678/webhook/vm-provision` on VM status change to `Staged` | NetBox | `[ ]` | | 1.13 | Test webhook fires correctly on VM status change | Manual | `[ ]` | @@ -51,12 +55,13 @@ ## Phase 2: Terraform VM Module > **Depends on:** Phase 0 (repo structure) +> **Note:** `terraform/proxmox/vm/` module exists with `main.tf`, `variables.tf`, `outputs.tf`, `providers.tf`. A `test-pipeline-vm` has been run. UDM DHCP module also exists at `terraform/unifi/dhcp/`. | # | Task | Done By | Status | |---|------|---------|--------| -| 2.1 | Write `variables.tf`: hostname, ip, vlan, template, proxmox_node | Manual | `[ ]` | -| 2.2 | Write `main.tf` using bpg/proxmox provider for VM resource | Manual | `[ ]` | -| 2.3 | Test `terraform apply` manually with hardcoded values | Manual | `[ ]` | +| 2.1 | ~~Write `variables.tf`: hostname, ip, vlan, template, proxmox_node~~ | Manual | `[x]` | +| 2.2 | ~~Write `main.tf` using bpg/proxmox provider for VM resource~~ | Manual | `[x]` | +| 2.3 | ~~Test `terraform apply` manually with hardcoded values~~ (`test-pipeline-vm` state exists) | Manual | `[x]` | | 2.4 | Validate cloud-init baseline config (hostname, SSH key, networking) | Manual | `[ ]` | | 2.5 | Configure Terraform state backend on `city-hall` | Manual | `[ ]` | @@ -65,15 +70,16 @@ ## Phase 3: Ansible Baseline Role & Semaphore > **Depends on:** Phase 0 (repo structure) +> **Note:** `common` role exists (hostname, chrony, packages, sudo). `dns-manager` role exists. `docker-host` role exists. Playbooks for DNS entry creation exist. Semaphore (`imagineering`) is deployed via helper script but not yet configured. | # | Task | Done By | Status | |---|------|---------|--------| | 3.1 | Configure NetBox dynamic inventory plugin (`netbox.yml`) | Manual | `[ ]` | -| 3.2 | Write/update `vm-baseline` role: packages, SSH hardening, Chrony → `sundial` | Manual | `[ ]` | -| 3.3 | Add DNS registration task to role (Technitium API on `monorail`) | Manual | `[ ]` | +| 3.2 | ~~Write/update `vm-baseline` role: packages, SSH hardening, Chrony → `sundial`~~ (`common` role exists) | Manual | `[x]` | +| 3.3 | ~~Add DNS registration task to role (Technitium API on `monorail`)~~ (`dns-manager` role + `add_technitium_dns_entry` task exist) | Manual | `[x]` | | 3.4 | Add NetBox status update task — set VM to `Active` via API on success | Manual | `[ ]` | | 3.5 | Add NetBox status update task — set VM to `Failed` via API on error | Manual | `[ ]` | -| 3.6 | Configure Semaphore (`imagineering`): connect to GitHub repo, create job template for `vm-baseline` | Manual | `[ ]` | +| 3.6 | Redeploy Semaphore (`imagineering`) as VM with Boilerplates Compose stack, then configure: connect to GitHub repo, create job template for `day0_baseline` | Manual | `[ ]` | | 3.7 | Test Ansible playbook end-to-end via Semaphore manual trigger | Manual | `[ ]` | --- @@ -82,16 +88,20 @@ > **Depends on:** Phases 1, 2, 3 -### 4A: Deploy & Configure n8n (`tiki-room`) +### 4A: Deploy & Configure n8n (`tiki-room`) ✅ + +> **Note:** `tiki-room` and n8n deployed via helper script, configured and working. `imagineering` (Semaphore) deployed via helper script but not yet configured. | # | Task | Done By | Status | |---|------|---------|--------| -| 4.1 | Provision `tiki-room` VM (10.1.71.23) if not already running | Terraform | `[ ]` | -| 4.2 | Deploy n8n containers on `tiki-room` | Ansible | `[ ]` | -| 4.3 | Add Traefik dynamic config for `n8n.local.mk-labs.cloud` → `tiki-room` | Ansible | `[ ]` | +| 4.1 | ~~Provision `tiki-room` (10.1.71.36)~~ — already running | Helper script | `[x]` | +| 4.2 | ~~Deploy and configure n8n on `tiki-room`~~ — working | Helper script | `[x]` | +| 4.3 | ~~Add Traefik dynamic config for `n8n.local.mk-labs.cloud` → `tiki-room`~~ | Ansible | `[x]` | ### 4B: Build the Provisioning Workflow +> **Note:** `n8n/workflows/VM Provisioning Pipeline.json` and `DNS: Create A Record.json` already exported to repo. + | # | Task | Done By | Status | |---|------|---------|--------| | 4.4 | Create n8n webhook node to receive NetBox payload | n8n | `[ ]` | @@ -99,7 +109,7 @@ | 4.6 | Add Terraform trigger: SSH to `city-hall`, run `terraform apply` with variables from payload | n8n | `[ ]` | | 4.7 | Add Semaphore trigger: call Semaphore API to launch `vm-baseline` job template | n8n | `[ ]` | | 4.8 | Add error handling: set NetBox VM status to `Failed` on any pipeline error | n8n | `[ ]` | -| 4.9 | Export n8n workflow JSON and commit to `n8n/workflows/vm-provisioning.json` | Manual | `[ ]` | +| 4.9 | ~~Export n8n workflow JSON and commit to `n8n/workflows/vm-provisioning.json`~~ (initial export exists) | Manual | `[x]` | --- @@ -109,10 +119,12 @@ ### 5A: Hostname & IP Allocation +> **Decided:** Hostname `the-grid` · IP `10.1.71.128` · VM ID `71128` · DNS `the-grid.local.mk-labs.cloud` · External `the-grid.mk-labs.cloud` + | # | Task | Done By | Status | |---|------|---------|--------| -| 5.1 | Select themed hostname for Nextcloud VM | Manual | `[ ]` | -| 5.2 | Allocate IP address from General Applications block (10.1.71.128/25) | Manual | `[ ]` | +| 5.1 | ~~Select themed hostname for Nextcloud VM~~ → `the-grid` | Manual | `[x]` | +| 5.2 | ~~Allocate IP address from General Applications block (10.1.71.128/25)~~ → `10.1.71.128` | Manual | `[x]` | | 5.3 | Add hostname and IP to master allocation table in `Homelab_Technical_Decision_Points.md` | Manual | `[ ]` | ### 5B: Pipeline Run @@ -147,9 +159,9 @@ | # | Task | Done By | Status | |---|------|---------|--------| -| 6.6 | Add Traefik dynamic config for `nextcloud.local.mk-labs.cloud` → Nextcloud VM | Ansible | `[ ]` | -| 6.7 | Create DNS record on `monorail` pointing `nextcloud.local.mk-labs.cloud` to `lightning-lane` (10.1.71.35) | Ansible | `[ ]` | -| 6.8 | Verify Nextcloud accessible via `nextcloud.local.mk-labs.cloud` | Manual | `[ ]` | +| 6.6 | Add Traefik dynamic config for `the-grid.local.mk-labs.cloud` → Nextcloud VM | Ansible | `[ ]` | +| 6.7 | Create DNS record on `monorail` pointing `the-grid.local.mk-labs.cloud` to `lightning-lane` (10.1.71.35) | Ansible | `[ ]` | +| 6.8 | Verify Nextcloud accessible via `the-grid.local.mk-labs.cloud` | Manual | `[ ]` | ### 6C: Authentik OIDC Integration @@ -187,7 +199,7 @@ | # | Task | Done By | Status | |---|------|---------|--------| | 7.4 | Add `cloudflared` container to Nextcloud's Compose stack (or deploy centrally — decide placement) | Manual | `[ ]` | -| 7.5 | Configure tunnel to route `nextcloud.mk-labs.cloud` → `http://localhost:80` (or Traefik) | Manual | `[ ]` | +| 7.5 | Configure tunnel to route `the-grid.mk-labs.cloud` → `http://localhost:80` (or Traefik) | Manual | `[ ]` | | 7.6 | Deploy `cloudflared` container | Ansible | `[ ]` | | 7.7 | Verify tunnel status in Cloudflare dashboard (healthy/connected) | Manual | `[ ]` | @@ -195,9 +207,9 @@ | # | Task | Done By | Status | |---|------|---------|--------| -| 7.8 | Verify Cloudflare auto-creates CNAME for `nextcloud.mk-labs.cloud` → tunnel | Cloudflare | `[ ]` | -| 7.9 | Configure Cloudflare Access policy for `nextcloud.mk-labs.cloud` (optional: OIDC via Authentik, IP allowlist, or open) | Cloudflare | `[ ]` | -| 7.10 | Test external access to `nextcloud.mk-labs.cloud` from outside the network | Manual | `[ ]` | +| 7.8 | Verify Cloudflare auto-creates CNAME for `the-grid.mk-labs.cloud` → tunnel | Cloudflare | `[ ]` | +| 7.9 | Configure Cloudflare Access policy for `the-grid.mk-labs.cloud` (optional: OIDC via Authentik, IP allowlist, or open) | Cloudflare | `[ ]` | +| 7.10 | Test external access to `the-grid.mk-labs.cloud` from outside the network | Manual | `[ ]` | | 7.11 | Test Nextcloud desktop/mobile client sync via external URL | Manual | `[ ]` | --- @@ -231,3 +243,7 @@ | P.7 | NetBox template auto-sync from Proxmox API | `proxmox_template` dropdown currently maintained manually | | P.8 | Additional Cloudflare Tunnel services | Pattern established with Nextcloud; extend to other external-facing services | | P.9 | Nextcloud: Photos backup, Calendar & Contacts | Expand Nextcloud scope beyond file sync | +| P.10 | Ansiblize NetBox LXC (`fire-station`) | Create Ansible role for NetBox Apache vhost config, `wed` user setup, and baseline config. Currently helper-script deployed with no `wed` user. Apache `ServerName` was manually changed from `netbox.example.com` to `netbox.local.mk-labs.cloud`. | +| P.11 | `add_service_route.yml` — remove stale CNAMEs | When a dynamic config is removed from `boilerplates/traefik/dynamic/`, the corresponding CNAME on `monorail` should be cleaned up. Currently the playbook only creates, never deletes. | +| P.12 | Rename existing deploy playbooks to day0/day1 convention | `deploy_authentik.yml` → `day1_deploy_authentik.yml`, `deploy_traefik.yml` → `day1_deploy_traefik.yml`, etc. New playbooks already follow the convention. | +| P.13 | Evaluate external secrets manager | Explore Infisical, HashiCorp Vault, or Doppler to replace Ansible Vault encrypted files. Would provide audit logging, rotation, access control. Consolidate centralized vs distributed vault question at the same time. | diff --git a/terraform/proxmox/hosts/tfvars/guest-relations.tfvars b/terraform/proxmox/hosts/tfvars/guest-relations.tfvars index 08cff6a..612b9c5 100644 --- a/terraform/proxmox/hosts/tfvars/guest-relations.tfvars +++ b/terraform/proxmox/hosts/tfvars/guest-relations.tfvars @@ -6,9 +6,7 @@ # cd terraform/proxmox/hosts # terraform apply \ # -var-file="tfvars/guest-relations.tfvars" \ -# -state="states/guest-relations.tfstate" \ -# -var="proxmox_api_url=https://main-street-usa.local.mk-labs.cloud:8006" \ -# -var="proxmox_api_token=terraform@pve!terraform-token=" +# -state="states/guest-relations.tfstate" hostname = "guest-relations" vm_id = 71040 diff --git a/terraform/proxmox/hosts/tfvars/imagineering.tfvars b/terraform/proxmox/hosts/tfvars/imagineering.tfvars new file mode 100644 index 0000000..843c1a0 --- /dev/null +++ b/terraform/proxmox/hosts/tfvars/imagineering.tfvars @@ -0,0 +1,24 @@ +# ─── imagineering ────────────────────────────────────────────────────────── +# Semaphore Ansible Automation +# Provisioned manually (pre-pipeline bootstrap — NetBox not yet available) +# +# Apply: +# cd terraform/proxmox/hosts +# terraform apply \ +# -var-file="tfvars/imagineering.tfvars" \ +# -state="states/imagineering.tfstate" + +hostname = "imagineering" +vm_id = 71037 +ip_address = "10.1.71.37" +target_node = "main-street-usa" +clone_node = "fantasyland" +template_name = "ubuntu-24.04-medium" +datastore = "liberty-tree" +bridge = "vmbr0" +dns_servers = ["10.1.71.1"] +search_domain = "local.mk-labs.cloud" + +# Bootstrap mode — no pipeline available yet +started = true +use_dhcp = false diff --git a/terraform/proxmox/hosts/tfvars/lightning-lane.tfvars b/terraform/proxmox/hosts/tfvars/lightning-lane.tfvars index 08bd3de..317a746 100644 --- a/terraform/proxmox/hosts/tfvars/lightning-lane.tfvars +++ b/terraform/proxmox/hosts/tfvars/lightning-lane.tfvars @@ -6,9 +6,7 @@ # cd terraform/proxmox/hosts # terraform apply \ # -var-file="tfvars/lightning-lane.tfvars" \ -# -state="states/lightning-lane.tfstate" \ -# -var="proxmox_api_url=https://main-street-usa.local.mk-labs.cloud:8006" \ -# -var="proxmox_api_token=terraform@pve!automation=" +# -state="states/lightning-lane.tfstate" hostname = "lightning-lane" vm_id = 71035 diff --git a/terraform/proxmox/hosts/tfvars/turnstile.tfvars b/terraform/proxmox/hosts/tfvars/turnstile.tfvars index 05ec128..22a25c7 100644 --- a/terraform/proxmox/hosts/tfvars/turnstile.tfvars +++ b/terraform/proxmox/hosts/tfvars/turnstile.tfvars @@ -6,11 +6,7 @@ # cd terraform/proxmox/hosts # terraform apply \ # -var-file="tfvars/turnstile.tfvars" \ -# -state="states/turnstile.tfstate" \ -# -var="proxmox_api_url=https://main-street-usa.local.mk-labs.cloud:8006" \ -# -var="proxmox_api_token=terraform@pve!terraform-token=" -# turnstile — Smallstep step-ca SSH Certificate Authority -# Provisioned manually (pre-pipeline bootstrap) +# -state="states/turnstile.tfstate" hostname = "turnstile" vm_id = 71034