Compare commits

..

36 Commits

Author SHA1 Message Date
Lino Silva 4a11a4ce8e feat: Sparky fitness 2026-05-31 12:14:58 +01:00
Lino Silva 844cef4bef chore: Change endpoint for price-scraper 2026-05-29 14:24:54 +01:00
Lino Silva 3ed21badb3 fix: Runner config path 2026-05-29 13:11:46 +01:00
Lino Silva bab98a020c feat: Forgejo runner 2026-05-29 13:09:40 +01:00
Lino Silva 3148136c22 feat: Forgejo reverse proxy 2026-05-29 13:09:35 +01:00
Lino Silva fe618ac8e4 fix: Forgejo version 2026-05-29 12:24:29 +01:00
Lino Silva d04a68b4df fix: Forgejo mirror 2026-05-29 12:23:08 +01:00
Lino Silva 6ed68a36be feat: Forgejo 2026-05-29 12:20:55 +01:00
Lino Silva 0eb4e4483c feat: Open wealthfolio 2026-05-28 12:55:03 +01:00
Lino Silva 3032dd0882 feat: Jellyfin reverse-proxy 2026-05-22 14:07:53 +01:00
Lino Silva 0ee5f37b54 feat: KVM reverse proxy 2026-05-22 09:26:38 +01:00
Lino Silva 24bd4ec162 chore: Remove env 2026-05-22 09:26:33 +01:00
Lino Silva cec78f8229 fix: Dahua2Mqtt docker compose 2026-05-19 21:31:06 +01:00
Lino Silva 234d9edc68 fix: Dahua2MQTT env file 2026-05-19 21:25:07 +01:00
Lino Silva 59c003f619 feat: Dahua2MQTT 2026-05-19 18:53:48 +01:00
Lino Silva 98c88759be feat: Speedtest 2026-05-19 18:41:09 +01:00
Lino Silva 8173b7cbc1 feat: Expose gitea 2026-05-19 10:13:23 +01:00
Lino Silva 886c6f559b fix: Price tracker reverse proxy 2026-05-12 22:32:32 +01:00
Lino Silva a05b2ea9ea chore: Renaming 2026-05-12 22:28:16 +01:00
Lino Silva ce197c3299 feat: Price tracker 2026-05-12 22:28:10 +01:00
Lino Silva 94984f0635 fix: Homelable images 2026-05-04 10:39:04 +01:00
Lino Silva e1500967cf feat: Homelable
Co-authored-by: Copilot <copilot@github.com>
2026-05-04 10:33:18 +01:00
Lino Silva 9e4a1f7836 feat: Unmanic endpoint 2026-04-21 12:15:16 +01:00
Lino Silva a286b755fe feat: Added apps-2 VM 2026-04-20 16:25:30 +01:00
Lino Silva e7bb6eadb8 feat: New endpoint 2026-04-14 00:56:44 +01:00
Lino Silva c5421a4af4 fix: Typo 2026-04-13 10:06:04 +01:00
Lino Silva fb7e101d6f fix: Subdomain for trek 2026-04-13 09:39:49 +01:00
Lino Silva 9ffae8989a fix: Remove env file 2026-04-12 23:11:14 +01:00
Lino Silva e44dafb0e2 fix: Dummy 2026-04-12 23:04:01 +01:00
Lino Silva 68d5178ab4 fix: Env var naming 2026-04-12 23:01:56 +01:00
Lino Silva 714f2449f6 fix: Revert 2026-04-12 22:44:22 +01:00
Lino Silva 5030362ba4 fix: Try new interpolation 2026-04-12 22:42:52 +01:00
Lino Silva 8fb291704e fix: Spacing? 2026-04-12 22:32:59 +01:00
Lino Silva f0b7351f64 fix: OIDC discovery url 2026-04-12 22:28:42 +01:00
Lino Silva f111fdfcb7 fix: Reverse proxy port 2026-04-12 22:28:31 +01:00
Lino Silva 07ac4dfec4 fix: Port 2026-04-12 22:22:37 +01:00
18 changed files with 616 additions and 118 deletions
@@ -20,3 +20,12 @@ app_data_disks:
disk_id: scsi1 disk_id: scsi1
mount_point: /data/trek mount_point: /data/trek
device: /dev/sdb device: /dev/sdb
forgejo:
vm: apps-1
vmid: 430
node: yunobo
size: "50"
storage: nvme-2tb
disk_id: scsi2
mount_point: /data/forgejo
device: /dev/sdc
+77 -46
View File
@@ -26,200 +26,231 @@ auto_configure_traefik:
subdomain: "sonarr" subdomain: "sonarr"
host: "10.0.2.25" host: "10.0.2.25"
port: 8989 port: 8989
auth_required: true internal: true
radarr: radarr:
subdomain: "radarr" subdomain: "radarr"
host: "10.0.2.25" host: "10.0.2.25"
port: 7878 port: 7878
auth_required: true internal: true
lidarr: lidarr:
subdomain: "lidarr" subdomain: "lidarr"
host: "10.0.2.25" host: "10.0.2.25"
port: 8686 port: 8686
auth_required: true internal: true
transmission: transmission:
subdomain: "transmission" subdomain: "transmission"
host: "10.0.2.25" host: "10.0.2.25"
port: 9091 port: 9091
auth_required: true internal: true
tdarr: unmanic:
subdomain: "tdarr" subdomain: "unmanic"
host: "10.0.2.25" host: "10.0.2.25"
port: 8265 port: 8888
auth_required: true internal: true
bazarr: bazarr:
subdomain: "bazarr" subdomain: "bazarr"
host: "10.0.2.25" host: "10.0.2.25"
port: 6767 port: 6767
auth_required: true internal: true
seerr: seerr:
subdomain: "overseerr" subdomain: "overseerr"
host: "10.0.2.25" host: "10.0.2.25"
port: 5055 port: 5055
auth_required: false internal: false
prowlarr: prowlarr:
subdomain: "prowlarr" subdomain: "prowlarr"
host: "10.0.2.25" host: "10.0.2.25"
port: 9696 port: 9696
auth_required: true internal: true
unpackerr: unpackerr:
subdomain: "unpackerr" subdomain: "unpackerr"
host: "10.0.2.25" host: "10.0.2.25"
port: 5656 port: 5656
auth_required: true internal: true
questarr:
subdomain: "questarr"
host: "10.0.2.25"
port: 5000
internal: true
# infra # infra
komodo: komodo:
subdomain: "komodo" subdomain: "komodo"
host: "10.0.4.10" host: "10.0.4.10"
port: 9120 port: 9120
auth_required: true internal: true
homeassistant: homeassistant:
subdomain: "homeassistant" subdomain: "homeassistant"
host: "10.0.2.100" host: "10.0.2.100"
port: 8123 port: 8123
auth_required: false internal: false
# media # media
plex: plex:
subdomain: "plex" subdomain: "plex"
host: "10.0.2.10" host: "10.0.2.10"
port: 32400 port: 32400
auth_required: false internal: false
tracearr: tracearr:
subdomain: "tracearr" subdomain: "tracearr"
host: "10.0.2.21" host: "10.0.2.21"
port: 3000 port: 3000
auth_required: true internal: true
jellyfin:
subdomain: "jellyfin"
host: "10.0.2.11"
port: 8096
internal: true
vaultwarden: vaultwarden:
subdomain: "pwds" subdomain: "pwds"
host: "10.0.2.27" host: "10.0.2.27"
port: 8004 port: 8004
auth_required: false internal: false
changedetection: changedetection:
subdomain: "changedetection" subdomain: "changedetection"
host: "10.0.2.24" host: "10.0.2.24"
port: 5000 port: 5000
auth_required: true internal: true
nextcloud: nextcloud:
subdomain: "cloud" subdomain: "cloud"
host: "10.0.2.30" host: "10.0.2.30"
port: 8001 port: 8001
auth_required: false internal: false
convertx: convertx:
subdomain: "convertx" subdomain: "convertx"
host: "10.0.2.43" host: "10.0.2.43"
port: 3000 port: 3000
auth_required: true internal: true
dawarich: dawarich:
subdomain: "places" subdomain: "places"
host: "10.0.2.48" host: "10.0.2.48"
port: 3000 port: 3000
auth_required: false internal: false
frigate: frigate:
subdomain: "frigate" subdomain: "frigate"
host: "10.0.2.14" host: "10.0.2.14"
port: 5000 port: 5000
auth_required: true internal: true
droposs: droposs:
subdomain: "games" subdomain: "games"
host: "10.0.2.46" host: "10.0.2.46"
port: 3000 port: 3000
auth_required: false internal: false
# geoguessr:
# subdomain: "geoguessr"
# host: "10.0.2.39"
# port: 8080
# auth_required: true
gitea: gitea:
subdomain: "gitea" subdomain: "gitea"
host: "10.0.2.28" host: "10.0.2.28"
port: 3000 port: 3000
auth_required: true internal: false
forgejo:
subdomain: "git"
host: "10.0.4.30"
port: 8086
internal: false
immich: immich:
subdomain: "immich" subdomain: "immich"
host: "10.0.2.18" host: "10.0.2.18"
port: 2283 port: 2283
auth_required: false internal: false
mastodon: mastodon:
subdomain: "social" subdomain: "social"
host: "10.0.2.20" host: "10.0.2.20"
port: 80 port: 80
auth_required: false internal: false
forward_https: true forward_https: true
matrix: matrix:
subdomain: "chat" subdomain: "chat"
host: "10.0.2.20" host: "10.0.2.20"
port: 8008 port: 8008
auth_required: false internal: false
mealie: mealie:
subdomain: "recipes" subdomain: "recipes"
host: "10.0.2.26" host: "10.0.2.26"
port: 9000 port: 9000
auth_required: false internal: false
truenas: truenas:
subdomain: "nas" subdomain: "nas"
host: "10.0.2.200" host: "10.0.2.200"
port: 80 port: 80
auth_required: true internal: true
paperless: paperless:
subdomain: "paperless" subdomain: "paperless"
host: "10.0.2.29" host: "10.0.2.29"
port: 8003 port: 8003
auth_required: true internal: true
pbs: pbs:
subdomain: "pbs" subdomain: "pbs"
host: "10.0.2.104" host: "10.0.2.104"
port: 8007 port: 8007
https: true https: true
auth_required: true internal: true
# pinchflat: # pinchflat:
# subdomain: "youtube" # subdomain: "youtube"
# host: "10.0.2.23" # host: "10.0.2.23"
# port: 8081 # port: 8081
# auth_required: true # internal: true
proxmox: proxmox:
subdomain: "proxmox" subdomain: "proxmox"
host: "10.0.2.2" host: "10.0.2.2"
port: 8006 port: 8006
https: true https: true
auth_required: true internal: true
resume: resume:
subdomain: "resume" subdomain: "resume"
host: "10.0.2.53" host: "10.0.2.53"
port: 3000 port: 3000
auth_required: true internal: true
auth_bypass_paths: auth_bypass_paths:
- /lino - /lino
- /assets - /assets
- /api - /api
speedtest-tracker: speedtest-tracker:
subdomain: "fast" subdomain: "fast"
host: "10.0.2.15" host: "10.0.4.30"
port: 8765 port: 8085
auth_required: true internal: true
stocks: stocks:
subdomain: "stocks" subdomain: "stocks"
host: "10.0.2.40" host: "10.0.2.40"
port: 3333 port: 3333
auth_required: false internal: false
super-productivity: super-productivity:
subdomain: "tasks" subdomain: "tasks"
host: "10.0.2.45" host: "10.0.2.45"
port: 80 port: 80
auth_required: true internal: true
uptime-kuma: uptime-kuma:
subdomain: "uptime" subdomain: "uptime"
host: "10.0.2.203" host: "10.0.2.203"
port: 3001 port: 3001
auth_required: true internal: true
wealthfolio: wealthfolio:
subdomain: "wealth" subdomain: "wealth"
host: "10.0.2.40" host: "10.0.2.40"
port: 8088 port: 8088
auth_required: true internal: false
trek:
subdomain: "trips"
host: "10.0.4.30"
port: 8083
internal: true
homelable:
subdomain: "infra"
host: "10.0.4.30"
port: 8084
internal: true
price-tracker:
subdomain: "prices"
host: "10.0.4.30"
port: 3000
internal: true
kvm:
subdomain: "kvm"
host: "10.0.3.1"
port: 80
internal: true
forward_https: true
# Auth services configuration # Auth services configuration
pocketid_host: 10.0.4.10 pocketid_host: 10.0.4.10
+52 -52
View File
@@ -1,53 +1,53 @@
$ANSIBLE_VAULT;1.1;AES256 $ANSIBLE_VAULT;1.1;AES256
33346333343637663032363331303231316234346636353763653039383662343730356335353730 63666330376531356135326331306565336237626132383934313666636134366436383831393730
6466653064643530393338663130613238343733646366350a666333636337356362393033393639 3330643462346434663536383231646364613963373833360a386237306230636131313464363636
30636331653939323336313638623235393632663963303834613430386135633134343465383738 66383366616436633538363430383530613635333462383431643438643962633833363632366438
6139633438383937320a353536643230383439323339316638366464336636353164646232373839 3063323965363031360a353662366435323263356235333633306161363664373738313830333562
35323165636364363238366431383663303430316130653366643263376238316137666665376366 36383637363465396161313332316262383132313061356461626331623134653136353566333539
61653937626264396531356639373865393962616565353265353366666133386266623638613138 39626662663539303337306662666131653738633666393434336338616561353061316132653666
38316632363065613234306661313431663639393862316630323064376236663332313130633465 39313537636561396466646366653366663134386564643036613465623061323261343532373037
37396136313032613932616664653239346265323135316131323735306638356664373336376231 39663931326339636533323631333661643736663066643262383766623163333234336364626165
34376565343531393831323438303563333463373437636535636162373830386135346164333264 36333536313332613966303838393262616335343563643965363664653334613330356134353362
37633264653932636639316161306637326361313530313365633335633937333832326130343532 30643636323661666463393564393434383436346636616333626464306261346337623063306136
39333739313364353539313262646364323931346436393633343063666238623363646338663862 33353034386566323366343739626533323735333638313261336666663964633665313962383364
37376565663636663166323030626133313065346135666439613032616135663136663062653032 65326536333462303637376265366532623435336363346230366631313663366234616436363161
34616433646266313462326261323166313566386266653962663435656232303036363235373632 65663932303138623865306163656464613039643936313532396135393966333632333235636461
32626461663936353236623564633366383366636666386236633766646439333161393438653661 65656636666339303365663766323434633032376561333939306336643563653832306362313134
39633362313337616139373663326364353534386231636561366664363862363833613133373031 64616438393235623964356132626231646539333065663334346139353232663263323331643064
30626664336166373938643935343138326564343036333266336331626638613238306262326261 35636563613836376666643664636265626530363235373265306163386331633631313161346133
30666265643435633565303365623633326466653837643633653934646638383736653365653730 64633038306335373236646632356238343763636433623938373064383834346361316232643830
66613365343730643635323032646363633934313263316534313263303533383865613636616266 64316663653638386466313336666164343036373231623066663033336365303934626236633238
66323435363037336239643366373534653434343063623130393437393633306130356666333339 62643032303863366436313934316563346364383536636236633232656164643032653530376665
30633533353563643832633064653165363563356436626637353833643064323432346131373230 30326639646632346638636232626431396536346165656539343535313266666665336366373333
32346433653332623535343366306662623638326462616463376333663830663039366235313766 31333930656330653031656236316261663366396434353063663831643464663134623063386333
31323665393964363262363366313764363965353439363865323464623632313833333235306237 37386431393336396362373834303135663631343366666333613331333136303134656231343530
30363937646335303066343934306130313330653266383239646462636364306439636163393634 64316562663362656662613932393136383837666666316438393235316666323063373732666334
65653638666239363737653632316536333535333134616664343665343030313637643333393963 38356162396630363430633166306566626131643734636536633264336632323734333163306535
38306338333033313064333339393239343631643563623765663362353764323661366161636138 36633965376362373733616635656565636164636562386566643231363835656634343235373838
30366166353364373139616562623634316432613662363539613765336335326266666666356332 34333730353935643935626366656133353330316165633835626333663539623665653662353138
34653263316663636530323431353562643833373935306264333565363832643030646433326263 61363230303634653131356563376263363339613265373534383561313932616635643038363266
38643462666237376331643037316232623664653333386433636566656366666430363337616130 31663835643830666363646635346538656665363730396366643439326537386264663666363332
31383730306563386465383531366462363266333437323831393561363665663231346362363665 64363561623031626531663934636634313536653435663431666463386362306331353137396362
35333836653931343161653261656265643732353837666337393835363536353937646561396365 65653039623636316338326335613164376366613266316134386163626436383539393932666436
64363463326435386330343937323934356366343434323964306131363133633434303266636563 33633264653230663065393632653935633833313233373933326464316331646363613832633330
39393463333539306262323239663033633830336433663931653433393030626633316564343737 30353263343433366362323365386536313535396430373966323337623830373465356437643734
31626461316234623965316339343434646561636164343037356566623366626636326663623533 32313038323664376566656666633364363634613033376636326635343233666134363864343634
63646166383835306430333965346234363334646534323566623430633865373837353763626663 65386538663835663539353533633931323837373738393463336337353865616439336537353933
37363461656430623739366664613832346135333535393531623762656566616137303439323039 32353162363166353265316534643764616132656534666463363439643237396166303833303038
63613436366161616263396464316231333535346561666631366464666433643031653231316464 66383236363738336363643832666130633464333536623134616265316663333237383739336537
62626363346335663639623366396634373664643965393339636336616139616431653830306331 37376331326139633764353166656634323339656435663531313934376565393639316531663237
37633439306365333961356336653637656661643763353032653063336430393638653830313439 64303931386461346632646161393061376534393539663966373562646432386134616435363261
62396632316166356131316438643164386466623162663661383834346633656265396438666231 37356466303165356336626134313135353830316536323165323233613235643733643333613636
61663332366634623032323836366235613933363964366665643330366466306434356232396330 63666139323931616166346566396162373637336331393034623631346437643632643938323834
39636163653536396365336631366633313830633631383333383338333964613034623935666663 35383862653464643533663333616263633465663939633064653666353363363830393565666236
66346434326630333630326333663462376431306432633466356166306532616530633262626231 31333663663332363533336132346666643734623131643339643865633565393262643966393734
36653936333134643832343865366333623939656539386534346430646330616431376366363265 36663533313638386166653334623832323363636262373931356664323766666538343838313039
33353132336562613139383264396462353234303533353263343433626566366263393134356666 39393765343430633336373966346161393130386539393366363366366163316363613038613962
65343633663261626138333665323238623239363364646436336639333636663236396162376164 36646336396333333863326565303666373963326163393434313534333533323739623035323137
62356534323663353832653466393837353931636232353331386534323934633336623039316662 32346535383263316332653239306633343935383166653139323036616133656638643532646634
30646432613761623966623033393533633235396431353631663364653461393464353738663031 64333466666533363932323366353762653461336538303166626330333336616437613037363139
63653931366633323966313664333562613263663239333937626536333662666538643736663034 63303764313330656366363630636463303461383565346262656136326362623839366531326663
38316365333033333130643931333331373662326639316266363436656365646262613433376336 34663534343564313030613366626337336331343637343564386638653530663631613234636237
31376663326563323637313339396263376231333230643238326339663239633463303435653035 37373064303137666263666133363865386135333038653231346562333131313233643062376265
39343533636234326262323330663736326431353637343663636165663935313236316337336463 34646635663961393837396637383834376136323864646166656436383338623364613861663537
33373033653435313235 39313230306465626630
@@ -33,6 +33,17 @@ vms:
network_bridge: "vmbr2" network_bridge: "vmbr2"
storage: nvme-2tb storage: nvme-2tb
apps-2:
vmid: 431
node: yuga
template_vmid: 9004
cores: 5
memory: 12288
disk: 30G
ip: 10.0.4.31
network_bridge: "vmbr0"
storage: media
edge-1: edge-1:
vmid: 401 vmid: 401
node: mipha node: mipha
+2
View File
@@ -22,3 +22,5 @@ all:
hosts: hosts:
apps-1: apps-1:
ansible_host: 10.0.4.30 ansible_host: 10.0.4.30
apps-2:
ansible_host: 10.0.4.31
+13 -1
View File
@@ -1,4 +1,8 @@
--- ---
# NOTE: Adding a komodo-periphery role to an edge means you need to
# create an onboarding key on Komodo and change its value on
# the vault
- hosts: infra - hosts: infra
become: yes become: yes
roles: roles:
@@ -25,10 +29,18 @@
- docker - docker
- komodo-periphery - komodo-periphery
- hosts: apps - hosts: apps-1
become: yes become: yes
roles: roles:
- base - base
- docker - docker
- komodo-periphery - komodo-periphery
- trek - trek
- forgejo
- hosts: apps-2
become: yes
roles:
- base
- docker
- komodo-periphery
+53
View File
@@ -0,0 +1,53 @@
---
- name: Add data disk to VM for forgejo
community.proxmox.proxmox_disk:
api_host: "{{ proxmox_api_host }}"
api_user: "{{ proxmox_api_user }}"
api_token_id: "{{ proxmox_api_token_id }}"
api_token_secret: "{{ proxmox_api_token_secret }}"
vmid: "{{ app_data_disks.forgejo.vmid }}"
disk: "{{ app_data_disks.forgejo.disk_id }}"
storage: "{{ app_data_disks.forgejo.storage }}"
size: "{{ app_data_disks.forgejo.size }}"
state: present
delegate_to: localhost
become: no
run_once: true
ignore_errors: yes
register: disk_result
- name: Display disk creation result
debug:
var: disk_result
- name: Wait for data disk to be available
wait_for:
path: "{{ app_data_disks.forgejo.device }}"
state: present
timeout: 30
- name: Check if data disk is formatted
command: "blkid {{ app_data_disks.forgejo.device }}"
register: disk_formatted
failed_when: false
changed_when: false
- name: Format data disk with ext4
filesystem:
fstype: ext4
dev: "{{ app_data_disks.forgejo.device }}"
when: disk_formatted.rc != 0
- name: Create forgejo data mount point
file:
path: "{{ app_data_disks.forgejo.mount_point }}"
state: directory
mode: "0755"
- name: Mount data disk
mount:
path: "{{ app_data_disks.forgejo.mount_point }}"
src: "{{ app_data_disks.forgejo.device }}"
fstype: ext4
state: mounted
opts: defaults
@@ -116,7 +116,7 @@ http:
# Auto-configured services - HTTPS # Auto-configured services - HTTPS
{% for service_name, config in auto_configure_traefik.items() %} {% for service_name, config in auto_configure_traefik.items() %}
{% if config.auth_required | default(true) %} {% if config.internal | default(true) %}
# {{ service_name }} - local IP bypass (no auth) # {{ service_name }} - local IP bypass (no auth)
{{ service_name }}-local: {{ service_name }}-local:
rule: "Host(`{{ config.subdomain }}.{{ domain }}`) && (ClientIP(`192.168.0.0/16`) || ClientIP(`10.0.0.0/8`) || ClientIP(`172.16.0.0/12`))" rule: "Host(`{{ config.subdomain }}.{{ domain }}`) && (ClientIP(`192.168.0.0/16`) || ClientIP(`10.0.0.0/8`) || ClientIP(`172.16.0.0/12`))"
@@ -153,9 +153,9 @@ http:
entryPoints: entryPoints:
- https - https
priority: 1 priority: 1
{% if config.auth_required | default(true) or config.forward_https | default(false) %} {% if config.internal | default(true) or config.forward_https | default(false) %}
middlewares: middlewares:
{% if config.auth_required | default(true) %} {% if config.internal | default(true) %}
- pocketid-auth - pocketid-auth
{% endif %} {% endif %}
{% if config.forward_https | default(false) %} {% if config.forward_https | default(false) %}
@@ -170,9 +170,9 @@ http:
rule: "Host(`{{ config.subdomain }}.{{ domain }}`)" rule: "Host(`{{ config.subdomain }}.{{ domain }}`)"
entryPoints: entryPoints:
- https - https
{% if config.auth_required | default(true) or config.forward_https | default(false) %} {% if config.internal | default(true) or config.forward_https | default(false) %}
middlewares: middlewares:
{% if config.auth_required | default(true) %} {% if config.internal | default(true) %}
- pocketid-auth - pocketid-auth
{% endif %} {% endif %}
{% if config.forward_https | default(false) %} {% if config.forward_https | default(false) %}
@@ -1,7 +0,0 @@
services:
webserver:
image: nginx:alpine
container_name: hello-webserver
ports:
- "8081:80"
restart: unless-stopped
@@ -0,0 +1,8 @@
services:
dahuavto2mqtt:
image: "registry.gitlab.com/elad.bar/dahuavto2mqtt:latest"
container_name: "dahua2mqtt"
hostname: "dahua2mqtt"
restart: "unless-stopped"
env_file:
- .env
@@ -0,0 +1,38 @@
services:
server:
image: codeberg.org/forgejo/forgejo:15
container_name: forgejo
environment:
- USER_UID=1000
- USER_GID=1000
restart: always
volumes:
- /data/forgejo:/data
- /etc/localtime:/etc/localtime:ro
ports:
- "8086:3000"
- "222:22"
docker-in-docker:
image: docker:dind
container_name: "docker_dind"
privileged: "true"
command: ["dockerd", "-H", "tcp://0.0.0.0:2375", "--tls=false"]
restart: "unless-stopped"
runner:
image: "data.forgejo.org/forgejo/runner:12"
links:
- docker-in-docker
depends_on:
docker-in-docker:
condition: service_started
container_name: "runner"
environment:
DOCKER_HOST: tcp://docker-in-docker:2375
# User without root privileges, but with access to `./data`.
user: 1001:1001
volumes:
- /data/forgejo/runner:/data
restart: "unless-stopped"
command: "forgejo-runner daemon --config /data/runner-config.yml"
@@ -0,0 +1,36 @@
services:
backend:
image: ghcr.io/pouzor/homelable-backend:latest
restart: unless-stopped
env_file:
- .env
environment:
# Override env_file: SQLite path must point inside the container volume
SQLITE_PATH: /app/data/homelab.db
volumes:
- /data/homelable:/app/data
networks:
- homelable
# Required for ping-based status checks
cap_add:
- NET_RAW
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/api/v1/health"]
interval: 10s
timeout: 5s
retries: 6
start_period: 15s
frontend:
image: ghcr.io/pouzor/homelable-frontend:latest
restart: unless-stopped
ports:
- "8084:80"
depends_on:
- backend
networks:
- homelable
networks:
homelable:
driver: bridge
@@ -0,0 +1,7 @@
services:
webserver:
image: git.lino.cooking/lino/bpi-stock-price-scraper:latest
container_name: price-tracker
ports:
- "3000:3000"
restart: unless-stopped
+210
View File
@@ -0,0 +1,210 @@
# SparkyFitness Environment Variables
# Copy this file to .env in the root directory and fill in your own values before running 'docker-compose up'.
# --- PostgreSQL Database Settings ---
# These values should match the ones used by your PostgreSQL container.
# For local development (running Node.js directly), use 'localhost' or '127.0.0.1' if PostgreSQL is on your host.
SPARKY_FITNESS_DB_NAME=sparkyfitness_db
#SPARKY_FITNESS_DB_USER is super user for DB initialization and migrations.
SPARKY_FITNESS_DB_USER=sparky
SPARKY_FITNESS_DB_PASSWORD=changeme_db_password
# Application database user with limited privileges. it can be changed any time after initialization.
SPARKY_FITNESS_APP_DB_USER=sparky_app
SPARKY_FITNESS_APP_DB_PASSWORD=password
# For Docker Compose deployments, SPARKY_FITNESS_DB_HOST will be the service name (e.g., 'sparkyfitness-db').
#SPARKY_FITNESS_DB_HOST=sparkyfitness-db
# SPARKY_FITNESS_DB_PORT controls the HOST port for external database access (e.g., pgAdmin, DBeaver).
# To use this, you must also uncomment the 'ports' section under sparkyfitness-db in docker-compose.prod.yml.
# Inside Docker, containers always communicate on port 5432 (the internal PostgreSQL port).
# Changing this value will NOT affect container-to-container communication.
#SPARKY_FITNESS_DB_PORT=5432
# --- Backend Server Settings ---
# The hostname or IP address of the backend server.
# For Docker Compose, this is typically the service name (e.g., 'sparkyfitness-server').
# For local development or other deployments, this might be 'localhost' or a specific IP.
SPARKY_FITNESS_SERVER_HOST=sparkyfitness-server
# The external port the server will be exposed on.
SPARKY_FITNESS_SERVER_PORT=3010
# The public URL of your frontend (e.g., https://fitness.example.com). This is crucial for CORS security.
# For local development, use http://localhost:8080. For production, use your domain with https.
SPARKY_FITNESS_FRONTEND_URL=http://localhost:3004
# Allow CORS requests from private network addresses (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, localhost, etc.)
# SECURITY WARNING: Only enable this if you are running on a private/self-hosted network.
# Do NOT enable on shared hosting or cloud environments where other users might access your network.
# Default: false (secure default - only the configured SPARKY_FITNESS_FRONTEND_URL is allowed)
#ALLOW_PRIVATE_NETWORK_CORS=false
# A comma-separated list of additional URLs that Better Auth should trust.
# This is useful when accessing the app from a specific local IP on your network.
# Example: SPARKY_FITNESS_EXTRA_TRUSTED_ORIGINS=http://192.168.1.175:8080,http://10.0.0.5:8080
# SPARKY_FITNESS_EXTRA_TRUSTED_ORIGINS=
# Logging level for the server (e.g., INFO, DEBUG, WARN, ERROR)
SPARKY_FITNESS_LOG_LEVEL=ERROR
# Node.js environment mode (e.g., development, production, test)
# Set to 'production' for deployment to ensure optimal performance and security.
NODE_ENV=production
# Server timezone. Use a TZ database name (e.g., 'America/New_York', 'Etc/UTC').
# This affects how dates/times are handled by the server if not explicitly managed in code.
TZ=Europe/Lisbon
# --- Security Settings ---
# A 64-character hex string for data encryption.
# You can generate a secure key with the following command:
# openssl rand -hex 32
# or
# node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"
# Changing this will invalidate existing encrypted data. You will need to delete and add External Data sources again.
SPARKY_FITNESS_API_ENCRYPTION_KEY=b65743a2f9946be8b7f14083f59183f26bc07c9d2d352a96b2d186a06907e111
# For Docker Swarm/Kubernetes secrets, you can use a file-based secret:
# SPARKY_FITNESS_API_ENCRYPTION_KEY_FILE=/run/secrets/sparkyfitness_api_key
# BETTER_AUTH_SECRET is used to sign sessions and encrypt 2FA/TOTP data.
# CRITICAL: If you change this after users have enabled 2FA, they will be LOCKED OUT of their accounts.
# Ensure this is set to a strong, persistent value during initial setup and is never changed.
# If you MUST change it, all users must disable Two-Factor Authentication (TOTP) first.
BETTER_AUTH_SECRET=297f9b19e4f13b3ce45af8f1fcc8234264223b6c2052e1f51ea6869583325ecc
# For Docker Swarm/Kubernetes secrets, you can use a file-based secret:
# BETTER_AUTH_SECRET_FILE=/run/secrets/sparkyfitness_better_auth_secret
# --- Signup Settings ---
# Set to 'true' to disable new user registrations.
SPARKY_FITNESS_DISABLE_SIGNUP=false
# --- Admin Settings ---
# Set the email of a user to automatically grant admin privileges on server startup.
# This is useful for development or initial setup.
# Example: SPARKY_FITNESS_ADMIN_EMAIL=admin@example.com
# Optional. If not set, no admin user will be created automatically.
SPARKY_FITNESS_ADMIN_EMAIL=sparkyfitness@lino.cooking
# --- OIDC Authentication Configuration ---
# Set to 'true' to disable email/password login on the login page (overridden by SPARKY_FITNESS_FORCE_EMAIL_LOGIN).
SPARKY_FITNESS_DISABLE_EMAIL_LOGIN=true
# Set to 'true' to enable OIDC login. When set, overrides the database value from Admin > Authentication Settings.
SPARKY_FITNESS_OIDC_AUTH_ENABLED=true
# Display name and provider slug (URL-safe id) for the ENV-configured OIDC provider.
SPARKY_FITNESS_OIDC_PROVIDER_SLUG=pocket-id
SPARKY_FITNESS_OIDC_PROVIDER_NAME=Pocket ID
SPARKY_FITNESS_OIDC_AUTO_REGISTER=true
SPARKY_FITNESS_OIDC_LOGO_URL=https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/pocket-id.svg
# OIDC issuer URL (e.g. https://example.com). Discovery URL is derived as issuer + /.well-known/openid-configuration.
# When set with CLIENT_ID, CLIENT_SECRET and PROVIDER_SLUG, an ENV-configured OIDC provider is upserted at startup.
SPARKY_FITNESS_OIDC_ISSUER_URL=https://auth.lino.cooking/application/o/{{slug}}/
# SPARKY_FITNESS_OIDC_DOMAIN=example.com
# OIDC client credentials from your IdP.
# SPARKY_FITNESS_OIDC_CLIENT_ID=
# SPARKY_FITNESS_OIDC_CLIENT_SECRET=
# SPARKY_FITNESS_OIDC_SCOPE=openid email profile
# Set to 'true' to allow auto-redirect to the single OIDC provider when email login is disabled.
SPARKY_FITNESS_OIDC_AUTO_REDIRECT=true
# Group/claim values from your IdP for role mapping (admin vs user). Configure your IdP to send these in token claims.
# SPARKY_FITNESS_OIDC_ADMIN_GROUP=Admin
# --- Advanced OIDC Settings ---
# SPARKY_FITNESS_OIDC_TOKEN_AUTH_METHOD=client_secret_post
# SPARKY_FITNESS_OIDC_ID_TOKEN_SIGNED_ALG=RS256
# SPARKY_FITNESS_OIDC_USERINFO_SIGNED_ALG=none
# SPARKY_FITNESS_OIDC_TIMEOUT=30000
# Set custom uploads and backups directory. Only needed for standalone installation
# SPARKY_FITNESS_CUSTOM_UPLOADS_DIRECTORY=
# SPARKY_FITNESS_CUSTOM_BACKUP_DIRECTORY=
#
# --- Login Management Fail-Safe ---
# Set to 'true' to force email/password login to be enabled, overriding any in-app settings.
# This is a fail-safe to prevent being locked out if OIDC is misconfigured.
# SPARKY_FITNESS_FORCE_EMAIL_LOGIN=true
# --- Email Settings (Optional) ---
# Configure these variables if you want to enable email notifications (e.g., for password resets).
# If not configured, email functionality will be disabled.
# SPARKY_FITNESS_EMAIL_HOST=smtp.example.com
# SPARKY_FITNESS_EMAIL_PORT=587
# SPARKY_FITNESS_EMAIL_SECURE=true # Use 'true' for TLS/SSL, 'false' for plain text
# SPARKY_FITNESS_EMAIL_USER=your_email@example.com
# SPARKY_FITNESS_EMAIL_PASS=your_email_password
# SPARKY_FITNESS_EMAIL_FROM=no-reply@example.com
# --- Volume Paths (Optional) ---
# These paths define where Docker volumes will store persistent data on your host.
# If not set, Docker will manage volumes automatically in its default location.
DB_PATH=/data/sparky-fitness/postgresql # Path for PostgreSQL database data
SERVER_BACKUP_PATH=/data/sparky-fitness/backup # Path for server backups
SERVER_UPLOADS_PATH=/data/sparky-fitness/uploads # Path for profile pictures and exercise images
# --- API Key Rate Limiting (Optional) ---
# Override the default rate limit for API key authentication (used by automation tools like n8n).
# Defaults to 100 requests per 60-second window if not set.
#SPARKY_FITNESS_API_KEY_RATELIMIT_WINDOW_MS=60000
#SPARKY_FITNESS_API_KEY_RATELIMIT_MAX_REQUESTS=100
# --- Start of Garmin Integration Settings ---
#Below variables are needed only for Garmin integration. If you don't use Garmin integration, you can remove them in your .env file.
# The URL for the Garmin microservice.
# For Docker Compose, this would typically be the service name and port (e.g., 'http://sparkyfitness-garmin:8000').
# For local development, use 'http://localhost:8000' or the port you've configured.
# GARMIN_MICROSERVICE_URL=http://sparkyfitness-garmin:8000
# This is used for Garmin Connect synchronization.
# If you are not using Garmin integration, you don't need this. Make sure this matches with GARMIN_MICROSERVICE_URL.
# GARMIN_SERVICE_PORT=8000
# set to true for China region. Everything else should be false. Optional - defaults to false
# GARMIN_SERVICE_IS_CN=false
# --- End of Garmin Integration Settings ---
# --- MCP Server Settings ---
# The port the MCP server will listen on.
# SPARKY_FITNESS_MCP_PORT=3001
# Vision API Settings (for sparky_analyze_food_image and sparky_scan_label)
# Supported providers: gemini, openai, anthropic
# VISION_API_PROVIDER=gemini
# VISION_API_KEY=
# Set to 'true' to enable developer tools (e.g., sparky_inspect_schema)
# Requires the authenticated user to have the 'admin' role.
# DEV_TOOLS_ENABLED=false
# ----- Developers Section -----
# Data source for external integrations (fitbit, garmin, withings).
# By default, these use live APIs. Set to 'local' to use mock data from the mock_data directory.
# To use these variables, you will also need to pass to Server container. For Garmin, pass to Garmin container.
#SPARKY_FITNESS_FITBIT_DATA_SOURCE=local
#SPARKY_FITNESS_WITHINGS_DATA_SOURCE=local
#SPARKY_FITNESS_GARMIN_DATA_SOURCE=local
#SPARKY_FITNESS_POLAR_DATA_SOURCE=local
#SPARKY_FITNESS_HEVY_DATA_SOURCE=local
# Set to 'true' to capture live API responses into mock data JSON files. Defaults to false.
#SPARKY_FITNESS_SAVE_MOCK_DATA=false
#-----------------------------
@@ -0,0 +1,70 @@
services:
sparkyfitness-db:
image: postgres:18.3-alpine
container_name: sparkyfitness-db
restart: always
# Uncomment below to expose PostgreSQL to the host (e.g., for pgAdmin, DBeaver).
# ports:
# - "${SPARKY_FITNESS_DB_PORT:-5432}:5432"
environment:
POSTGRES_DB: ${SPARKY_FITNESS_DB_NAME:?Variable is required and must be set}
POSTGRES_USER: ${SPARKY_FITNESS_DB_USER:?Variable is required and must be set}
POSTGRES_PASSWORD: ${SPARKY_FITNESS_DB_PASSWORD:?Variable is required and must be set}
PUID: 1000
GUID: 1000
volumes:
- ${DB_PATH:-./postgresql}:/var/lib/postgresql
sparkyfitness-server:
image: codewithcj/sparkyfitness_server:latest # Use pre-built image
environment:
SPARKY_FITNESS_LOG_LEVEL: ${SPARKY_FITNESS_LOG_LEVEL}
ALLOW_PRIVATE_NETWORK_CORS: ${ALLOW_PRIVATE_NETWORK_CORS:-false}
SPARKY_FITNESS_EXTRA_TRUSTED_ORIGINS: ${SPARKY_FITNESS_EXTRA_TRUSTED_ORIGINS:-}
SPARKY_FITNESS_DB_USER: ${SPARKY_FITNESS_DB_USER:-sparky}
SPARKY_FITNESS_DB_HOST: ${SPARKY_FITNESS_DB_HOST:-sparkyfitness-db} # Use the service name 'sparkyfitness-db' for inter-container communication
SPARKY_FITNESS_DB_NAME: ${SPARKY_FITNESS_DB_NAME}
SPARKY_FITNESS_DB_PASSWORD: ${SPARKY_FITNESS_DB_PASSWORD:?Variable is required and must be set}
SPARKY_FITNESS_APP_DB_USER: ${SPARKY_FITNESS_APP_DB_USER:-sparkyapp}
SPARKY_FITNESS_APP_DB_PASSWORD: ${SPARKY_FITNESS_APP_DB_PASSWORD:?Variable is required and must be set}
SPARKY_FITNESS_DB_PORT: 5432 # Uses internal container port. Do NOT change this if SPARKY_FITNESS_DB_HOST is using container name.
SPARKY_FITNESS_API_ENCRYPTION_KEY: ${SPARKY_FITNESS_API_ENCRYPTION_KEY:?Variable is required and must be set}
# Uncomment the line below and comment the line above to use a file-based secret
# SPARKY_FITNESS_API_ENCRYPTION_KEY_FILE: /run/secrets/sparkyfitness_api_key
BETTER_AUTH_SECRET: ${BETTER_AUTH_SECRET:?Variable is required and must be set}
# Uncomment the line below and comment the line above to use a file-based secret
# BETTER_AUTH_SECRET_FILE: /run/secrets/sparkyfitness_better_auth_secret
SPARKY_FITNESS_FRONTEND_URL: ${SPARKY_FITNESS_FRONTEND_URL:-http://0.0.0.0:3004}
SPARKY_FITNESS_DISABLE_SIGNUP: ${SPARKY_FITNESS_DISABLE_SIGNUP}
SPARKY_FITNESS_ADMIN_EMAIL: ${SPARKY_FITNESS_ADMIN_EMAIL} #User with this email can access the admin panel
SPARKY_FITNESS_EMAIL_HOST: ${SPARKY_FITNESS_EMAIL_HOST}
SPARKY_FITNESS_EMAIL_PORT: ${SPARKY_FITNESS_EMAIL_PORT}
SPARKY_FITNESS_EMAIL_SECURE: ${SPARKY_FITNESS_EMAIL_SECURE}
SPARKY_FITNESS_EMAIL_USER: ${SPARKY_FITNESS_EMAIL_USER}
SPARKY_FITNESS_EMAIL_PASS: ${SPARKY_FITNESS_EMAIL_PASS}
SPARKY_FITNESS_EMAIL_FROM: ${SPARKY_FITNESS_EMAIL_FROM}
GARMIN_MICROSERVICE_URL: http://sparkyfitness-garmin:8000 # Add Garmin microservice URL
PUID: 1000
GUID: 1000
restart: always
depends_on:
- sparkyfitness-db # Backend depends on the database being available
volumes:
- ${SERVER_BACKUP_PATH:-./backup}:/app/SparkyFitnessServer/backup # Mount volume for backups
- ${SERVER_UPLOADS_PATH:-./uploads}:/app/SparkyFitnessServer/uploads # Mount volume for Profile pictures and excercise images
sparkyfitness-frontend:
image: codewithcj/sparkyfitness:latest # Use pre-built image
ports:
- "8087:80" # Map host port 8087 to container port 80 (Nginx)
environment:
SPARKY_FITNESS_FRONTEND_URL: ${SPARKY_FITNESS_FRONTEND_URL}
SPARKY_FITNESS_SERVER_HOST: sparkyfitness-server # Internal Docker service name for the backend
SPARKY_FITNESS_SERVER_PORT: 3010 # Port the backend server listens on
PUID: 1000
GUID: 1000
restart: always
depends_on:
- sparkyfitness-server # Frontend depends on the server
#- sparkyfitness-garmin # Frontend depends on Garmin microservice. Enable if you are using Garmin Connect features.
@@ -0,0 +1,19 @@
services:
speedtest:
container_name: speedtest
image: henrywhitaker3/speedtest-tracker
ports:
- 8085:80
volumes:
- /data/speedtest:/config
environment:
- TZ=Europe/Lisbon
- PGID=1000
- PUID=1000
- OOKLA_EULA_GDPR=true
logging:
driver: "json-file"
options:
max-file: "10"
max-size: "200k"
restart: unless-stopped
-2
View File
@@ -1,2 +0,0 @@
OIDC_CLIENT_SECRET=[[TREKCLIENTSECRET]]
ENCRYPTION_KEY=[[TREKENCRYPTIONKEY]]
+6 -5
View File
@@ -14,23 +14,24 @@ services:
tmpfs: tmpfs:
- /tmp:noexec,nosuid,size=64m - /tmp:noexec,nosuid,size=64m
ports: ports:
- "3000:3000" - "8083:3000"
environment: environment:
- NODE_ENV=production - NODE_ENV=production
- PORT=3000 - PORT=3000
- ENCRYPTION_KEY=${ENCRYPTION_KEY} - ENCRYPTION_KEY=${ENCRYPTION_KEY}
- TZ=Europe/Lisbon - TZ=Europe/Lisbon
- LOG_LEVEL=info - LOG_LEVEL=info
- ALLOWED_ORIGINS=https://trek.lino.cooking - ALLOWED_ORIGINS=https://trips.lino.cooking
- FORCE_HTTPS=true - FORCE_HTTPS=true
- TRUST_PROXY=1 - TRUST_PROXY=1
- ALLOW_INTERNAL_NETWORK=trur - ALLOW_INTERNAL_NETWORK=true
- APP_URL=https://trek.lino.cooking - APP_URL=https://trips.lino.cooking
- OIDC_ISSUER=https://auth.lino.cooking - OIDC_ISSUER=https://auth.lino.cooking
- OIDC_CLIENT_ID=652278a5-b695-4589-9d51-d23cfb2e15dd - OIDC_CLIENT_ID=652278a5-b695-4589-9d51-d23cfb2e15dd
- OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET} - OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET}
- OIDC_DISPLAY_NAME=PocketID - OIDC_DISPLAY_NAME=PocketID
- OIDC_ONLY=true - OIDC_ONLY=true
- OIDC_DISCOVERY_URL=https://auth.lino.cooking/.well-known/openid-configuration
volumes: volumes:
- /data/trek/app:/app/data - /data/trek/app:/app/data
- /data/trek/uploads:/app/uploads - /data/trek/uploads:/app/uploads
@@ -38,6 +39,6 @@ services:
healthcheck: healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/health"] test: ["CMD", "wget", "-qO-", "http://localhost:3000/api/health"]
interval: 30s interval: 30s
timeout: 10s timeout: 15s
retries: 3 retries: 3
start_period: 15s start_period: 15s