Compare commits
10 commits
338f2ae636
...
a8a2815c5f
| Author | SHA1 | Date | |
|---|---|---|---|
| a8a2815c5f | |||
| cea2523e15 | |||
| c4094b692f | |||
| 16cbd189b8 | |||
| 82fca48b08 | |||
| 4bee182978 | |||
| 39a1b43577 | |||
| cc9340b7cc | |||
| b07ed72a92 | |||
| 8a3fddbe49 |
33 changed files with 717 additions and 640 deletions
|
|
@ -162,6 +162,12 @@ Note that, by applying these playbooks, both the root user and the `counterweigh
|
|||
```bash
|
||||
cp ansible/infra_secrets.yml.example ansible/infra_secrets.yml
|
||||
```
|
||||
> **DEPRECATED (2026-09-11).** Uptime Kuma has been decommissioned. The server
|
||||
> deployment was removed from this repo; what it monitored and how it was set up is
|
||||
> preserved in [`archive/uptime_kuma/`](archive/uptime_kuma/). The monitoring blocks in
|
||||
> the playbooks are kept but inert (`uptime_kuma_enabled: false`) so the check logic
|
||||
> survives for whatever replaces it. The credentials below no longer exist in the vault.
|
||||
|
||||
* Edit `ansible/infra_secrets.yml` and add your Uptime Kuma credentials:
|
||||
```yaml
|
||||
uptime_kuma_username: "admin"
|
||||
|
|
|
|||
|
|
@ -49,6 +49,12 @@ Checklist:
|
|||
|
||||
## Uptime Kuma
|
||||
|
||||
> **DEPRECATED (2026-09-11).** Uptime Kuma has been decommissioned. The server
|
||||
> deployment was removed from this repo; what it monitored and how it was set up is
|
||||
> preserved in [`archive/uptime_kuma/`](archive/uptime_kuma/). The monitoring blocks in
|
||||
> the playbooks are kept but inert (`uptime_kuma_enabled: false`) so the check logic
|
||||
> survives for whatever replaces it. The credentials below no longer exist in the vault.
|
||||
|
||||
Uptime Kuma gets used to monitor the availability of services, keep track of their uptime and notify issues.
|
||||
|
||||
### Deploy
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ Assumes that you've set `ansible/.vault_pass` with `chmod 600`.
|
|||
+ Plan install
|
||||
+ File based config
|
||||
+ Crossbackup to Desky via rsync
|
||||
* Uptime Kuma
|
||||
* ~~Uptime Kuma~~ — decommissioned 2026-09-11, see `archive/uptime_kuma/`
|
||||
+ Deployed on Vipy
|
||||
+ Crossbackup to Desky via rsync
|
||||
* Vaultwarden
|
||||
|
|
|
|||
|
|
@ -1,45 +1,60 @@
|
|||
$ANSIBLE_VAULT;1.1;AES256
|
||||
65343264303166346334396163363362326334626531336363363766326135393462373564313539
|
||||
6633346163343664393232363965383334303563396236360a316265623239333431636133306663
|
||||
65623237393564323936303936633036343137646637633963396166313462626165616463616665
|
||||
3235373562626238640a636163623535376565373835653831666361636563616230353639626131
|
||||
38393530363461346334356437613934306330666563326661343465653362313038346535386337
|
||||
62623964633764343964653061373137366539326433396231396339313231633632353465323139
|
||||
33333866383834376165303964353639386234646535626333363932333764646137663036303530
|
||||
32326635343631623535323830333934376466323338353234323464666435383436633139343037
|
||||
62666333383231356163383530353339336230373431616665333638633234656231393166303639
|
||||
32386134386264613839313564316164336461373738646630636630363731643066633132336636
|
||||
64663532663661653539653431353763303436323234383864353064333631643435633733366435
|
||||
32656332626633313134623361343965643962663134613363626265353865643738363738316232
|
||||
62356136623166303038653830393138646637636335366362323239316333616331383765663861
|
||||
33643331323766646463663862396232306233343134326436326235336165616662383636616539
|
||||
39373962336264636363303734343666646534343733666632626338393936393032626130643233
|
||||
30633963656166343834396431323233363036353165623934336532333662323932336630636235
|
||||
63326631366234383732316464383364316337393034303433646365343763633135336336376161
|
||||
33326436303863326666616234396438623864333538313363623261353962336430316132343830
|
||||
36353761326133666166393930343233643861366138363930623362336566386230316236353365
|
||||
65663632383436333536636161393133316334376262653330303238636431353966646666663665
|
||||
30386137623066343135616534323336313162643066636330323934646162303362373838313532
|
||||
61386163356537613334616537656134373835326265393765303436396233383239393365336136
|
||||
64623130383538306331323939386634316663663263306362363830383930346232313965613035
|
||||
33353235663230663635316136666335343233646539613832643431393134303865616232636435
|
||||
66366437353863336235646438353431616465396365373562636461623938303663326461656134
|
||||
66353735343237363164326236663363376333316163353462626234393861663535323463623233
|
||||
66623934336662323830616362653035353563343564636431383837643961303637366131633132
|
||||
33376133376465623030643935643737636339333236316566636663323934626265633863343963
|
||||
38626563323166343264643465626264393838643330393739386330656461656561306539653232
|
||||
63393838626233386531353063366131366237633162393537363963633361386238643232336230
|
||||
36363062386262303364303736373061316265373730366437326166336163386335623665323234
|
||||
35383865646466363534383833653764303833323230613863313735393264336132303934633465
|
||||
65616138636134613361316539343739353735666538653438333264623034306633663634306438
|
||||
33643165353534623039626536636433373963383866303535333931633633393138663464336562
|
||||
36643432366233323235613139626236346135633237613265343933646434373939396265626366
|
||||
34313835346463303132326537323166363032306133623662343736393435383330356433306138
|
||||
65653931613832313832323936353638303937613863646430633266306330656135386533306462
|
||||
30663366396566393134653663356531316639303635343236666333363637636433336533356663
|
||||
35346261363134326165316463626439306130653165636134616434663736616666643963336464
|
||||
61643834613164336234386237393333636234306162306563363430646262363963366666653666
|
||||
64323036323731626236343361613566643565666138386631633462613836613766626562353934
|
||||
32363936626466346464356131653232326330386239666638626333346238623964383666393961
|
||||
38393264663636353161663636393733396332333838333962393439346533353332653362356230
|
||||
62613039376539636363
|
||||
61356165613635386631393135656434646436303665313031346566323336313138353433316463
|
||||
3363323534613064643132663335623238366431393062340a346538396662306537663163623366
|
||||
38626166383933616331623231373137306562623637313263333237633661663436666266616433
|
||||
3862346438643638650a306634333535653633613534646630386131333236366538333765323333
|
||||
38656163303837303732663561373232393132343331663164656262393730326434373731333636
|
||||
36613538646431396536363936336562616431656665653965373864633366663836353434626434
|
||||
34383932373461333564303439623565383661646365386665393831383463663662356536356236
|
||||
36373964666236626465366161636135393734356536633466383262326537343833636630343738
|
||||
62353066316131613737373162643363653662656261363465386364323962656537373061373032
|
||||
33343763353464383438363438343965653532393831343930393562633630383932653862623637
|
||||
38386239353237356631646436356166373961333464396639383538383662326534343339313330
|
||||
65373339356364636634616532363832386631323062363530313861336238353261353334306235
|
||||
62616338396431316537346638656365356564346666366366343638356261623664393263323937
|
||||
30343261363562383332323462336435376664386134646562643836363834313237373631353731
|
||||
35653535663864643266313332356635363262363533663232656531373130336539633066376139
|
||||
32316665393831663035623962656364363831333563366135636164346335383738363336663566
|
||||
63356532643563393939383635386462663561386434323939303431653438653131363538383034
|
||||
33623933333464363032656636643033326162626163353633343062633966343332383138363963
|
||||
36383831663562616533316436366566323061386535343538393861383462333166343562316633
|
||||
30623665623035393537393965626363323132656433313339396233356666346634316332616336
|
||||
37363635363330323230373332326565343530653335383437373230366563366237633665626331
|
||||
66623336626230663361636439316337393865383035326136653264666438666566646132353036
|
||||
38616264313833316536623238633339373466613866626366383835656638623863323838653030
|
||||
63303938376164653966356435386333363731656666313234663535666165646233313137343563
|
||||
36386437393139656438333262383437656666343831313239323961373637653163643664356565
|
||||
62346431393133656530316262303763646165643336396661666431383436323562336137653031
|
||||
62626538373839613734396366653065306534636630346338316237616161613037616364356431
|
||||
38643965376133616161336633383664326230383435363334353137303162663738313331346238
|
||||
39356161616533616134356231323530306338333162343363353531303263636632613036386638
|
||||
63633136386232306234323936303563646466313935326631396565383432386130656638616266
|
||||
32383334363237336539396665336366643764633131643663643137376438323666326435626461
|
||||
64346633636431393137633537306431646564386565303933636434386462346630626537346438
|
||||
32623333666133303061646564366366326665363163396262633164323631636337346130303239
|
||||
38373936663337356134666132303165393365663763396362623434633737373538653566646134
|
||||
62316164396438303532616266313062326666633130656338653139376634306664633031333037
|
||||
31636166306565353334633435656233336233363664306264626237623366336161303134353433
|
||||
63383739666462623336386537346662633666626466393039653439346436653937633537396436
|
||||
35393339383066326630353066623132333034656539363561346462626265363263303535343961
|
||||
39316461616630326539613731303039613736393633373338646266323938326162373831346336
|
||||
30656130343463366534323030646238313465306266383034623065636665623366333063383736
|
||||
38373063393837306462303564643962373334343139626338623935336435643730646532633630
|
||||
66363730386636633639346463363365343239373265303738353732653633653437636130636664
|
||||
39386365353334653765343335303263363461313965383664326563333734626533376436626530
|
||||
63353163323637303730353564383733653365613635353764333266393532653663326533646132
|
||||
39313763373735323835626437306435373238653432393936643165663663656665316132653330
|
||||
35383038353532656434366336346235363563636264303734633138323963396562306232646236
|
||||
38366536306561653937336333373434336164663336613839353439356435333833396363636437
|
||||
38323934613735643363656233333037336465336564313966623063376566663030303230323262
|
||||
65643564666534326234306164343365383632333061316238623565353538313538396364313337
|
||||
35336230313339643736653238386231343661623337306236383665356632366236356335323530
|
||||
66373831616239376231636361333430343433303233393066323865663434643433303832373262
|
||||
36366534646161323130393931626362626139663139643263366639656531613436313533363130
|
||||
65643736363833333939613566663339623964333262643863333030623138633464386238613934
|
||||
31323639333234336264313663376465323737353766643839303665313737336534386665363034
|
||||
30326439666433373232306136306365343764643434306561343339353132346430646436343362
|
||||
32333765616262363930353435616563333736313533653339656231316230346166363335356638
|
||||
37333561366339613136306438306130343230663732333862663838396463623661303961336433
|
||||
65646332373139303462303633346432366530643130366133363937653739653036366136373434
|
||||
343864373734666431326239373866313734
|
||||
|
|
|
|||
|
|
@ -1,45 +1,60 @@
|
|||
$ANSIBLE_VAULT;1.1;AES256
|
||||
65343264303166346334396163363362326334626531336363363766326135393462373564313539
|
||||
6633346163343664393232363965383334303563396236360a316265623239333431636133306663
|
||||
65623237393564323936303936633036343137646637633963396166313462626165616463616665
|
||||
3235373562626238640a636163623535376565373835653831666361636563616230353639626131
|
||||
38393530363461346334356437613934306330666563326661343465653362313038346535386337
|
||||
62623964633764343964653061373137366539326433396231396339313231633632353465323139
|
||||
33333866383834376165303964353639386234646535626333363932333764646137663036303530
|
||||
32326635343631623535323830333934376466323338353234323464666435383436633139343037
|
||||
62666333383231356163383530353339336230373431616665333638633234656231393166303639
|
||||
32386134386264613839313564316164336461373738646630636630363731643066633132336636
|
||||
64663532663661653539653431353763303436323234383864353064333631643435633733366435
|
||||
32656332626633313134623361343965643962663134613363626265353865643738363738316232
|
||||
62356136623166303038653830393138646637636335366362323239316333616331383765663861
|
||||
33643331323766646463663862396232306233343134326436326235336165616662383636616539
|
||||
39373962336264636363303734343666646534343733666632626338393936393032626130643233
|
||||
30633963656166343834396431323233363036353165623934336532333662323932336630636235
|
||||
63326631366234383732316464383364316337393034303433646365343763633135336336376161
|
||||
33326436303863326666616234396438623864333538313363623261353962336430316132343830
|
||||
36353761326133666166393930343233643861366138363930623362336566386230316236353365
|
||||
65663632383436333536636161393133316334376262653330303238636431353966646666663665
|
||||
30386137623066343135616534323336313162643066636330323934646162303362373838313532
|
||||
61386163356537613334616537656134373835326265393765303436396233383239393365336136
|
||||
64623130383538306331323939386634316663663263306362363830383930346232313965613035
|
||||
33353235663230663635316136666335343233646539613832643431393134303865616232636435
|
||||
66366437353863336235646438353431616465396365373562636461623938303663326461656134
|
||||
66353735343237363164326236663363376333316163353462626234393861663535323463623233
|
||||
66623934336662323830616362653035353563343564636431383837643961303637366131633132
|
||||
33376133376465623030643935643737636339333236316566636663323934626265633863343963
|
||||
38626563323166343264643465626264393838643330393739386330656461656561306539653232
|
||||
63393838626233386531353063366131366237633162393537363963633361386238643232336230
|
||||
36363062386262303364303736373061316265373730366437326166336163386335623665323234
|
||||
35383865646466363534383833653764303833323230613863313735393264336132303934633465
|
||||
65616138636134613361316539343739353735666538653438333264623034306633663634306438
|
||||
33643165353534623039626536636433373963383866303535333931633633393138663464336562
|
||||
36643432366233323235613139626236346135633237613265343933646434373939396265626366
|
||||
34313835346463303132326537323166363032306133623662343736393435383330356433306138
|
||||
65653931613832313832323936353638303937613863646430633266306330656135386533306462
|
||||
30663366396566393134653663356531316639303635343236666333363637636433336533356663
|
||||
35346261363134326165316463626439306130653165636134616434663736616666643963336464
|
||||
61643834613164336234386237393333636234306162306563363430646262363963366666653666
|
||||
64323036323731626236343361613566643565666138386631633462613836613766626562353934
|
||||
32363936626466346464356131653232326330386239666638626333346238623964383666393961
|
||||
38393264663636353161663636393733396332333838333962393439346533353332653362356230
|
||||
62613039376539636363
|
||||
34616531626537376463326332306434383163393761363536633133363161373631376437653234
|
||||
3831656536313531343433376264643261396634633965370a303931336236323766313065636535
|
||||
31343338616364386132623232373266663665353563666535383232666262663062323864303932
|
||||
3439373734316639650a633732333064633335383833663261326464336538636666323063646331
|
||||
66653464636534663935616461636132613162303530663237376661343338396133323431623561
|
||||
30303563303465633231306339326561313533333536376433393130376634303932643339656336
|
||||
30616130343733626162366561393939393766623138616537393032376665396139333561623830
|
||||
33623130336235633034666561383165616439316334323664623661343438663733373833306335
|
||||
30396165313731636435636263353133326135346236323030653734353831626238666663656364
|
||||
62386164363361373464383730333733626333333736306535336635613634646535383237326332
|
||||
37636532663933663739303634333235343137333363316430643263326231613635643633636437
|
||||
30336462633233396430633939616661643261666136656363363461343230653738613166346434
|
||||
63376363666462346539343063343562623962303130616535306439653134633630353963373337
|
||||
64313239353162363862643432666438383330636638333464323731643163643236313535313030
|
||||
65656231383738356537326661663163376634613031396436646633376139313237343534653065
|
||||
64323532346133313265346334353530393633396339316330366536646565353836396662303866
|
||||
65373030393463306664623235626437613965303837313365373632643935656630303936373837
|
||||
64663539623764656636613263346638376665626262663430333231633735653563643864343835
|
||||
62303637383332653366383066326536316336306539623230353066343739316430356437313365
|
||||
33323031613130643832636133636263303565623330306135333762363036633737343933623437
|
||||
33633436363062643436376632336235666330656265316333323361316430656631383734343238
|
||||
65616366666536363866343361666563643336306532666332643230656264303565353032393932
|
||||
36613738326239376161383064646634623639356439663965323237303361343838373737636235
|
||||
39656465333063633136643463356564636537326339653033633063366265636138656466646264
|
||||
32643961343863656464353439346531633036613138353333353631626665396239326465303632
|
||||
39336664333038636435366333623336353963323535316436646136313739373537376537353735
|
||||
66333265633232346536313933333836643439656666636236626266323333383935383565616139
|
||||
38626133356364613562393664643563346539366364636332613162663337356232333735393431
|
||||
30343635393462356431646336636663333735343164616261343836363366616162613563613066
|
||||
66333034613234626431356536323832393466363135653231336238356334353638613838626430
|
||||
63636630313533363563376161663637353362383431663130646666646433353864373736613662
|
||||
62343666633862643839666532656132653939663437373164393536653739376265303130353636
|
||||
62616538326330333136626238306133363634326365366637363961333635356133613564373131
|
||||
64626139656633663065353862343135393233333231386166346532656534623361623061336434
|
||||
37616565626134333863376532393861376132323434656433613731613834633963386635353336
|
||||
39653263346637303836663763653264396139383363616461393333333362616332663863363834
|
||||
61613832326466646133626337663364333566326633313664613236346135653332373035313034
|
||||
62356530313065393737393634313166313039616635363365633031336434396463326462316236
|
||||
62353838636533303664663132353838636632353733316639643964666139383539333761663531
|
||||
37366530373165653063303032383461326535613336343635626538373635356266396666346133
|
||||
61383434323565306438356634646338666232363238393932353365363461376130323363363236
|
||||
34643862653937353461383265663933646264373365623465313666643662633334366437646434
|
||||
34343332613832366235663563353435323738356339383338333361383561336366376238393237
|
||||
38656265663164376666616366623062393530366261623361383365376235643035353838313235
|
||||
32396430376139313430316439333539343266393965353030636638656661316137313437663832
|
||||
64366661323865383262323036613230316233666566386133363633303931323464663238323861
|
||||
62333132346165353830653062353763306232366563323430383933653163373562326536393362
|
||||
66353931376262383931613931303034356537363137366235643430323465623162363031373034
|
||||
64653563666533363062333831336463376530306639616631303266386136666233653638653732
|
||||
31313537393838333730303235363661326333646531653935633935373362303732653565656438
|
||||
36626330623063373832333739643666396135653838643164376264393863646433353036643731
|
||||
34623636623366353466333237373265323936643134613230326565303663306431373634356334
|
||||
37613732393262626135306632623336613364323632316636623037656538313236666562633438
|
||||
37306361333130376538366232393637646263656239303431623963626265386634313735373162
|
||||
64393733303132383464386330626135336237303563326238633437346164333738646431333730
|
||||
62616533363638643261306565373835303832313539656564386132393863373039653938616261
|
||||
36343031356361336563316230343433633033353130373933313361326164633765316433616162
|
||||
62356338393634653330623933313433343630386264396337373532376335316362333164363963
|
||||
363663666365336564663232363462613162
|
||||
|
|
|
|||
|
|
@ -2,19 +2,20 @@
|
|||
vipy ansible_host=167.172.107.33 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
watchtower ansible_host=164.92.239.72 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
spacey ansible_host=64.227.112.128 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
|
||||
[nodito_host]
|
||||
nodito ansible_host=192.168.1.139 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
|
||||
|
||||
# Requires the tailnet to be up on the control node.
|
||||
[nodito_vms]
|
||||
knots_box_local ansible_host=192.168.1.135 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
fulcrum_box_local ansible_host=192.168.1.142 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
mempool_box_local ansible_host=192.168.1.140 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
memos_box_local ansible_host=192.168.1.130 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
forgejo_runner_local ansible_host=192.168.1.147 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
arbret_staging_local ansible_host=192.168.1.142 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
small_backups_local ansible_host=192.168.1.148 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
nonkeiwaisi_local ansible_host=192.168.1.151 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
knots_box_local ansible_host=knots-box lan_ip=192.168.1.135 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
fulcrum_box_local ansible_host=fulcrum-box lan_ip=192.168.1.140 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
mempool_box_local ansible_host=mempool-box lan_ip=192.168.1.142 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
memos_box_local ansible_host=memos-box lan_ip=192.168.1.145 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
forgejo_runner_local ansible_host=forgejo-runner-box lan_ip=192.168.1.132 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
arbret_staging_local ansible_host=arbret-staging-box lan_ip=192.168.1.147 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
small_backups_local ansible_host=small-backups-box lan_ip=192.168.1.131 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
nonkeiwaisi_local ansible_host=nonkeiwaisi-box lan_ip=192.168.1.151 ansible_user=counterweight ansible_port=22 ansible_ssh_private_key_file=~/.ssh/counterganzua
|
||||
|
||||
# Local connection to laptop: this assumes you're running ansible commands from your personal laptop
|
||||
[lapy]
|
||||
|
|
@ -58,4 +59,13 @@ localhost
|
|||
[managed:children]
|
||||
vps
|
||||
nodito_host
|
||||
nodito_vms
|
||||
nodito_vms
|
||||
|
||||
# Hosts that run Caddy and therefore have /etc/caddy/sites-enabled.
|
||||
[caddy:children]
|
||||
edge
|
||||
monitoring
|
||||
vpn_control
|
||||
|
||||
[backup_store]
|
||||
small_backups_local
|
||||
|
|
|
|||
118
ansible/roles/caddy_site/README.md
Normal file
118
ansible/roles/caddy_site/README.md
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
# `caddy_site`
|
||||
|
||||
Writes one Caddy site file into `{{ caddy_sites_dir }}`, makes sure the main
|
||||
Caddyfile imports that directory, validates the result, and reloads Caddy once.
|
||||
|
||||
Replaces the four-task block that was copy-pasted into 10 playbooks.
|
||||
|
||||
Runs on any host in the `[caddy]` group — `edge` (vipy), `monitoring`
|
||||
(watchtower) and `vpn_control` (spacey).
|
||||
|
||||
## Usage
|
||||
|
||||
```yaml
|
||||
- ansible.builtin.include_role:
|
||||
name: caddy_site
|
||||
vars:
|
||||
caddy_site_name: forgejo # -> forgejo.conf
|
||||
caddy_site_domain: "{{ forgejo_domain }}"
|
||||
caddy_site_upstream: "localhost:{{ forgejo_port }}"
|
||||
```
|
||||
|
||||
Use `include_role`, not a `roles:` block, so the call stays in task order next
|
||||
to the tasks it depends on. Variables passed this way are scoped to the include
|
||||
and do not leak into later calls — so **every call must pass everything it
|
||||
needs**; nothing carries over.
|
||||
|
||||
## Shapes
|
||||
|
||||
Pick exactly one of `caddy_site_upstream`, `caddy_site_root`, `caddy_site_body`.
|
||||
|
||||
| Want | Set |
|
||||
|---|---|
|
||||
| `reverse_proxy host:port` | `caddy_site_upstream` |
|
||||
| static `root *` + `file_server` | `caddy_site_root` |
|
||||
| anything else | `caddy_site_body` (raw, indented 4 for you) |
|
||||
|
||||
`caddy_site_upstream` accepts two modifiers, which add a block to the
|
||||
`reverse_proxy`:
|
||||
|
||||
- `caddy_site_headers_up: {"X-Forwarded-Host": "..."}`
|
||||
- `caddy_site_resolvers: "100.100.100.100"` — Tailscale MagicDNS
|
||||
|
||||
and `caddy_site_basic_auth` wraps the site in a `basic_auth` block.
|
||||
|
||||
## `caddy_site_basic_auth` is a LIST, not a dict
|
||||
|
||||
```yaml
|
||||
caddy_site_basic_auth:
|
||||
- user: "{{ datum_dashboard_username }}"
|
||||
hash: "{{ datum_dashboard_password_hash }}"
|
||||
```
|
||||
|
||||
**Ansible does not template dictionary keys.** With `{ "{{ user }}": "hash" }`
|
||||
the value is rendered and the key is not, so the literal string
|
||||
`{{ datum_dashboard_username }}` lands in the config file. Found while building
|
||||
this role; the `assert` refuses a mapping so it cannot happen again.
|
||||
|
||||
## Secrets and `--diff`
|
||||
|
||||
Rendered site files can carry credentials — `datum-gateway.conf` holds a bcrypt
|
||||
hash — and `--diff` prints rendered content. The template task therefore sets
|
||||
`diff: "{{ caddy_site_reveal | bool }}"`, default `false`, so `--diff` runs are
|
||||
safe everywhere. Pass `-e caddy_site_reveal=true` to see what moved on a site
|
||||
you know is not secret.
|
||||
|
||||
## Validation
|
||||
|
||||
`validate: "caddy validate --adapter caddyfile --config %s"` runs against the
|
||||
rendered temp file before it is moved into place. Verified on vipy that a single
|
||||
site fragment validates cleanly (rc=0, `Valid configuration`) and that a
|
||||
malformed one is rejected (rc=1, with the syntax error and line number). A
|
||||
failed validate leaves the live file untouched, so a broken config can no longer
|
||||
reach a running Caddy.
|
||||
|
||||
What it cannot catch is a conflict with the global `/etc/caddy/Caddyfile`.
|
||||
|
||||
## The reload is a handler
|
||||
|
||||
`Reload caddy` fires **once, at the end of the play**, however many sites
|
||||
notified it. The code this replaced ran `command: systemctl reload caddy`
|
||||
immediately, mid-play. If a later task in the same play needs the new config to
|
||||
be live, flush first:
|
||||
|
||||
```yaml
|
||||
- ansible.builtin.meta: flush_handlers
|
||||
```
|
||||
|
||||
## Known intentional difference
|
||||
|
||||
The `resolvers` block is commented `# Use Tailscale MagicDNS to resolve the
|
||||
upstream hostname` in every case. `datum-gateway` previously said `# Resolve via
|
||||
Tailscale MagicDNS`. Migrating it therefore rewrites one comment line, which
|
||||
Caddy ignores. Every other site renders byte-identical to what its playbook
|
||||
produced.
|
||||
|
||||
## Sites on the hosts that this role does NOT manage
|
||||
|
||||
Four vhosts exist in `/etc/caddy/sites-enabled/` that no playbook writes. They
|
||||
were made by hand. The role only ever writes the one file it is told to, so it
|
||||
leaves them alone — but nothing in the repo records them, and that is why they
|
||||
are listed here. Checked 2026-09-11:
|
||||
|
||||
| File | Host | Serves | State |
|
||||
|---|---|---|---|
|
||||
| `uptime-kuma.conf` | watchtower | `localhost:3001` | **HTTP 302 — still live**, see below |
|
||||
| `arbretstaging.conf` | vipy | `arbret-staging-box:80` via MagicDNS | HTTP 200 |
|
||||
| `bitcoininfra.conf` | vipy | static `file_server` from `/var/www/bitcoin-services-home` | HTTP 200 |
|
||||
| `scriberr.conf` | vipy | `scriberr-box:8080` via MagicDNS | HTTP 502 — upstream down |
|
||||
|
||||
**`uptime-kuma.conf` must not be deleted as dead config.** Uptime Kuma was
|
||||
"decommissioned" in the repo — its playbooks archived and its credentials pulled
|
||||
from the vault — but the container is **still running** on watchtower
|
||||
(`louislam/uptime-kuma:latest`, created 2026-02-07, `restart=unless-stopped`)
|
||||
and is still reachable at its public subdomain. Only the Ansible code was
|
||||
retired; the service was not. See `archive/uptime_kuma/`.
|
||||
|
||||
`scriberr` returning 502 is the one that looks like genuine rot: it proxies to a
|
||||
`scriberr-box` that is not answering, and `scriberr-box` is not in the inventory.
|
||||
23
ansible/roles/caddy_site/defaults/main.yml
Normal file
23
ansible/roles/caddy_site/defaults/main.yml
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
# Required
|
||||
caddy_site_name: "" # file basename -> <name>.conf
|
||||
caddy_site_domain: "" # site address line; may hold several, comma separated
|
||||
|
||||
# Pick exactly one shape
|
||||
caddy_site_upstream: "" # "localhost:3000" -> reverse_proxy
|
||||
caddy_site_root: "" # filesystem path -> root * + file_server
|
||||
caddy_site_body: "" # raw escape hatch for one-off sites; wins over both
|
||||
|
||||
# reverse_proxy modifiers
|
||||
caddy_site_resolvers: "" # "100.100.100.100" for Tailscale MagicDNS
|
||||
caddy_site_headers_up: {} # {"X-Forwarded-Host": "wallet.example.com"}
|
||||
# A LIST, not a dict: Ansible does not template dict *keys*, so a Jinja
|
||||
# expression for the username silently passes through as literal text.
|
||||
caddy_site_basic_auth: [] # [{user: "{{ x_user }}", hash: "{{ x_hash }}"}]
|
||||
|
||||
# Placement. caddy_sites_dir comes from services_config.yml; this is the fallback.
|
||||
caddy_sites_dir: /etc/caddy/sites-enabled
|
||||
|
||||
# Rendered site files can carry credentials (basic_auth hashes), so --diff is
|
||||
# suppressed by default. Pass -e caddy_site_reveal=true to see what moved.
|
||||
caddy_site_reveal: false
|
||||
12
ansible/roles/caddy_site/handlers/main.yml
Normal file
12
ansible/roles/caddy_site/handlers/main.yml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
# Fires once at the end of the play, however many sites notified it.
|
||||
# Anything later in the same play that needs the new config live must be
|
||||
# preceded by `- ansible.builtin.meta: flush_handlers`.
|
||||
# become is explicit because handlers do not inherit it from the task that
|
||||
# notified them. headscale's play runs become: no and elevates per task, so
|
||||
# without this the reload would run unprivileged and fail.
|
||||
- name: Reload caddy
|
||||
become: true
|
||||
ansible.builtin.systemd:
|
||||
name: caddy
|
||||
state: reloaded
|
||||
46
ansible/roles/caddy_site/tasks/main.yml
Normal file
46
ansible/roles/caddy_site/tasks/main.yml
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
---
|
||||
- name: Assert caddy_site parameters are sane
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- caddy_site_name | length > 0
|
||||
- caddy_site_domain | length > 0
|
||||
- (caddy_site_upstream | length > 0) or (caddy_site_root | length > 0) or (caddy_site_body | length > 0)
|
||||
- caddy_site_basic_auth is not mapping
|
||||
fail_msg: >-
|
||||
caddy_site: '{{ caddy_site_name | default("<unnamed>") }}' needs a name, a domain and
|
||||
one of caddy_site_upstream / caddy_site_root / caddy_site_body.
|
||||
caddy_site_basic_auth must be a LIST of {user, hash} — Ansible does not template dict keys.
|
||||
quiet: true
|
||||
|
||||
- name: Ensure Caddy sites-enabled directory exists
|
||||
ansible.builtin.file:
|
||||
path: "{{ caddy_sites_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Ensure Caddyfile imports sites-enabled
|
||||
ansible.builtin.lineinfile:
|
||||
path: /etc/caddy/Caddyfile
|
||||
line: 'import sites-enabled/*'
|
||||
insertafter: EOF
|
||||
state: present
|
||||
create: yes
|
||||
mode: '0644'
|
||||
backup: yes
|
||||
|
||||
# `validate` runs `caddy validate` against the rendered temp file before it is
|
||||
# moved into place: verified on vipy that a single site fragment validates
|
||||
# cleanly (rc=0, "Valid configuration") and that a malformed one is rejected
|
||||
# (rc=1). A failed validate leaves the live file untouched.
|
||||
- name: "Write Caddy site '{{ caddy_site_name }}'"
|
||||
ansible.builtin.template:
|
||||
src: site.conf.j2
|
||||
dest: "{{ caddy_sites_dir }}/{{ caddy_site_name }}.conf"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
validate: "caddy validate --adapter caddyfile --config %s"
|
||||
diff: "{{ caddy_site_reveal | bool }}"
|
||||
notify: Reload caddy
|
||||
34
ansible/roles/caddy_site/templates/site.conf.j2
Normal file
34
ansible/roles/caddy_site/templates/site.conf.j2
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
{{ caddy_site_domain }} {
|
||||
{% if caddy_site_body %}
|
||||
{{ caddy_site_body | trim | indent(4, first=True) }}
|
||||
{% else %}
|
||||
{% if caddy_site_basic_auth %}
|
||||
basic_auth {
|
||||
{% for cred in caddy_site_basic_auth %}
|
||||
{{ cred.user }} {{ cred.hash }}
|
||||
{% endfor %}
|
||||
}
|
||||
{% endif %}
|
||||
{% if caddy_site_root %}
|
||||
root * {{ caddy_site_root }}
|
||||
file_server
|
||||
{% endif %}
|
||||
{% if caddy_site_upstream %}
|
||||
{% if caddy_site_headers_up or caddy_site_resolvers %}
|
||||
reverse_proxy {{ caddy_site_upstream }} {
|
||||
{% for key, value in caddy_site_headers_up.items() %}
|
||||
header_up {{ key }} {{ value }}
|
||||
{% endfor %}
|
||||
{% if caddy_site_resolvers %}
|
||||
# Use Tailscale MagicDNS to resolve the upstream hostname
|
||||
transport http {
|
||||
resolvers {{ caddy_site_resolvers }}
|
||||
}
|
||||
{% endif %}
|
||||
}
|
||||
{% else %}
|
||||
reverse_proxy {{ caddy_site_upstream }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
}
|
||||
62
ansible/roles/socket_proxy/README.md
Normal file
62
ansible/roles/socket_proxy/README.md
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
# `socket_proxy`
|
||||
|
||||
Exposes a service running on a private Tailscale host through a public TCP port
|
||||
on an edge machine, using `systemd-socket-proxyd`. Writes a `.socket` and a
|
||||
`.service` unit, enables the socket, opens the UFW port, and checks the upstream
|
||||
is reachable.
|
||||
|
||||
## Usage
|
||||
|
||||
```yaml
|
||||
- ansible.builtin.include_role:
|
||||
name: socket_proxy
|
||||
vars:
|
||||
socket_proxy_name: fulcrum-ssl # -> fulcrum-ssl-proxy.{socket,service}
|
||||
socket_proxy_description: "Fulcrum SSL" # -> "Fulcrum SSL Proxy Socket"
|
||||
socket_proxy_listen_port: "{{ fulcrum_ssl_port }}"
|
||||
socket_proxy_upstream_host: "{{ fulcrum_tailscale_hostname }}"
|
||||
```
|
||||
|
||||
`socket_proxy_upstream_port` defaults to `socket_proxy_listen_port`, which is
|
||||
what all three current callers want.
|
||||
|
||||
## Optional unit settings
|
||||
|
||||
These exist because the **live** `bitcoin-p2p-proxy` units on vipy carried
|
||||
settings the playbook never wrote. Somebody added them by hand, so running
|
||||
`deploy_bitcoin_knots_playbook.yml` would have silently removed them:
|
||||
|
||||
| Variable | Emits | Why it matters |
|
||||
|---|---|---|
|
||||
| `socket_proxy_free_bind` | `FreeBind=true` in `[Socket]` | Lets the socket bind to an address that is not up yet. Without it the socket can fail to start on boot. |
|
||||
| `socket_proxy_documentation` | `Documentation=` in both units | Cosmetic. |
|
||||
| `socket_proxy_timeout_stop_sec` | `TimeoutStopSec=` | Bounds how long a stop can hang. |
|
||||
| `socket_proxy_log_to_journal` | `StandardOutput=journal` + `StandardError=journal` | Cosmetic on modern systemd, which defaults to the journal anyway. |
|
||||
|
||||
Only `bitcoin-p2p` passes any of them.
|
||||
|
||||
## `socket_proxy_ufw_comment`
|
||||
|
||||
Defaults to `"<description> public access"`, which reproduces the live rule
|
||||
comment for bitcoin-p2p and fulcrum-ssl. **datum-stratum must pass it
|
||||
explicitly** — its live comment is `DATUM Gateway Stratum public access` while
|
||||
the derived default would be `DATUM Stratum public access`, and UFW treats the
|
||||
comment as part of the rule, so the mismatch rewrites the rule on every run.
|
||||
|
||||
## The upstream check never fails the play
|
||||
|
||||
`wait_for` on the upstream carries `failed_when: false`. The proxy is correctly
|
||||
configured whether or not the backend happens to be up, and this is the one task
|
||||
that depends on another machine. The original plays used `ignore_errors: yes`,
|
||||
which prints a red "ignoring" line; `failed_when: false` is the quieter
|
||||
equivalent.
|
||||
|
||||
## Restarts
|
||||
|
||||
The handler restarts the `.socket`, not the `.service` — that is what picks up a
|
||||
changed unit; the service is started by the socket on the next connection.
|
||||
|
||||
**Restarting a socket drops connections that are currently open through it.**
|
||||
For bitcoin-p2p that means peers reconnect; for datum-stratum it means a mining
|
||||
client has to reconnect and may lose in-flight shares. The handler only fires
|
||||
when a unit file actually changes.
|
||||
17
ansible/roles/socket_proxy/defaults/main.yml
Normal file
17
ansible/roles/socket_proxy/defaults/main.yml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
# Required
|
||||
socket_proxy_name: "" # "bitcoin-p2p" -> bitcoin-p2p-proxy.{socket,service}
|
||||
socket_proxy_description: "" # "Bitcoin P2P" -> "Bitcoin P2P Proxy Socket"
|
||||
socket_proxy_listen_port: 0 # public port on the edge host
|
||||
socket_proxy_upstream_host: "" # Tailscale hostname, e.g. "knots-box"
|
||||
|
||||
# Optional
|
||||
socket_proxy_upstream_port: "" # defaults to socket_proxy_listen_port
|
||||
socket_proxy_documentation: "" # Documentation= in both units
|
||||
socket_proxy_free_bind: false # FreeBind=true: bind before the address is up
|
||||
socket_proxy_timeout_stop_sec: "" # TimeoutStopSec=
|
||||
socket_proxy_log_to_journal: false # StandardOutput/StandardError=journal
|
||||
|
||||
# Firewall
|
||||
socket_proxy_ufw_proto: tcp
|
||||
socket_proxy_ufw_comment: "" # defaults to "<description> public access"
|
||||
8
ansible/roles/socket_proxy/handlers/main.yml
Normal file
8
ansible/roles/socket_proxy/handlers/main.yml
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
# Restarting the .socket is what picks up a changed unit; the .service is
|
||||
# started by the socket on the next connection.
|
||||
- name: Restart socket proxy
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ socket_proxy_name }}-proxy.socket"
|
||||
state: restarted
|
||||
daemon_reload: yes
|
||||
54
ansible/roles/socket_proxy/tasks/main.yml
Normal file
54
ansible/roles/socket_proxy/tasks/main.yml
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
---
|
||||
- name: Assert socket_proxy parameters are sane
|
||||
ansible.builtin.assert:
|
||||
that:
|
||||
- socket_proxy_name | length > 0
|
||||
- socket_proxy_description | length > 0
|
||||
- socket_proxy_listen_port | int > 0
|
||||
- socket_proxy_upstream_host | length > 0
|
||||
fail_msg: >-
|
||||
socket_proxy: '{{ socket_proxy_name | default("<unnamed>") }}' needs a name,
|
||||
a description, a listen port and an upstream host.
|
||||
quiet: true
|
||||
|
||||
- name: "Create the {{ socket_proxy_name }}-proxy socket unit"
|
||||
ansible.builtin.template:
|
||||
src: proxy.socket.j2
|
||||
dest: "/etc/systemd/system/{{ socket_proxy_name }}-proxy.socket"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
notify: Restart socket proxy
|
||||
|
||||
- name: "Create the {{ socket_proxy_name }}-proxy service unit"
|
||||
ansible.builtin.template:
|
||||
src: proxy.service.j2
|
||||
dest: "/etc/systemd/system/{{ socket_proxy_name }}-proxy.service"
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
notify: Restart socket proxy
|
||||
|
||||
- name: "Enable and start the {{ socket_proxy_name }}-proxy socket"
|
||||
ansible.builtin.systemd:
|
||||
name: "{{ socket_proxy_name }}-proxy.socket"
|
||||
enabled: yes
|
||||
state: started
|
||||
daemon_reload: yes
|
||||
|
||||
- name: "Allow the {{ socket_proxy_name }} port through UFW"
|
||||
community.general.ufw:
|
||||
rule: allow
|
||||
port: "{{ socket_proxy_listen_port | string }}"
|
||||
proto: "{{ socket_proxy_ufw_proto }}"
|
||||
comment: "{{ socket_proxy_ufw_comment | default(socket_proxy_description ~ ' public access', true) }}"
|
||||
|
||||
# Reachability of the upstream over Tailscale. Deliberately non-fatal: the proxy
|
||||
# is still correctly configured if the backend happens to be down, and this is
|
||||
# the one check that depends on another machine being up.
|
||||
- name: "Verify {{ socket_proxy_upstream_host }} is reachable over Tailscale"
|
||||
ansible.builtin.wait_for:
|
||||
host: "{{ socket_proxy_upstream_host }}"
|
||||
port: "{{ socket_proxy_upstream_port | default(socket_proxy_listen_port, true) }}"
|
||||
timeout: 10
|
||||
failed_when: false
|
||||
18
ansible/roles/socket_proxy/templates/proxy.service.j2
Normal file
18
ansible/roles/socket_proxy/templates/proxy.service.j2
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
[Unit]
|
||||
Description={{ socket_proxy_description }} Proxy to {{ socket_proxy_upstream_host }}
|
||||
{% if socket_proxy_documentation %}
|
||||
Documentation={{ socket_proxy_documentation }}
|
||||
{% endif %}
|
||||
Requires={{ socket_proxy_name }}-proxy.socket
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
ExecStart=/lib/systemd/systemd-socket-proxyd {{ socket_proxy_upstream_host }}:{{ socket_proxy_upstream_port | default(socket_proxy_listen_port, true) }}
|
||||
{% if socket_proxy_timeout_stop_sec %}
|
||||
TimeoutStopSec={{ socket_proxy_timeout_stop_sec }}
|
||||
{% endif %}
|
||||
{% if socket_proxy_log_to_journal %}
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
{% endif %}
|
||||
14
ansible/roles/socket_proxy/templates/proxy.socket.j2
Normal file
14
ansible/roles/socket_proxy/templates/proxy.socket.j2
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
[Unit]
|
||||
Description={{ socket_proxy_description }} Proxy Socket
|
||||
{% if socket_proxy_documentation %}
|
||||
Documentation={{ socket_proxy_documentation }}
|
||||
{% endif %}
|
||||
|
||||
[Socket]
|
||||
ListenStream={{ socket_proxy_listen_port }}
|
||||
{% if socket_proxy_free_bind %}
|
||||
FreeBind=true
|
||||
{% endif %}
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
|
|
@ -740,7 +740,7 @@
|
|||
state: restarted
|
||||
|
||||
|
||||
- name: Setup public Bitcoin P2P forwarding on vipy via systemd-socket-proxyd
|
||||
- name: Setup public Bitcoin P2P forwarding on the edge host
|
||||
hosts: edge
|
||||
become: yes
|
||||
vars_files:
|
||||
|
|
@ -753,62 +753,21 @@
|
|||
uptime_kuma_api_url: "https://{{ subdomains.uptime_kuma }}.{{ root_domain }}"
|
||||
|
||||
tasks:
|
||||
- name: Create Bitcoin P2P proxy socket unit
|
||||
copy:
|
||||
dest: /etc/systemd/system/bitcoin-p2p-proxy.socket
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Bitcoin P2P Proxy Socket
|
||||
|
||||
[Socket]
|
||||
ListenStream={{ bitcoin_p2p_port }}
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
notify: Restart bitcoin-p2p-proxy socket
|
||||
|
||||
- name: Create Bitcoin P2P proxy service unit
|
||||
copy:
|
||||
dest: /etc/systemd/system/bitcoin-p2p-proxy.service
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Bitcoin P2P Proxy to {{ bitcoin_tailscale_hostname }}
|
||||
Requires=bitcoin-p2p-proxy.socket
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
ExecStart=/lib/systemd/systemd-socket-proxyd {{ bitcoin_tailscale_hostname }}:{{ bitcoin_p2p_port }}
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Reload systemd daemon
|
||||
systemd:
|
||||
daemon_reload: yes
|
||||
|
||||
- name: Enable and start Bitcoin P2P proxy socket
|
||||
systemd:
|
||||
name: bitcoin-p2p-proxy.socket
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: Allow Bitcoin P2P port through UFW
|
||||
ufw:
|
||||
rule: allow
|
||||
port: "{{ bitcoin_p2p_port | string }}"
|
||||
proto: tcp
|
||||
comment: "Bitcoin P2P public access"
|
||||
|
||||
- name: Verify connectivity to knots-box via Tailscale
|
||||
wait_for:
|
||||
host: "{{ bitcoin_tailscale_hostname }}"
|
||||
port: "{{ bitcoin_p2p_port }}"
|
||||
timeout: 10
|
||||
ignore_errors: yes
|
||||
- name: Expose Bitcoin P2P through a socket proxy
|
||||
ansible.builtin.include_role:
|
||||
name: socket_proxy
|
||||
vars:
|
||||
socket_proxy_name: bitcoin-p2p
|
||||
socket_proxy_description: "Bitcoin P2P"
|
||||
socket_proxy_listen_port: "{{ bitcoin_p2p_port }}"
|
||||
socket_proxy_upstream_host: "{{ bitcoin_tailscale_hostname }}"
|
||||
# These four were added by hand on vipy and were NOT in this playbook;
|
||||
# writing the unit without them would have dropped FreeBind, which lets
|
||||
# the socket bind before the address is up.
|
||||
socket_proxy_documentation: "https://github.com/bitcoin/bitcoin"
|
||||
socket_proxy_free_bind: true
|
||||
socket_proxy_timeout_stop_sec: 5
|
||||
socket_proxy_log_to_journal: true
|
||||
|
||||
- name: Display public endpoint
|
||||
when: uptime_kuma_enabled | default(false)
|
||||
|
|
@ -931,8 +890,3 @@
|
|||
- /tmp/setup_bitcoin_p2p_tcp_monitor.py
|
||||
- /tmp/ansible_bitcoin_p2p_config.yml
|
||||
|
||||
handlers:
|
||||
- name: Restart bitcoin-p2p-proxy socket
|
||||
systemd:
|
||||
name: bitcoin-p2p-proxy.socket
|
||||
state: restarted
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
- name: Install and configure Caddy on Debian 12
|
||||
hosts: vps
|
||||
hosts: caddy
|
||||
become: yes
|
||||
|
||||
tasks:
|
||||
|
|
|
|||
|
|
@ -487,7 +487,7 @@
|
|||
# ===========================================
|
||||
# Caddy Reverse Proxy for DATUM Dashboard (on vipy)
|
||||
# ===========================================
|
||||
- name: Configure Caddy reverse proxy for DATUM Gateway dashboard on vipy
|
||||
- name: Configure Caddy reverse proxy for DATUM Gateway dashboard on the edge host
|
||||
hosts: edge
|
||||
become: yes
|
||||
vars_files:
|
||||
|
|
@ -498,64 +498,29 @@
|
|||
vars:
|
||||
datum_gateway_subdomain: "{{ subdomains.datum_gateway }}"
|
||||
datum_gateway_domain: "{{ datum_gateway_subdomain }}.{{ root_domain }}"
|
||||
caddy_sites_dir: "{{ caddy_sites_dir }}"
|
||||
uptime_kuma_api_url: "https://{{ subdomains.uptime_kuma }}.{{ root_domain }}"
|
||||
|
||||
tasks:
|
||||
- name: Ensure Caddy sites-enabled directory exists
|
||||
file:
|
||||
path: "{{ caddy_sites_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0755"
|
||||
- name: Publish the DATUM Gateway dashboard through Caddy
|
||||
ansible.builtin.include_role:
|
||||
name: caddy_site
|
||||
vars:
|
||||
caddy_site_name: datum-gateway
|
||||
caddy_site_domain: "{{ datum_gateway_domain }}"
|
||||
caddy_site_upstream: "knots-box:{{ datum_gateway_api_port }}"
|
||||
caddy_site_resolvers: "100.100.100.100"
|
||||
caddy_site_basic_auth:
|
||||
- user: "{{ datum_dashboard_username }}"
|
||||
hash: "{{ datum_dashboard_password_hash }}"
|
||||
|
||||
- name: Ensure Caddyfile includes import directive for sites-enabled
|
||||
lineinfile:
|
||||
path: /etc/caddy/Caddyfile
|
||||
line: "import sites-enabled/*"
|
||||
insertafter: EOF
|
||||
state: present
|
||||
backup: yes
|
||||
create: yes
|
||||
mode: "0644"
|
||||
|
||||
- name: Create Caddy reverse proxy config for DATUM Gateway dashboard
|
||||
copy:
|
||||
dest: "{{ caddy_sites_dir }}/datum-gateway.conf"
|
||||
content: |
|
||||
{{ datum_gateway_domain }} {
|
||||
basic_auth {
|
||||
{{ datum_dashboard_username }} {{ datum_dashboard_password_hash }}
|
||||
}
|
||||
reverse_proxy knots-box:{{ datum_gateway_api_port }} {
|
||||
# Resolve via Tailscale MagicDNS
|
||||
transport http {
|
||||
resolvers 100.100.100.100
|
||||
}
|
||||
}
|
||||
}
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: Validate Caddy config
|
||||
command: caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
|
||||
register: caddy_validate
|
||||
# The role validates the site fragment on its own. This re-validates the
|
||||
# whole assembled Caddyfile, which is the only thing that catches a
|
||||
# conflict between this site and another. Kept from the hand-rolled
|
||||
# version; the other nine services never had it.
|
||||
- name: Validate the assembled Caddyfile
|
||||
ansible.builtin.command: caddy validate --config /etc/caddy/Caddyfile --adapter caddyfile
|
||||
changed_when: false
|
||||
|
||||
- name: Display Caddy validation output
|
||||
debug:
|
||||
msg: "{{ caddy_validate.stdout_lines + caddy_validate.stderr_lines }}"
|
||||
|
||||
- name: Reload Caddy
|
||||
command: systemctl reload caddy
|
||||
register: caddy_reload
|
||||
|
||||
- name: Display Caddy reload output
|
||||
debug:
|
||||
msg: "{{ caddy_reload.stdout_lines + caddy_reload.stderr_lines }}"
|
||||
|
||||
- name: Display DATUM Gateway dashboard URL
|
||||
when: uptime_kuma_enabled | default(false)
|
||||
debug:
|
||||
|
|
@ -685,7 +650,7 @@
|
|||
# Miners connect to vipy:23334; traffic is forwarded to knots-box:23334
|
||||
# over the Tailscale network, matching the Bitcoin P2P proxy pattern.
|
||||
# ===========================================
|
||||
- name: Setup public Stratum port forwarding on vipy via systemd-socket-proxyd
|
||||
- name: Setup public Stratum port forwarding on the edge host
|
||||
hosts: edge
|
||||
become: yes
|
||||
vars_files:
|
||||
|
|
@ -698,62 +663,17 @@
|
|||
uptime_kuma_api_url: "https://{{ subdomains.uptime_kuma }}.{{ root_domain }}"
|
||||
|
||||
tasks:
|
||||
- name: Create Stratum proxy socket unit
|
||||
copy:
|
||||
dest: /etc/systemd/system/datum-stratum-proxy.socket
|
||||
content: |
|
||||
[Unit]
|
||||
Description=DATUM Stratum Proxy Socket
|
||||
|
||||
[Socket]
|
||||
ListenStream={{ datum_gateway_stratum_port }}
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
notify: Restart datum-stratum-proxy socket
|
||||
|
||||
- name: Create Stratum proxy service unit
|
||||
copy:
|
||||
dest: /etc/systemd/system/datum-stratum-proxy.service
|
||||
content: |
|
||||
[Unit]
|
||||
Description=DATUM Stratum Proxy to {{ datum_tailscale_hostname }}
|
||||
Requires=datum-stratum-proxy.socket
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
ExecStart=/lib/systemd/systemd-socket-proxyd {{ datum_tailscale_hostname }}:{{ datum_gateway_stratum_port }}
|
||||
owner: root
|
||||
group: root
|
||||
mode: "0644"
|
||||
|
||||
- name: Reload systemd daemon
|
||||
systemd:
|
||||
daemon_reload: yes
|
||||
|
||||
- name: Enable and start Stratum proxy socket
|
||||
systemd:
|
||||
name: datum-stratum-proxy.socket
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: Allow Stratum port through UFW
|
||||
ufw:
|
||||
rule: allow
|
||||
port: "{{ datum_gateway_stratum_port | string }}"
|
||||
proto: tcp
|
||||
comment: "DATUM Gateway Stratum public access"
|
||||
|
||||
- name: Verify connectivity to knots-box Stratum via Tailscale
|
||||
wait_for:
|
||||
host: "{{ datum_tailscale_hostname }}"
|
||||
port: "{{ datum_gateway_stratum_port }}"
|
||||
timeout: 10
|
||||
ignore_errors: yes
|
||||
- name: Expose the DATUM Stratum port through a socket proxy
|
||||
ansible.builtin.include_role:
|
||||
name: socket_proxy
|
||||
vars:
|
||||
socket_proxy_name: datum-stratum
|
||||
socket_proxy_description: "DATUM Stratum"
|
||||
socket_proxy_listen_port: "{{ datum_gateway_stratum_port }}"
|
||||
socket_proxy_upstream_host: "{{ datum_tailscale_hostname }}"
|
||||
# Matches the UFW comment already on vipy; the derived default would
|
||||
# have said "DATUM Stratum" and rewritten the rule.
|
||||
socket_proxy_ufw_comment: "DATUM Gateway Stratum public access"
|
||||
|
||||
- name: Display public Stratum endpoint
|
||||
when: uptime_kuma_enabled | default(false)
|
||||
|
|
@ -880,8 +800,3 @@
|
|||
- /tmp/setup_datum_stratum_tcp_monitor.py
|
||||
- /tmp/ansible_datum_stratum_config.yml
|
||||
|
||||
handlers:
|
||||
- name: Restart datum-stratum-proxy socket
|
||||
systemd:
|
||||
name: datum-stratum-proxy.socket
|
||||
state: restarted
|
||||
|
|
|
|||
|
|
@ -25,4 +25,6 @@ ansible-playbook ansible/services/forgejo-runner/deploy_forgejo_runner_playbook.
|
|||
|
||||
1. On the VM: `systemctl status forgejo-runner` should show active
|
||||
2. In Forgejo: **Site Administration** > **Actions** > **Runners** should show the runner as online
|
||||
3. In Uptime Kuma: the `forgejo-runner-healthcheck` push monitor should be receiving pings
|
||||
3. ~~In Uptime Kuma: the `forgejo-runner-healthcheck` push monitor should be receiving pings~~
|
||||
*(Uptime Kuma was decommissioned 2026-09-11 — this check no longer applies. The
|
||||
healthcheck timer still runs on the host but pushes nowhere. See `archive/uptime_kuma/`.)*
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
- ./forgejo_vars.yml
|
||||
vars:
|
||||
forgejo_subdomain: "{{ subdomains.forgejo }}"
|
||||
caddy_sites_dir: "{{ caddy_sites_dir }}"
|
||||
forgejo_domain: "{{ forgejo_subdomain }}.{{ root_domain }}"
|
||||
uptime_kuma_api_url: "https://{{ subdomains.uptime_kuma }}.{{ root_domain }}"
|
||||
|
||||
|
|
@ -88,35 +87,13 @@
|
|||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: Ensure Caddy sites-enabled directory exists
|
||||
file:
|
||||
path: "{{ caddy_sites_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Ensure Caddyfile includes import directive for sites-enabled
|
||||
lineinfile:
|
||||
path: /etc/caddy/Caddyfile
|
||||
line: 'import sites-enabled/*'
|
||||
insertafter: EOF
|
||||
state: present
|
||||
backup: yes
|
||||
|
||||
- name: Create Caddy reverse proxy configuration for forgejo
|
||||
copy:
|
||||
dest: "{{ caddy_sites_dir }}/forgejo.conf"
|
||||
content: |
|
||||
{{ forgejo_domain }} {
|
||||
reverse_proxy localhost:{{ forgejo_port }}
|
||||
}
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Reload Caddy to apply new config
|
||||
command: systemctl reload caddy
|
||||
- name: Publish Forgejo through Caddy
|
||||
ansible.builtin.include_role:
|
||||
name: caddy_site
|
||||
vars:
|
||||
caddy_site_name: forgejo
|
||||
caddy_site_domain: "{{ forgejo_domain }}"
|
||||
caddy_site_upstream: "localhost:{{ forgejo_port }}"
|
||||
|
||||
# ═════════════════════════════════════════════════════════════════════════
|
||||
# DEPRECATED — Uptime Kuma was decommissioned on 2026-09-11.
|
||||
|
|
|
|||
|
|
@ -540,7 +540,7 @@
|
|||
state: restarted
|
||||
|
||||
|
||||
- name: Setup public Fulcrum SSL forwarding on vipy via systemd-socket-proxyd
|
||||
- name: Setup public Fulcrum SSL forwarding on the edge host
|
||||
hosts: edge
|
||||
become: yes
|
||||
vars_files:
|
||||
|
|
@ -552,62 +552,14 @@
|
|||
uptime_kuma_api_url: "https://{{ subdomains.uptime_kuma }}.{{ root_domain }}"
|
||||
|
||||
tasks:
|
||||
- name: Create Fulcrum SSL proxy socket unit
|
||||
copy:
|
||||
dest: /etc/systemd/system/fulcrum-ssl-proxy.socket
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Fulcrum SSL Proxy Socket
|
||||
|
||||
[Socket]
|
||||
ListenStream={{ fulcrum_ssl_port }}
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
notify: Restart fulcrum-ssl-proxy socket
|
||||
|
||||
- name: Create Fulcrum SSL proxy service unit
|
||||
copy:
|
||||
dest: /etc/systemd/system/fulcrum-ssl-proxy.service
|
||||
content: |
|
||||
[Unit]
|
||||
Description=Fulcrum SSL Proxy to {{ fulcrum_tailscale_hostname }}
|
||||
Requires=fulcrum-ssl-proxy.socket
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
Type=notify
|
||||
ExecStart=/lib/systemd/systemd-socket-proxyd {{ fulcrum_tailscale_hostname }}:{{ fulcrum_ssl_port }}
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Reload systemd daemon
|
||||
systemd:
|
||||
daemon_reload: yes
|
||||
|
||||
- name: Enable and start Fulcrum SSL proxy socket
|
||||
systemd:
|
||||
name: fulcrum-ssl-proxy.socket
|
||||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: Allow Fulcrum SSL port through UFW
|
||||
ufw:
|
||||
rule: allow
|
||||
port: "{{ fulcrum_ssl_port | string }}"
|
||||
proto: tcp
|
||||
comment: "Fulcrum SSL public access"
|
||||
|
||||
- name: Verify connectivity to fulcrum-box via Tailscale
|
||||
wait_for:
|
||||
host: "{{ fulcrum_tailscale_hostname }}"
|
||||
port: "{{ fulcrum_ssl_port }}"
|
||||
timeout: 10
|
||||
ignore_errors: yes
|
||||
- name: Expose Fulcrum SSL through a socket proxy
|
||||
ansible.builtin.include_role:
|
||||
name: socket_proxy
|
||||
vars:
|
||||
socket_proxy_name: fulcrum-ssl
|
||||
socket_proxy_description: "Fulcrum SSL"
|
||||
socket_proxy_listen_port: "{{ fulcrum_ssl_port }}"
|
||||
socket_proxy_upstream_host: "{{ fulcrum_tailscale_hostname }}"
|
||||
|
||||
- name: Display public endpoint
|
||||
when: uptime_kuma_enabled | default(false)
|
||||
|
|
@ -730,9 +682,4 @@
|
|||
- /tmp/setup_fulcrum_ssl_tcp_monitor.py
|
||||
- /tmp/ansible_fulcrum_ssl_config.yml
|
||||
|
||||
handlers:
|
||||
- name: Restart fulcrum-ssl-proxy socket
|
||||
systemd:
|
||||
name: fulcrum-ssl-proxy.socket
|
||||
state: restarted
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
- ./headscale_vars.yml
|
||||
vars:
|
||||
headscale_subdomain: "{{ subdomains.headscale }}"
|
||||
caddy_sites_dir: "{{ caddy_sites_dir }}"
|
||||
headscale_domain: "{{ headscale_subdomain }}.{{ root_domain }}"
|
||||
headscale_base_domain: "tailnet.{{ root_domain }}"
|
||||
headscale_namespace: "{{ service_settings.headscale.namespace }}"
|
||||
|
|
@ -230,39 +229,34 @@
|
|||
port: '3478'
|
||||
proto: udp
|
||||
|
||||
- name: Ensure Caddy sites-enabled directory exists
|
||||
become: yes
|
||||
file:
|
||||
path: "{{ caddy_sites_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Ensure Caddyfile includes import directive for sites-enabled
|
||||
become: yes
|
||||
lineinfile:
|
||||
path: /etc/caddy/Caddyfile
|
||||
line: 'import sites-enabled/*'
|
||||
insertafter: EOF
|
||||
state: present
|
||||
backup: yes
|
||||
|
||||
- name: Create Caddy reverse proxy configuration for headscale
|
||||
become: yes
|
||||
copy:
|
||||
dest: "{{ caddy_sites_dir }}/headscale.conf"
|
||||
content: |
|
||||
{{ headscale_domain }} {
|
||||
reverse_proxy localhost:{{ headscale_port }}
|
||||
- name: Publish headscale through Caddy
|
||||
ansible.builtin.include_role:
|
||||
name: caddy_site
|
||||
# This play is become: no and elevates per task. `apply` is how an
|
||||
# include_role passes become down to the role's tasks - `become:` on
|
||||
# the include itself is rejected. The role's handler sets its own.
|
||||
apply:
|
||||
become: yes
|
||||
vars:
|
||||
caddy_site_name: headscale
|
||||
caddy_site_domain: "{{ headscale_domain }}"
|
||||
# Raw body, and it must stay raw: the /admin* route in front of
|
||||
# Headplane is not expressible as a plain reverse_proxy. The previous
|
||||
# version of this task wrote only `reverse_proxy localhost:8080`, which
|
||||
# would have deleted the admin route and its auth on the next run.
|
||||
caddy_site_body: |
|
||||
@headplane {
|
||||
path /admin*
|
||||
}
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Reload Caddy to apply new config
|
||||
become: yes
|
||||
command: systemctl reload caddy
|
||||
handle @headplane {
|
||||
basicauth {
|
||||
{{ headscale_ui_username }} {{ headscale_ui_password_hash }}
|
||||
}
|
||||
reverse_proxy http://localhost:{{ headplane_port }}
|
||||
}
|
||||
# Headscale API is protected by its own API key authentication
|
||||
# All API operations require a valid Bearer token in the Authorization header
|
||||
reverse_proxy * http://localhost:{{ headscale_port }}
|
||||
|
||||
# ═════════════════════════════════════════════════════════════════════════
|
||||
# DEPRECATED — Uptime Kuma was decommissioned on 2026-09-11.
|
||||
|
|
|
|||
|
|
@ -22,3 +22,6 @@ remote_port: "{{ hostvars.get(remote_host_name, {}).get('ansible_port', 22) }}"
|
|||
# Local backup
|
||||
local_backup_dir: "{{ lookup('env', 'HOME') }}/headscale-backups"
|
||||
backup_script_path: "{{ lookup('env', 'HOME') }}/.local/bin/headscale_backup.sh"
|
||||
|
||||
# Headplane (headscale admin UI), proxied at /admin* behind Caddy basic auth
|
||||
headplane_port: 3000
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
- ./lnbits_vars.yml
|
||||
vars:
|
||||
lnbits_subdomain: "{{ subdomains.lnbits }}"
|
||||
caddy_sites_dir: "{{ caddy_sites_dir }}"
|
||||
lnbits_domain: "{{ lnbits_subdomain }}.{{ root_domain }}"
|
||||
uptime_kuma_api_url: "https://{{ subdomains.uptime_kuma }}.{{ root_domain }}"
|
||||
|
||||
|
|
@ -147,39 +146,15 @@
|
|||
enabled: yes
|
||||
state: started
|
||||
|
||||
- name: Ensure Caddy sites-enabled directory exists
|
||||
file:
|
||||
path: "{{ caddy_sites_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Ensure Caddyfile includes import directive for sites-enabled
|
||||
lineinfile:
|
||||
path: /etc/caddy/Caddyfile
|
||||
line: 'import sites-enabled/*'
|
||||
insertafter: EOF
|
||||
state: present
|
||||
backup: yes
|
||||
create: yes
|
||||
mode: '0644'
|
||||
|
||||
- name: Create Caddy reverse proxy configuration for lnbits
|
||||
copy:
|
||||
dest: "{{ caddy_sites_dir }}/lnbits.conf"
|
||||
content: |
|
||||
{{ lnbits_domain }} {
|
||||
reverse_proxy localhost:{{ lnbits_port }} {
|
||||
header_up X-Forwarded-Host {{ lnbits_domain }}
|
||||
}
|
||||
}
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Reload Caddy to apply new config
|
||||
command: systemctl reload caddy
|
||||
- name: Publish LNBits through Caddy
|
||||
ansible.builtin.include_role:
|
||||
name: caddy_site
|
||||
vars:
|
||||
caddy_site_name: lnbits
|
||||
caddy_site_domain: "{{ lnbits_domain }}"
|
||||
caddy_site_upstream: "localhost:{{ lnbits_port }}"
|
||||
caddy_site_headers_up:
|
||||
X-Forwarded-Host: "{{ lnbits_domain }}"
|
||||
|
||||
# ═════════════════════════════════════════════════════════════════════════
|
||||
# DEPRECATED — Uptime Kuma was decommissioned on 2026-09-11.
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@
|
|||
state: restarted
|
||||
|
||||
|
||||
- name: Configure Caddy reverse proxy for Memos on vipy (proxying via Tailscale)
|
||||
- name: Configure Caddy reverse proxy for Memos on the edge host (via Tailscale)
|
||||
hosts: edge
|
||||
become: yes
|
||||
vars_files:
|
||||
|
|
@ -166,45 +166,18 @@
|
|||
- ./memos_vars.yml
|
||||
vars:
|
||||
memos_subdomain: "{{ subdomains.memos }}"
|
||||
caddy_sites_dir: "{{ caddy_sites_dir }}"
|
||||
memos_domain: "{{ memos_subdomain }}.{{ root_domain }}"
|
||||
uptime_kuma_api_url: "https://{{ subdomains.uptime_kuma }}.{{ root_domain }}"
|
||||
|
||||
tasks:
|
||||
- name: Ensure Caddy sites-enabled directory exists
|
||||
file:
|
||||
path: "{{ caddy_sites_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Ensure Caddyfile includes import directive for sites-enabled
|
||||
lineinfile:
|
||||
path: /etc/caddy/Caddyfile
|
||||
line: 'import sites-enabled/*'
|
||||
insertafter: EOF
|
||||
state: present
|
||||
backup: yes
|
||||
|
||||
- name: Create Caddy reverse proxy configuration for memos (via Tailscale)
|
||||
copy:
|
||||
dest: "{{ caddy_sites_dir }}/memos.conf"
|
||||
content: |
|
||||
{{ memos_domain }} {
|
||||
reverse_proxy {{ memos_tailscale_hostname }}:{{ memos_port }} {
|
||||
# Use Tailscale MagicDNS to resolve the upstream hostname
|
||||
transport http {
|
||||
resolvers 100.100.100.100
|
||||
}
|
||||
}
|
||||
}
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Reload Caddy to apply new config
|
||||
command: systemctl reload caddy
|
||||
- name: Publish Memos through Caddy (via Tailscale)
|
||||
ansible.builtin.include_role:
|
||||
name: caddy_site
|
||||
vars:
|
||||
caddy_site_name: memos
|
||||
caddy_site_domain: "{{ memos_domain }}"
|
||||
caddy_site_upstream: "{{ memos_tailscale_hostname }}:{{ memos_port }}"
|
||||
caddy_site_resolvers: "100.100.100.100"
|
||||
|
||||
- name: Create Uptime Kuma monitor setup script for Memos
|
||||
when: uptime_kuma_enabled | default(false)
|
||||
|
|
|
|||
|
|
@ -603,7 +603,7 @@
|
|||
- /tmp/ansible_mempool_config.yml
|
||||
- /tmp/mempool_push_urls.yml
|
||||
|
||||
- name: Configure Caddy reverse proxy for Mempool on vipy
|
||||
- name: Configure Caddy reverse proxy for Mempool on the edge host
|
||||
hosts: edge
|
||||
become: yes
|
||||
vars_files:
|
||||
|
|
@ -614,47 +614,16 @@
|
|||
vars:
|
||||
mempool_subdomain: "{{ subdomains.mempool }}"
|
||||
mempool_domain: "{{ mempool_subdomain }}.{{ root_domain }}"
|
||||
caddy_sites_dir: "{{ caddy_sites_dir }}"
|
||||
|
||||
tasks:
|
||||
- name: Ensure Caddy sites-enabled directory exists
|
||||
file:
|
||||
path: "{{ caddy_sites_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Ensure Caddyfile includes import directive for sites-enabled
|
||||
lineinfile:
|
||||
path: /etc/caddy/Caddyfile
|
||||
line: 'import sites-enabled/*'
|
||||
insertafter: EOF
|
||||
state: present
|
||||
backup: yes
|
||||
create: yes
|
||||
mode: '0644'
|
||||
|
||||
- name: Create Caddy reverse proxy configuration for Mempool
|
||||
copy:
|
||||
dest: "{{ caddy_sites_dir }}/mempool.conf"
|
||||
content: |
|
||||
{{ mempool_domain }} {
|
||||
reverse_proxy mempool-box:{{ mempool_frontend_port }} {
|
||||
# Use Tailscale MagicDNS to resolve the upstream hostname
|
||||
transport http {
|
||||
resolvers 100.100.100.100
|
||||
}
|
||||
}
|
||||
}
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Reload Caddy to apply new config
|
||||
systemd:
|
||||
name: caddy
|
||||
state: reloaded
|
||||
- name: Publish Mempool through Caddy (via Tailscale)
|
||||
ansible.builtin.include_role:
|
||||
name: caddy_site
|
||||
vars:
|
||||
caddy_site_name: mempool
|
||||
caddy_site_domain: "{{ mempool_domain }}"
|
||||
caddy_site_upstream: "mempool-box:{{ mempool_frontend_port }}"
|
||||
caddy_site_resolvers: "100.100.100.100"
|
||||
|
||||
- name: Display Mempool URL
|
||||
when: uptime_kuma_enabled | default(false)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
- ./ntfy_emergency_app_vars.yml
|
||||
vars:
|
||||
ntfy_emergency_app_subdomain: "{{ subdomains.ntfy_emergency_app }}"
|
||||
caddy_sites_dir: "{{ caddy_sites_dir }}"
|
||||
ntfy_emergency_app_domain: "{{ ntfy_emergency_app_subdomain }}.{{ root_domain }}"
|
||||
ntfy_service_domain: "{{ subdomains.ntfy }}.{{ root_domain }}"
|
||||
ntfy_emergency_app_ntfy_url: "https://{{ ntfy_service_domain }}"
|
||||
|
|
@ -49,35 +48,13 @@
|
|||
args:
|
||||
chdir: "{{ ntfy_emergency_app_dir }}"
|
||||
|
||||
- name: Ensure Caddy sites-enabled directory exists
|
||||
file:
|
||||
path: "{{ caddy_sites_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Ensure Caddyfile includes import directive for sites-enabled
|
||||
lineinfile:
|
||||
path: /etc/caddy/Caddyfile
|
||||
line: 'import sites-enabled/*'
|
||||
insertafter: EOF
|
||||
state: present
|
||||
backup: yes
|
||||
|
||||
- name: Create Caddy reverse proxy configuration for ntfy-emergency-app
|
||||
copy:
|
||||
dest: "{{ caddy_sites_dir }}/ntfy-emergency-app.conf"
|
||||
content: |
|
||||
{{ ntfy_emergency_app_domain }} {
|
||||
reverse_proxy localhost:{{ ntfy_emergency_app_port }}
|
||||
}
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Reload Caddy to apply new config
|
||||
command: systemctl reload caddy
|
||||
- name: Publish ntfy-emergency-app through Caddy
|
||||
ansible.builtin.include_role:
|
||||
name: caddy_site
|
||||
vars:
|
||||
caddy_site_name: ntfy-emergency-app
|
||||
caddy_site_domain: "{{ ntfy_emergency_app_domain }}"
|
||||
caddy_site_upstream: "localhost:{{ ntfy_emergency_app_port }}"
|
||||
|
||||
# ═════════════════════════════════════════════════════════════════════════
|
||||
# DEPRECATED — Uptime Kuma was decommissioned on 2026-09-11.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
- ./ntfy_vars.yml
|
||||
vars:
|
||||
ntfy_subdomain: "{{ subdomains.ntfy }}"
|
||||
caddy_sites_dir: "{{ caddy_sites_dir }}"
|
||||
ntfy_domain: "{{ ntfy_subdomain }}.{{ root_domain }}"
|
||||
|
||||
tasks:
|
||||
|
|
@ -76,42 +75,23 @@
|
|||
shell: |
|
||||
(echo "{{ ntfy_password }}"; echo "{{ ntfy_password }}") | ntfy user add --role=admin "{{ ntfy_username }}"
|
||||
|
||||
- name: Ensure Caddy sites-enabled directory exists
|
||||
file:
|
||||
path: "{{ caddy_sites_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
- name: Publish ntfy through Caddy
|
||||
ansible.builtin.include_role:
|
||||
name: caddy_site
|
||||
vars:
|
||||
caddy_site_name: ntfy
|
||||
caddy_site_domain: "{{ ntfy_domain }}, http://{{ ntfy_domain }}"
|
||||
# Raw body: ntfy needs a plain-HTTP listener for its CLI/app clients,
|
||||
# with only GETs to the docs and topic paths redirected to HTTPS.
|
||||
caddy_site_body: |
|
||||
reverse_proxy 127.0.0.1:{{ ntfy_port }}
|
||||
|
||||
- name: Ensure Caddyfile includes import directive for sites-enabled
|
||||
lineinfile:
|
||||
path: /etc/caddy/Caddyfile
|
||||
line: 'import sites-enabled/*'
|
||||
insertafter: EOF
|
||||
state: present
|
||||
backup: yes
|
||||
|
||||
- name: Create Caddy reverse proxy configuration for ntfy
|
||||
copy:
|
||||
dest: "{{ caddy_sites_dir }}/ntfy.conf"
|
||||
content: |
|
||||
{{ ntfy_domain }}, http://{{ ntfy_domain }} {
|
||||
reverse_proxy 127.0.0.1:{{ ntfy_port }}
|
||||
|
||||
@httpget {
|
||||
protocol http
|
||||
method GET
|
||||
path_regexp ^/([-_a-z0-9]{0,64}$|docs/|static/)
|
||||
}
|
||||
redir @httpget https://{host}{uri}
|
||||
@httpget {
|
||||
protocol http
|
||||
method GET
|
||||
path_regexp ^/([-_a-z0-9]{0,64}$|docs/|static/)
|
||||
}
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Reload Caddy to apply new config
|
||||
command: systemctl reload caddy
|
||||
redir @httpget https://{host}{uri}
|
||||
|
||||
handlers:
|
||||
- name: Restart ntfy
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
- ./personal_blog_vars.yml
|
||||
vars:
|
||||
personal_blog_subdomain: "{{ subdomains.personal_blog }}"
|
||||
caddy_sites_dir: "{{ caddy_sites_dir }}"
|
||||
personal_blog_domain: "{{ personal_blog_subdomain }}.{{ root_domain }}"
|
||||
uptime_kuma_api_url: "https://{{ subdomains.uptime_kuma }}.{{ root_domain }}"
|
||||
|
||||
|
|
@ -51,36 +50,13 @@
|
|||
group: www-data
|
||||
mode: '0664'
|
||||
|
||||
- name: Ensure Caddy sites-enabled directory exists
|
||||
file:
|
||||
path: "{{ caddy_sites_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Ensure Caddyfile includes import directive for sites-enabled
|
||||
lineinfile:
|
||||
path: /etc/caddy/Caddyfile
|
||||
line: 'import sites-enabled/*'
|
||||
insertafter: EOF
|
||||
state: present
|
||||
backup: yes
|
||||
|
||||
- name: Create Caddy file server configuration for personal blog
|
||||
copy:
|
||||
dest: "{{ caddy_sites_dir }}/personal-blog.conf"
|
||||
content: |
|
||||
{{ personal_blog_domain }} {
|
||||
root * {{ personal_blog_web_root }}
|
||||
file_server
|
||||
}
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Reload Caddy to apply new config
|
||||
command: systemctl reload caddy
|
||||
- name: Publish the blog through Caddy
|
||||
ansible.builtin.include_role:
|
||||
name: caddy_site
|
||||
vars:
|
||||
caddy_site_name: personal-blog
|
||||
caddy_site_domain: "{{ personal_blog_domain }}"
|
||||
caddy_site_root: "{{ personal_blog_web_root }}"
|
||||
|
||||
# ═════════════════════════════════════════════════════════════════════════
|
||||
# DEPRECATED — Uptime Kuma was decommissioned on 2026-09-11.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
# ⚠️ After the first run, back up {{ phoenixd_data_dir }}/seed.dat. Losing it
|
||||
# means losing the funds. See setup_backup_phoenixd_to_lapy.yml.
|
||||
|
||||
- name: Deploy phoenixd on vipy
|
||||
- name: Deploy phoenixd on the edge host
|
||||
hosts: edge
|
||||
become: yes
|
||||
vars_files:
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
- ./vaultwarden_vars.yml
|
||||
vars:
|
||||
vaultwarden_subdomain: "{{ subdomains.vaultwarden }}"
|
||||
caddy_sites_dir: "{{ caddy_sites_dir }}"
|
||||
vaultwarden_domain: "{{ vaultwarden_subdomain }}.{{ root_domain }}"
|
||||
uptime_kuma_api_url: "https://{{ subdomains.uptime_kuma }}.{{ root_domain }}"
|
||||
|
||||
|
|
@ -81,35 +80,13 @@
|
|||
name: fail2ban
|
||||
state: restarted
|
||||
|
||||
- name: Ensure Caddy sites-enabled directory exists
|
||||
file:
|
||||
path: "{{ caddy_sites_dir }}"
|
||||
state: directory
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0755'
|
||||
|
||||
- name: Ensure Caddyfile includes import directive for sites-enabled
|
||||
lineinfile:
|
||||
path: /etc/caddy/Caddyfile
|
||||
line: 'import sites-enabled/*'
|
||||
insertafter: EOF
|
||||
state: present
|
||||
backup: yes
|
||||
|
||||
- name: Create Caddy reverse proxy configuration for vaultwarden
|
||||
copy:
|
||||
dest: "{{ caddy_sites_dir }}/vaultwarden.conf"
|
||||
content: |
|
||||
{{ vaultwarden_domain }} {
|
||||
reverse_proxy localhost:{{ vaultwarden_port }}
|
||||
}
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
|
||||
- name: Reload Caddy to apply new config
|
||||
command: systemctl reload caddy
|
||||
- name: Publish Vaultwarden through Caddy
|
||||
ansible.builtin.include_role:
|
||||
name: caddy_site
|
||||
vars:
|
||||
caddy_site_name: vaultwarden
|
||||
caddy_site_domain: "{{ vaultwarden_domain }}"
|
||||
caddy_site_upstream: "localhost:{{ vaultwarden_port }}"
|
||||
|
||||
# ═════════════════════════════════════════════════════════════════════════
|
||||
# DEPRECATED — Uptime Kuma was decommissioned on 2026-09-11.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue