From 29a8ff914cf838918ab827280e4415afbce5ca8d Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 29 Aug 2025 21:59:39 +0200 Subject: [PATCH] feat: consolidate setup scripts and guides into unified solution MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Created unified SIMPLE_SETUP.md combining Docker and native installation guides - Created universal scripts/setup.sh supporting both Docker and native installations - Removed redundant setup files (simple-setup.md, simple-setup.sh, scripts/simple-setup.sh) - Added intelligent installation method selection based on system resources - Implemented update and uninstall functionality in unified script - Enhanced with command-line options for unattended installations - Improved cross-platform support (Ubuntu, Debian, RHEL/CentOS, Fedora, Raspberry Pi OS) Fixes #7 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .claude-flow/metrics/system-metrics.json | 572 ++++------- DEPLOYMENT_GUIDE.md | 26 +- SIMPLE_SETUP.md | 519 ++++++++++ scripts/setup.sh | 1184 ++++++++++++++++++++++ simple-setup.md | 276 ----- simple-setup.sh | 941 ----------------- 6 files changed, 1924 insertions(+), 1594 deletions(-) create mode 100644 SIMPLE_SETUP.md create mode 100755 scripts/setup.sh delete mode 100644 simple-setup.md delete mode 100755 simple-setup.sh diff --git a/.claude-flow/metrics/system-metrics.json b/.claude-flow/metrics/system-metrics.json index 1bbe057..4edc398 100644 --- a/.claude-flow/metrics/system-metrics.json +++ b/.claude-flow/metrics/system-metrics.json @@ -1,518 +1,338 @@ [ { - "timestamp": 1756069288374, + "timestamp": 1756496746582, "memoryTotal": 25769803776, - "memoryUsed": 24624726016, - "memoryFree": 1145077760, - "memoryUsagePercent": 95.55651346842447, - "memoryEfficiency": 4.44348653157553, + "memoryUsed": 25277186048, + "memoryFree": 492617728, + "memoryUsagePercent": 98.08839162190756, + "memoryEfficiency": 1.9116083780924384, "cpuCount": 14, - "cpuLoad": 0.20016043526785715, + "cpuLoad": 0.24197823660714285, "platform": "darwin", - "uptime": 4755441 + "uptime": 5182900 }, { - "timestamp": 1756069318375, + "timestamp": 1756496776582, "memoryTotal": 25769803776, - "memoryUsed": 25187663872, - "memoryFree": 582139904, - "memoryUsagePercent": 97.74099985758463, - "memoryEfficiency": 2.259000142415374, + "memoryUsed": 25447661568, + "memoryFree": 322142208, + "memoryUsagePercent": 98.74992370605469, + "memoryEfficiency": 1.2500762939453125, "cpuCount": 14, - "cpuLoad": 0.17435128348214285, + "cpuLoad": 0.1962890625, "platform": "darwin", - "uptime": 4755471 + "uptime": 5182930 }, { - "timestamp": 1756069348375, + "timestamp": 1756496806600, "memoryTotal": 25769803776, - "memoryUsed": 25293045760, - "memoryFree": 476758016, - "memoryUsagePercent": 98.14993540445963, - "memoryEfficiency": 1.850064595540374, + "memoryUsed": 25413042176, + "memoryFree": 356761600, + "memoryUsagePercent": 98.61558278401694, + "memoryEfficiency": 1.3844172159830634, "cpuCount": 14, - "cpuLoad": 0.18059430803571427, + "cpuLoad": 0.22129603794642858, "platform": "darwin", - "uptime": 4755501 + "uptime": 5182960 }, { - "timestamp": 1756069378375, + "timestamp": 1756496836604, "memoryTotal": 25769803776, - "memoryUsed": 25323126784, - "memoryFree": 446676992, - "memoryUsagePercent": 98.26666514078775, - "memoryEfficiency": 1.733334859212249, + "memoryUsed": 25516834816, + "memoryFree": 252968960, + "memoryUsagePercent": 99.01835123697916, + "memoryEfficiency": 0.9816487630208428, "cpuCount": 14, - "cpuLoad": 0.13584681919642858, + "cpuLoad": 0.21344866071428573, "platform": "darwin", - "uptime": 4755531 + "uptime": 5182990 }, { - "timestamp": 1756069408378, + "timestamp": 1756496866605, "memoryTotal": 25769803776, - "memoryUsed": 25281445888, - "memoryFree": 488357888, - "memoryUsagePercent": 98.10492197672525, - "memoryEfficiency": 1.895078023274749, + "memoryUsed": 25414123520, + "memoryFree": 355680256, + "memoryUsagePercent": 98.61977895100912, + "memoryEfficiency": 1.380221048990876, "cpuCount": 14, - "cpuLoad": 0.13201032366071427, + "cpuLoad": 0.21822684151785715, "platform": "darwin", - "uptime": 4755561 + "uptime": 5183020 }, { - "timestamp": 1756069438379, + "timestamp": 1756496896607, "memoryTotal": 25769803776, - "memoryUsed": 25302237184, - "memoryFree": 467566592, - "memoryUsagePercent": 98.18560282389322, - "memoryEfficiency": 1.8143971761067803, + "memoryUsed": 25196363776, + "memoryFree": 573440000, + "memoryUsagePercent": 97.77475992838541, + "memoryEfficiency": 2.225240071614593, "cpuCount": 14, - "cpuLoad": 0.15656389508928573, + "cpuLoad": 0.20950753348214285, "platform": "darwin", - "uptime": 4755591 + "uptime": 5183050 }, { - "timestamp": 1756069468380, + "timestamp": 1756496926609, "memoryTotal": 25769803776, - "memoryUsed": 25389481984, - "memoryFree": 380321792, - "memoryUsagePercent": 98.52415720621744, - "memoryEfficiency": 1.4758427937825616, + "memoryUsed": 25503711232, + "memoryFree": 266092544, + "memoryUsagePercent": 98.96742502848306, + "memoryEfficiency": 1.0325749715169366, "cpuCount": 14, - "cpuLoad": 0.190185546875, + "cpuLoad": 0.23154994419642858, "platform": "darwin", - "uptime": 4755621 + "uptime": 5183080 }, { - "timestamp": 1756069498381, + "timestamp": 1756496956610, "memoryTotal": 25769803776, - "memoryUsed": 25366888448, - "memoryFree": 402915328, - "memoryUsagePercent": 98.43648274739584, - "memoryEfficiency": 1.5635172526041572, + "memoryUsed": 25550979072, + "memoryFree": 218824704, + "memoryUsagePercent": 99.15084838867188, + "memoryEfficiency": 0.849151611328125, "cpuCount": 14, - "cpuLoad": 0.16587611607142858, + "cpuLoad": 0.20741489955357142, "platform": "darwin", - "uptime": 4755651 + "uptime": 5183110 }, { - "timestamp": 1756069528382, + "timestamp": 1756496986609, "memoryTotal": 25769803776, - "memoryUsed": 25608175616, - "memoryFree": 161628160, - "memoryUsagePercent": 99.3728001912435, - "memoryEfficiency": 0.6271998087565009, + "memoryUsed": 25552404480, + "memoryFree": 217399296, + "memoryUsagePercent": 99.15637969970703, + "memoryEfficiency": 0.8436203002929688, "cpuCount": 14, - "cpuLoad": 0.17508370535714285, + "cpuLoad": 0.22112165178571427, "platform": "darwin", - "uptime": 4755681 + "uptime": 5183140 }, { - "timestamp": 1756069558384, + "timestamp": 1756497016611, "memoryTotal": 25769803776, - "memoryUsed": 25126961152, - "memoryFree": 642842624, - "memoryUsagePercent": 97.50544230143228, - "memoryEfficiency": 2.494557698567718, + "memoryUsed": 25680560128, + "memoryFree": 89243648, + "memoryUsagePercent": 99.653689066569, + "memoryEfficiency": 0.34631093343099906, "cpuCount": 14, - "cpuLoad": 0.17497907366071427, + "cpuLoad": 0.23615373883928573, "platform": "darwin", - "uptime": 4755711 + "uptime": 5183170 }, { - "timestamp": 1756069588385, + "timestamp": 1756497046610, "memoryTotal": 25769803776, - "memoryUsed": 25449037824, - "memoryFree": 320765952, - "memoryUsagePercent": 98.75526428222656, - "memoryEfficiency": 1.2447357177734375, + "memoryUsed": 25631408128, + "memoryFree": 138395648, + "memoryUsagePercent": 99.46295420328775, + "memoryEfficiency": 0.5370457967122491, "cpuCount": 14, - "cpuLoad": 0.149169921875, + "cpuLoad": 0.19859095982142858, "platform": "darwin", - "uptime": 4755741 + "uptime": 5183200 }, { - "timestamp": 1756069618386, + "timestamp": 1756497076611, "memoryTotal": 25769803776, - "memoryUsed": 25644417024, - "memoryFree": 125386752, - "memoryUsagePercent": 99.51343536376953, - "memoryEfficiency": 0.48656463623046875, + "memoryUsed": 25655099392, + "memoryFree": 114704384, + "memoryUsagePercent": 99.55488840738931, + "memoryEfficiency": 0.44511159261068656, "cpuCount": 14, - "cpuLoad": 0.16245814732142858, + "cpuLoad": 0.23831612723214285, "platform": "darwin", - "uptime": 4755771 + "uptime": 5183230 }, { - "timestamp": 1756069648386, + "timestamp": 1756497106613, "memoryTotal": 25769803776, - "memoryUsed": 25567952896, - "memoryFree": 201850880, - "memoryUsagePercent": 99.21671549479166, - "memoryEfficiency": 0.7832845052083428, + "memoryUsed": 25590169600, + "memoryFree": 179634176, + "memoryUsagePercent": 99.30292765299478, + "memoryEfficiency": 0.6970723470052178, "cpuCount": 14, - "cpuLoad": 0.17110770089285715, + "cpuLoad": 0.29031808035714285, "platform": "darwin", - "uptime": 4755801 + "uptime": 5183260 }, { - "timestamp": 1756069678387, + "timestamp": 1756497136613, "memoryTotal": 25769803776, - "memoryUsed": 25535414272, - "memoryFree": 234389504, - "memoryUsagePercent": 99.09044901529947, - "memoryEfficiency": 0.9095509847005303, + "memoryUsed": 25682378752, + "memoryFree": 87425024, + "memoryUsagePercent": 99.66074625651041, + "memoryEfficiency": 0.3392537434895928, "cpuCount": 14, - "cpuLoad": 0.17755998883928573, + "cpuLoad": 0.26834542410714285, "platform": "darwin", - "uptime": 4755831 + "uptime": 5183290 }, { - "timestamp": 1756069708388, + "timestamp": 1756497166614, "memoryTotal": 25769803776, - "memoryUsed": 25529073664, - "memoryFree": 240730112, - "memoryUsagePercent": 99.06584421793619, - "memoryEfficiency": 0.9341557820638116, + "memoryUsed": 25591283712, + "memoryFree": 178520064, + "memoryUsagePercent": 99.3072509765625, + "memoryEfficiency": 0.6927490234375, "cpuCount": 14, - "cpuLoad": 0.18059430803571427, + "cpuLoad": 0.2820521763392857, "platform": "darwin", - "uptime": 4755861 + "uptime": 5183320 }, { - "timestamp": 1756069738390, + "timestamp": 1756497196616, "memoryTotal": 25769803776, - "memoryUsed": 25574866944, - "memoryFree": 194936832, - "memoryUsagePercent": 99.24354553222656, - "memoryEfficiency": 0.7564544677734375, + "memoryUsed": 25577848832, + "memoryFree": 191954944, + "memoryUsagePercent": 99.25511678059897, + "memoryEfficiency": 0.7448832194010322, "cpuCount": 14, - "cpuLoad": 0.18073381696428573, + "cpuLoad": 0.23618861607142858, "platform": "darwin", - "uptime": 4755891 + "uptime": 5183350 }, { - "timestamp": 1756069768392, + "timestamp": 1756497226617, "memoryTotal": 25769803776, - "memoryUsed": 25546063872, - "memoryFree": 223739904, - "memoryUsagePercent": 99.13177490234375, - "memoryEfficiency": 0.86822509765625, + "memoryUsed": 25343754240, + "memoryFree": 426049536, + "memoryUsagePercent": 98.34671020507812, + "memoryEfficiency": 1.653289794921875, "cpuCount": 14, - "cpuLoad": 0.18244280133928573, + "cpuLoad": 0.23228236607142858, "platform": "darwin", - "uptime": 4755921 + "uptime": 5183380 }, { - "timestamp": 1756069798393, + "timestamp": 1756497256617, "memoryTotal": 25769803776, - "memoryUsed": 25663946752, - "memoryFree": 105857024, - "memoryUsagePercent": 99.58922068277994, - "memoryEfficiency": 0.41077931722006156, + "memoryUsed": 25662668800, + "memoryFree": 107134976, + "memoryUsagePercent": 99.58426157633463, + "memoryEfficiency": 0.41573842366537406, "cpuCount": 14, - "cpuLoad": 0.15778459821428573, + "cpuLoad": 0.19471958705357142, "platform": "darwin", - "uptime": 4755951 + "uptime": 5183410 }, { - "timestamp": 1756069828394, + "timestamp": 1756497286619, "memoryTotal": 25769803776, - "memoryUsed": 25486589952, - "memoryFree": 283213824, - "memoryUsagePercent": 98.90098571777344, - "memoryEfficiency": 1.0990142822265625, + "memoryUsed": 25610125312, + "memoryFree": 159678464, + "memoryUsagePercent": 99.38036600748697, + "memoryEfficiency": 0.6196339925130303, "cpuCount": 14, - "cpuLoad": 0.19245256696428573, + "cpuLoad": 0.19126674107142858, "platform": "darwin", - "uptime": 4755981 + "uptime": 5183440 }, { - "timestamp": 1756069858395, + "timestamp": 1756497316620, "memoryTotal": 25769803776, - "memoryUsed": 25451380736, - "memoryFree": 318423040, - "memoryUsagePercent": 98.76435597737631, - "memoryEfficiency": 1.2356440226236884, + "memoryUsed": 25256427520, + "memoryFree": 513376256, + "memoryUsagePercent": 98.0078379313151, + "memoryEfficiency": 1.9921620686849053, "cpuCount": 14, - "cpuLoad": 0.17762974330357142, + "cpuLoad": 0.15576171875, "platform": "darwin", - "uptime": 4756011 + "uptime": 5183470 }, { - "timestamp": 1756069888397, + "timestamp": 1756497346620, "memoryTotal": 25769803776, - "memoryUsed": 25088442368, - "memoryFree": 681361408, - "memoryUsagePercent": 97.35596974690756, - "memoryEfficiency": 2.6440302530924384, + "memoryUsed": 25464700928, + "memoryFree": 305102848, + "memoryUsagePercent": 98.81604512532553, + "memoryEfficiency": 1.1839548746744697, "cpuCount": 14, - "cpuLoad": 0.159912109375, + "cpuLoad": 0.21369280133928573, "platform": "darwin", - "uptime": 4756041 + "uptime": 5183500 }, { - "timestamp": 1756069918398, + "timestamp": 1756497376620, "memoryTotal": 25769803776, - "memoryUsed": 25246859264, - "memoryFree": 522944512, - "memoryUsagePercent": 97.97070821126303, - "memoryEfficiency": 2.0292917887369697, + "memoryUsed": 25632653312, + "memoryFree": 137150464, + "memoryUsagePercent": 99.46778615315756, + "memoryEfficiency": 0.5322138468424384, "cpuCount": 14, - "cpuLoad": 0.12831333705357142, + "cpuLoad": 0.201904296875, "platform": "darwin", - "uptime": 4756071 + "uptime": 5183530 }, { - "timestamp": 1756069948399, + "timestamp": 1756497406621, "memoryTotal": 25769803776, - "memoryUsed": 25182126080, - "memoryFree": 587677696, - "memoryUsagePercent": 97.71951039632162, - "memoryEfficiency": 2.280489603678376, + "memoryUsed": 25066160128, + "memoryFree": 703643648, + "memoryUsagePercent": 97.26950327555338, + "memoryEfficiency": 2.730496724446624, "cpuCount": 14, - "cpuLoad": 0.1826171875, + "cpuLoad": 0.192626953125, "platform": "darwin", - "uptime": 4756101 + "uptime": 5183560 }, { - "timestamp": 1756069978401, + "timestamp": 1756497436623, "memoryTotal": 25769803776, - "memoryUsed": 25322684416, - "memoryFree": 447119360, - "memoryUsagePercent": 98.26494852701822, - "memoryEfficiency": 1.7350514729817803, + "memoryUsed": 25574244352, + "memoryFree": 195559424, + "memoryUsagePercent": 99.24112955729166, + "memoryEfficiency": 0.7588704427083428, "cpuCount": 14, - "cpuLoad": 0.18136160714285715, + "cpuLoad": 0.19761439732142858, "platform": "darwin", - "uptime": 4756131 + "uptime": 5183590 }, { - "timestamp": 1756070008402, + "timestamp": 1756497466624, "memoryTotal": 25769803776, - "memoryUsed": 25357484032, - "memoryFree": 412319744, - "memoryUsagePercent": 98.39998881022134, - "memoryEfficiency": 1.6000111897786553, + "memoryUsed": 25427623936, + "memoryFree": 342179840, + "memoryUsagePercent": 98.67216746012369, + "memoryEfficiency": 1.3278325398763116, "cpuCount": 14, - "cpuLoad": 0.18488420758928573, + "cpuLoad": 0.20005580357142858, "platform": "darwin", - "uptime": 4756161 + "uptime": 5183620 }, { - "timestamp": 1756070038402, + "timestamp": 1756497496626, "memoryTotal": 25769803776, - "memoryUsed": 25503760384, - "memoryFree": 266043392, - "memoryUsagePercent": 98.96761576334634, - "memoryEfficiency": 1.0323842366536553, + "memoryUsed": 25596116992, + "memoryFree": 173686784, + "memoryUsagePercent": 99.32600657145181, + "memoryEfficiency": 0.6739934285481866, "cpuCount": 14, - "cpuLoad": 0.18415178571428573, + "cpuLoad": 0.19367327008928573, "platform": "darwin", - "uptime": 4756191 + "uptime": 5183650 }, { - "timestamp": 1756070068403, + "timestamp": 1756497526626, "memoryTotal": 25769803776, - "memoryUsed": 25171984384, - "memoryFree": 597819392, - "memoryUsagePercent": 97.68015543619791, - "memoryEfficiency": 2.319844563802093, + "memoryUsed": 25207111680, + "memoryFree": 562692096, + "memoryUsagePercent": 97.81646728515625, + "memoryEfficiency": 2.18353271484375, "cpuCount": 14, - "cpuLoad": 0.22530691964285715, + "cpuLoad": 0.15276227678571427, "platform": "darwin", - "uptime": 4756221 + "uptime": 5183680 }, { - "timestamp": 1756070098405, + "timestamp": 1756497556628, "memoryTotal": 25769803776, - "memoryUsed": 25521356800, - "memoryFree": 248446976, - "memoryUsagePercent": 99.03589884440103, - "memoryEfficiency": 0.9641011555989678, + "memoryUsed": 25510182912, + "memoryFree": 259620864, + "memoryUsagePercent": 98.99253845214844, + "memoryEfficiency": 1.0074615478515625, "cpuCount": 14, - "cpuLoad": 0.20929827008928573, + "cpuLoad": 0.13654436383928573, "platform": "darwin", - "uptime": 4756251 - }, - { - "timestamp": 1756070128388, - "memoryTotal": 25769803776, - "memoryUsed": 25556877312, - "memoryFree": 212926464, - "memoryUsagePercent": 99.17373657226562, - "memoryEfficiency": 0.826263427734375, - "cpuCount": 14, - "cpuLoad": 0.19838169642857142, - "platform": "darwin", - "uptime": 4756281 - }, - { - "timestamp": 1756070158382, - "memoryTotal": 25769803776, - "memoryUsed": 25423691776, - "memoryFree": 346112000, - "memoryUsagePercent": 98.65690867106119, - "memoryEfficiency": 1.3430913289388116, - "cpuCount": 14, - "cpuLoad": 0.23814174107142858, - "platform": "darwin", - "uptime": 4756311 - }, - { - "timestamp": 1756070188381, - "memoryTotal": 25769803776, - "memoryUsed": 24874237952, - "memoryFree": 895565824, - "memoryUsagePercent": 96.52474721272787, - "memoryEfficiency": 3.475252787272126, - "cpuCount": 14, - "cpuLoad": 0.22272600446428573, - "platform": "darwin", - "uptime": 4756341 - }, - { - "timestamp": 1756070218381, - "memoryTotal": 25769803776, - "memoryUsed": 24984682496, - "memoryFree": 785121280, - "memoryUsagePercent": 96.95332845052084, - "memoryEfficiency": 3.046671549479157, - "cpuCount": 14, - "cpuLoad": 0.23807198660714285, - "platform": "darwin", - "uptime": 4756371 - }, - { - "timestamp": 1756070248383, - "memoryTotal": 25769803776, - "memoryUsed": 25002754048, - "memoryFree": 767049728, - "memoryUsagePercent": 97.02345530192056, - "memoryEfficiency": 2.9765446980794366, - "cpuCount": 14, - "cpuLoad": 0.22795758928571427, - "platform": "darwin", - "uptime": 4756401 - }, - { - "timestamp": 1756070278384, - "memoryTotal": 25769803776, - "memoryUsed": 25581617152, - "memoryFree": 188186624, - "memoryUsagePercent": 99.26973978678384, - "memoryEfficiency": 0.7302602132161553, - "cpuCount": 14, - "cpuLoad": 0.19461495535714285, - "platform": "darwin", - "uptime": 4756431 - }, - { - "timestamp": 1756070308384, - "memoryTotal": 25769803776, - "memoryUsed": 25362219008, - "memoryFree": 407584768, - "memoryUsagePercent": 98.41836293538412, - "memoryEfficiency": 1.581637064615876, - "cpuCount": 14, - "cpuLoad": 0.23835100446428573, - "platform": "darwin", - "uptime": 4756461 - }, - { - "timestamp": 1756070338385, - "memoryTotal": 25769803776, - "memoryUsed": 25515917312, - "memoryFree": 253886464, - "memoryUsagePercent": 99.01479085286459, - "memoryEfficiency": 0.9852091471354072, - "cpuCount": 14, - "cpuLoad": 0.189208984375, - "platform": "darwin", - "uptime": 4756491 - }, - { - "timestamp": 1756070368387, - "memoryTotal": 25769803776, - "memoryUsed": 25517277184, - "memoryFree": 252526592, - "memoryUsagePercent": 99.02006785074869, - "memoryEfficiency": 0.9799321492513116, - "cpuCount": 14, - "cpuLoad": 0.22147042410714285, - "platform": "darwin", - "uptime": 4756521 - }, - { - "timestamp": 1756070398388, - "memoryTotal": 25769803776, - "memoryUsed": 25596608512, - "memoryFree": 173195264, - "memoryUsagePercent": 99.32791392008463, - "memoryEfficiency": 0.6720860799153741, - "cpuCount": 14, - "cpuLoad": 0.16423688616071427, - "platform": "darwin", - "uptime": 4756551 - }, - { - "timestamp": 1756070428388, - "memoryTotal": 25769803776, - "memoryUsed": 25535250432, - "memoryFree": 234553344, - "memoryUsagePercent": 99.08981323242188, - "memoryEfficiency": 0.910186767578125, - "cpuCount": 14, - "cpuLoad": 0.14815848214285715, - "platform": "darwin", - "uptime": 4756581 - }, - { - "timestamp": 1756070458390, - "memoryTotal": 25769803776, - "memoryUsed": 25610747904, - "memoryFree": 159055872, - "memoryUsagePercent": 99.38278198242188, - "memoryEfficiency": 0.617218017578125, - "cpuCount": 14, - "cpuLoad": 0.12758091517857142, - "platform": "darwin", - "uptime": 4756611 - }, - { - "timestamp": 1756070488391, - "memoryTotal": 25769803776, - "memoryUsed": 25343475712, - "memoryFree": 426328064, - "memoryUsagePercent": 98.34562937418619, - "memoryEfficiency": 1.6543706258138116, - "cpuCount": 14, - "cpuLoad": 0.13835797991071427, - "platform": "darwin", - "uptime": 4756641 - }, - { - "timestamp": 1756070518391, - "memoryTotal": 25769803776, - "memoryUsed": 25244123136, - "memoryFree": 525680640, - "memoryUsagePercent": 97.96009063720703, - "memoryEfficiency": 2.0399093627929688, - "cpuCount": 14, - "cpuLoad": 0.11725725446428571, - "platform": "darwin", - "uptime": 4756671 - }, - { - "timestamp": 1756070548393, - "memoryTotal": 25769803776, - "memoryUsed": 25330614272, - "memoryFree": 439189504, - "memoryUsagePercent": 98.29572041829428, - "memoryEfficiency": 1.7042795817057197, - "cpuCount": 14, - "cpuLoad": 0.151611328125, - "platform": "darwin", - "uptime": 4756701 + "uptime": 5183710 } ] \ No newline at end of file diff --git a/DEPLOYMENT_GUIDE.md b/DEPLOYMENT_GUIDE.md index 7eeefc1..bddc24e 100644 --- a/DEPLOYMENT_GUIDE.md +++ b/DEPLOYMENT_GUIDE.md @@ -1,6 +1,30 @@ # 🚀 PicPeak Deployment Guide -This guide covers deploying PicPeak using Docker Compose with direct port exposure. For internet-facing deployments, you'll need to add a reverse proxy (nginx, Traefik, Caddy, etc.) for SSL/HTTPS. +This guide covers multiple deployment options for PicPeak, from simple local setups to production-ready configurations. + +## đŸŽ¯ Quick Start - Simple Setup (Recommended for Beginners) + +For the easiest installation without Docker or complex configurations, use our **simple setup script**: + +```bash +curl -fsSL https://raw.githubusercontent.com/yourusername/wedding-photo-sharing/main/scripts/simple-setup.sh -o setup.sh && \ +chmod +x setup.sh && \ +sudo ./setup.sh +``` + +This automated script handles everything including OS detection, dependencies, database setup, and service configuration. Perfect for: +- Small to medium deployments +- Local or VPS installations +- Users who prefer avoiding Docker complexity +- Quick testing and evaluation + +👉 **See [SIMPLE_SETUP_GUIDE.md](./SIMPLE_SETUP_GUIDE.md) for detailed instructions.** + +--- + +## đŸŗ Docker Compose Deployment + +This section covers deploying PicPeak using Docker Compose with direct port exposure. For internet-facing deployments, you'll need to add a reverse proxy (nginx, Traefik, Caddy, etc.) for SSL/HTTPS. ## 📋 Table of Contents diff --git a/SIMPLE_SETUP.md b/SIMPLE_SETUP.md new file mode 100644 index 0000000..4e25157 --- /dev/null +++ b/SIMPLE_SETUP.md @@ -0,0 +1,519 @@ +# 🚀 PicPeak Simple Setup Guide + +This guide provides easy installation instructions for PicPeak on Linux servers with both Docker and non-Docker options. + +## 📋 Quick Start + +### One-Line Installation + +```bash +# Download and run the unified setup script +curl -fsSL https://raw.githubusercontent.com/yourusername/wedding-photo-sharing/main/scripts/setup.sh -o setup.sh && \ +chmod +x setup.sh && \ +sudo ./setup.sh +``` + +The script will automatically detect your environment and recommend the best installation method. + +## đŸŽ¯ Installation Methods + +### Method 1: Docker Installation (Recommended) +Best for: Most users, easy updates, isolated environment + +```bash +sudo ./setup.sh --docker +``` + +**Pros:** +- ✅ Easier installation and updates +- ✅ Better isolation from system +- ✅ Consistent environment across platforms +- ✅ Built-in PostgreSQL and Redis + +**Cons:** +- ❌ Requires more resources (~4GB RAM recommended) +- ❌ Additional Docker overhead + +### Method 2: Native Installation +Best for: Resource-constrained systems, Raspberry Pi, direct control + +```bash +sudo ./setup.sh --native +``` + +**Pros:** +- ✅ Lower resource usage (~1GB RAM minimum) +- ✅ Direct system control +- ✅ No Docker overhead +- ✅ Better for ARM devices + +**Cons:** +- ❌ More complex setup +- ❌ System dependencies required +- ❌ Manual update process + +## 📋 System Requirements + +### Minimum Requirements +- **OS**: Ubuntu 20.04+, Debian 11+, Fedora 38+, RHEL/CentOS 8+, Raspberry Pi OS +- **RAM**: + - Docker: 2GB minimum (4GB recommended) + - Native: 1GB minimum (2GB recommended) +- **Storage**: 2GB for application + space for photos +- **Network**: Port 3001 (or 80/443 with proxy) + +### Supported Platforms +- ✅ Ubuntu 20.04, 22.04, 24.04 +- ✅ Debian 11, 12 +- ✅ Raspberry Pi OS (32-bit and 64-bit) +- ✅ Fedora 38, 39, 40 +- ✅ RHEL/CentOS/Rocky/AlmaLinux 8, 9 + +## đŸ› ī¸ Installation Options + +### Interactive Mode (Default) +```bash +sudo ./setup.sh +``` + +The script will prompt you to choose: +1. Installation method (Docker or Native) +2. Admin email and password +3. Domain configuration (optional) +4. Email server settings (optional) +5. SSL/HTTPS setup (optional) + +### Unattended Installation + +#### Docker with full configuration: +```bash +sudo ./setup.sh --docker --unattended \ + --domain photos.example.com \ + --email admin@example.com \ + --admin-password SecurePass123 \ + --smtp-host smtp.gmail.com \ + --smtp-port 587 \ + --smtp-user your-email@gmail.com \ + --smtp-pass your-app-password \ + --enable-ssl +``` + +#### Native with minimal configuration: +```bash +sudo ./setup.sh --native --unattended \ + --email admin@example.com \ + --admin-password SecurePass123 +``` + +### Command Line Options + +| Option | Description | Example | +|--------|-------------|---------| +| `--docker` | Use Docker installation | `--docker` | +| `--native` | Use native installation | `--native` | +| `--unattended` | Run without prompts | `--unattended` | +| `--domain` | Domain for HTTPS setup | `--domain photos.example.com` | +| `--email` | Admin email address | `--email admin@example.com` | +| `--admin-password` | Set admin password | `--admin-password MySecurePass` | +| `--smtp-host` | SMTP server hostname | `--smtp-host smtp.gmail.com` | +| `--smtp-port` | SMTP server port | `--smtp-port 587` | +| `--smtp-user` | SMTP username | `--smtp-user user@gmail.com` | +| `--smtp-pass` | SMTP password | `--smtp-pass app-password` | +| `--enable-ssl` | Enable HTTPS with Let's Encrypt | `--enable-ssl` | +| `--port` | Custom port (native only) | `--port 8080` | +| `--update` | Update existing installation | `--update` | +| `--uninstall` | Remove installation | `--uninstall` | +| `--help` | Show help message | `--help` | + +## đŸ—ī¸ What Gets Installed + +### Docker Installation +``` +~/picpeak/ # Or custom directory +├── docker-compose.yml # Service definitions +├── .env # Configuration +├── storage/ +│ └── events/ # Photo storage +│ ├── active/ # Current galleries +│ └── archived/ # Expired galleries +├── logs/ # Application logs +└── backup/ # Backup directory +``` + +**Services:** +- PicPeak Backend (Node.js application) +- PostgreSQL Database +- Redis Cache +- Nginx Reverse Proxy (optional) +- Background Workers + +### Native Installation +``` +/opt/picpeak/ # Installation directory +├── backend/ # Application code +├── events/ # Photo storage +│ ├── active/ # Current galleries +│ └── archived/ # Expired galleries +├── logs/ # Application logs +└── config/ # Configuration files +``` + +**Services (systemd):** +- `picpeak-backend` - Main application +- `picpeak-workers` - Background workers +- `caddy` - Web server (optional) + +## 🌐 Access Methods + +### Direct Access (Simplest) +- **Docker**: `http://your-server:3000` (frontend), `http://your-server:3001/admin` (admin) +- **Native**: `http://your-server:3001/admin` (admin panel) + +### With Domain & HTTPS +If configured during setup: +- `https://your-domain.com` - Gallery frontend +- `https://your-domain.com/admin` - Admin panel + +### Behind Existing Proxy +Add to your Nginx/Apache configuration: +```nginx +location / { + proxy_pass http://localhost:3001; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection 'upgrade'; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + client_max_body_size 100M; +} +``` + +## 📁 Managing Galleries + +### Creating a Gallery + +#### Method 1: Via Admin Panel (Recommended) +1. Login to admin panel +2. Click "Create New Event" +3. Configure settings and upload photos + +#### Method 2: File System +```bash +# Docker installation +mkdir -p ~/picpeak/storage/events/active/wedding-smith-2024 +cp /path/to/photos/* ~/picpeak/storage/events/active/wedding-smith-2024/ + +# Native installation +sudo mkdir -p /opt/picpeak/events/active/wedding-smith-2024 +sudo cp /path/to/photos/* /opt/picpeak/events/active/wedding-smith-2024/ +sudo chown -R picpeak:picpeak /opt/picpeak/events/active/wedding-smith-2024 +``` + +### Gallery Structure +``` +wedding-smith-2024/ +├── collages/ # Group photos +├── individual/ # Individual photos +└── thumbnails/ # Auto-generated thumbnails +``` + +## 🔧 Service Management + +### Docker Installation + +```bash +cd ~/picpeak + +# Check status +docker compose ps + +# View logs +docker compose logs -f + +# Stop services +docker compose down + +# Start services +docker compose up -d + +# Restart services +docker compose restart + +# Update PicPeak +docker compose pull +docker compose up -d +``` + +### Native Installation + +```bash +# Check status +sudo systemctl status picpeak-backend +sudo systemctl status picpeak-workers + +# View logs +sudo journalctl -u picpeak-backend -f +sudo journalctl -u picpeak-workers -f + +# Start services +sudo systemctl start picpeak-backend picpeak-workers + +# Stop services +sudo systemctl stop picpeak-backend picpeak-workers + +# Restart services +sudo systemctl restart picpeak-backend picpeak-workers + +# Update PicPeak +sudo ./setup.sh --update +``` + +## âš™ī¸ Configuration + +### Docker Configuration +Edit `~/picpeak/.env`: +```bash +nano ~/picpeak/.env +docker compose restart +``` + +### Native Configuration +Edit `/opt/picpeak/backend/.env`: +```bash +sudo nano /opt/picpeak/backend/.env +sudo systemctl restart picpeak-backend +``` + +### Key Settings + +| Setting | Description | Default | +|---------|-------------|---------| +| `JWT_SECRET` | Token signing secret | Auto-generated | +| `ADMIN_EMAIL` | Admin email | admin@example.com | +| `ADMIN_PASSWORD` | Admin password | Auto-generated | +| `PHOTOS_DIR` | Photo storage path | Varies by method | +| `SMTP_ENABLED` | Email notifications | false | +| `DEFAULT_EXPIRY_DAYS` | Gallery expiration | 30 | + +## 📧 Email Configuration + +### Gmail Setup +1. Enable 2-Factor Authentication +2. Generate App Password +3. Configure: +```env +SMTP_ENABLED=true +SMTP_HOST=smtp.gmail.com +SMTP_PORT=587 +SMTP_SECURE=false +SMTP_USER=your-email@gmail.com +SMTP_PASS=your-app-password +SMTP_FROM=noreply@yourdomain.com +``` + +### SendGrid Setup +1. Sign up at sendgrid.com (100 emails/day free) +2. Create API key +3. Configure: +```env +SMTP_ENABLED=true +SMTP_HOST=smtp.sendgrid.net +SMTP_PORT=587 +SMTP_USER=apikey +SMTP_PASS=your-sendgrid-api-key +SMTP_FROM=verified-sender@yourdomain.com +``` + +## 🔄 Maintenance + +### Backups + +#### Docker: +```bash +# Backup script included +cd ~/picpeak +./backup.sh + +# Manual backup +docker exec picpeak-postgres pg_dump -U picpeak picpeak > backup.sql +tar -czf photos-backup.tar.gz storage/events/ +``` + +#### Native: +```bash +# Database backup +sudo cp /opt/picpeak/backend/database.sqlite /backup/database-$(date +%Y%m%d).sqlite + +# Photos backup +sudo tar -czf /backup/photos-$(date +%Y%m%d).tar.gz /opt/picpeak/events/ +``` + +### Updates + +```bash +# Docker +cd ~/picpeak +docker compose pull +docker compose up -d + +# Native +sudo ./setup.sh --update +``` + +### Uninstall + +```bash +# Will prompt for confirmation and data removal options +sudo ./setup.sh --uninstall +``` + +## 🐛 Troubleshooting + +### Common Issues + +#### Service Won't Start +```bash +# Docker +docker compose logs backend +docker compose down && docker compose up -d + +# Native +sudo journalctl -u picpeak-backend -n 50 +sudo systemctl restart picpeak-backend +``` + +#### Can't Access Admin Panel +1. Check firewall: +```bash +# Ubuntu/Debian +sudo ufw allow 3001 + +# RHEL/CentOS +sudo firewall-cmd --add-port=3001/tcp --permanent +sudo firewall-cmd --reload +``` + +2. Verify service: +```bash +# Docker +curl http://localhost:3001/api/health + +# Native +sudo systemctl is-active picpeak-backend +``` + +#### Photos Not Showing +```bash +# Check permissions (Native) +sudo chown -R picpeak:picpeak /opt/picpeak/events/ +sudo chmod -R 755 /opt/picpeak/events/ + +# Check permissions (Docker) +ls -la ~/picpeak/storage/events/ +``` + +#### Reset Admin Password + +```bash +# Docker +docker exec picpeak-backend node scripts/reset-admin-password.js + +# Native +cd /opt/picpeak/backend +sudo -u picpeak node scripts/reset-admin-password.js +``` + +### Getting Help + +1. **Check logs:** + - Docker: `docker compose logs -f` + - Native: `sudo journalctl -u picpeak-backend -f` + - Installation: `/tmp/picpeak-setup-*.log` + +2. **Documentation:** + - [Full Documentation](https://github.com/yourusername/wedding-photo-sharing) + - [Deployment Guide](./DEPLOYMENT_GUIDE.md) + +3. **Support:** + - [GitHub Issues](https://github.com/yourusername/wedding-photo-sharing/issues) + - Include: Error messages, system info (`uname -a`), installation method + +## 🔒 Security Best Practices + +### Essential Security +1. **Change default admin password immediately** +2. **Use HTTPS for production** (Let's Encrypt included) +3. **Configure firewall** (only open necessary ports) +4. **Regular updates** (system and PicPeak) +5. **Automated backups** (configure in admin panel) + +### Advanced Security +- Use VPN for admin panel access +- Configure fail2ban for brute force protection +- Enable audit logging +- Regular security scans +- Implement IP whitelisting + +## 📊 Performance Optimization + +### Docker Optimization +```yaml +# Adjust in docker-compose.yml +services: + backend: + deploy: + resources: + limits: + cpus: '2' + memory: 2G +``` + +### Native Optimization +```bash +# Increase Node.js memory +echo "NODE_OPTIONS=--max-old-space-size=2048" >> /opt/picpeak/backend/.env +sudo systemctl restart picpeak-backend +``` + +## đŸŽ¯ Quick Setup Examples + +### Home/Office Network +```bash +# Simple local setup without domain +sudo ./setup.sh --native --email admin@local.com +``` + +### Public Website with HTTPS +```bash +# Full production setup +sudo ./setup.sh --docker \ + --domain photos.company.com \ + --email admin@company.com \ + --enable-ssl +``` + +### Raspberry Pi Setup +```bash +# Optimized for ARM devices +sudo ./setup.sh --native \ + --port 8080 \ + --email pi@local.com +``` + +## ✅ Post-Installation Checklist + +- [ ] Admin password changed +- [ ] Email configuration tested +- [ ] First test gallery created +- [ ] Backup schedule configured +- [ ] Firewall rules applied +- [ ] SSL certificate working (if applicable) +- [ ] Monitoring setup +- [ ] Documentation bookmarked + +--- + +**PicPeak Setup v1.0** | [Documentation](https://github.com/yourusername/wedding-photo-sharing) | [Support](https://github.com/yourusername/wedding-photo-sharing/issues) \ No newline at end of file diff --git a/scripts/setup.sh b/scripts/setup.sh new file mode 100755 index 0000000..dc50d7e --- /dev/null +++ b/scripts/setup.sh @@ -0,0 +1,1184 @@ +#!/usr/bin/env bash + +################################################################################ +# PicPeak Unified Setup Script +# Version: 2.0.0 +# Description: Universal installer for PicPeak with Docker and Native options +# Supports: Ubuntu, Debian, Fedora, RHEL/CentOS, Raspberry Pi OS +################################################################################ + +set -euo pipefail +IFS=$'\n\t' + +# Script configuration +readonly SCRIPT_VERSION="2.0.0" +readonly APP_NAME="PicPeak" +readonly REPO_URL="https://github.com/yourusername/wedding-photo-sharing" +readonly NODE_VERSION="20" +readonly MIN_RAM_DOCKER=2048 +readonly MIN_RAM_NATIVE=1024 +readonly MIN_DISK_GB=2 +readonly DEFAULT_PORT=3001 + +# Installation paths +readonly NATIVE_APP_DIR="/opt/picpeak" +readonly NATIVE_APP_USER="picpeak" +readonly DOCKER_APP_DIR="$HOME/picpeak" + +# Color codes for output +readonly RED='\033[0;31m' +readonly GREEN='\033[0;32m' +readonly YELLOW='\033[1;33m' +readonly BLUE='\033[0;34m' +readonly PURPLE='\033[0;35m' +readonly CYAN='\033[0;36m' +readonly NC='\033[0m' # No Color + +# Logging +readonly LOG_FILE="/tmp/picpeak-setup-$(date +%Y%m%d-%H%M%S).log" +exec 1> >(tee -a "$LOG_FILE") +exec 2>&1 + +# Global variables +INSTALL_METHOD="" # docker or native +OS_TYPE="" +OS_VERSION="" +PACKAGE_MANAGER="" +ADMIN_PASSWORD="" +ADMIN_EMAIL="admin@example.com" +DOMAIN_NAME="" +SMTP_HOST="" +SMTP_PORT="" +SMTP_USER="" +SMTP_PASS="" +ENABLE_SSL=false +CUSTOM_PORT="" +UNATTENDED=false +UPDATE_MODE=false +UNINSTALL_MODE=false + +################################################################################ +# Helper Functions +################################################################################ + +print_banner() { + echo -e "${PURPLE}" + echo "╔════════════════════════════════════════════════════════════════════════╗" + echo "║ ║" + echo "║ ____ _ ____ _ ____ _ ║" + echo "║ | _ \\(_) ___| _ \\ ___ __ _| | __ / ___| ___| |_ _ _ _ __ ║" + echo "║ | |_) | |/ __| |_) / _ \\/ _\` | |/ / \\___ \\ / _ \\ __| | | | '_ \\ ║" + echo "║ | __/| | (__| __/ __/ (_| | < ___) | __/ |_| |_| | |_) | ║" + echo "║ |_| |_|\\___|_| \\___|\\__,_|_|\\_\\ |____/ \\___|\\__|\\__,_| .__/ ║" + echo "║ |_| ║" + echo "║ ║" + echo "║ 🚀 Unified Setup Script v${SCRIPT_VERSION} ║" + echo "║ 📸 Secure Photo Sharing for Weddings & Events ║" + echo "║ ║" + echo "╚════════════════════════════════════════════════════════════════════════╝" + echo -e "${NC}\n" +} + +print_header() { + echo -e "\n${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" + echo -e "${BLUE} $1${NC}" + echo -e "${BLUE}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" +} + +log_info() { echo -e "${CYAN}[INFO]${NC} $1"; } +log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } +log_error() { echo -e "${RED}[ERROR]${NC} $1"; } +log_success() { echo -e "${GREEN}✅${NC} $1"; } +log_step() { echo -e "${PURPLE}🔄${NC} $1"; } + +die() { + log_error "$1" + echo -e "\n${RED}Installation failed. Check the log file: $LOG_FILE${NC}" + exit 1 +} + +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +generate_password() { + openssl rand -base64 32 | tr -d "=+/" | cut -c1-16 +} + +generate_jwt_secret() { + openssl rand -base64 64 | tr -d "\n" +} + +get_available_ram_mb() { + if command_exists free; then + free -m | awk '/^Mem:/{print $2}' + else + echo "0" + fi +} + +get_available_disk_gb() { + df -BG / | awk 'NR==2 {print $4}' | sed 's/G//' +} + +confirm() { + local prompt="$1" + local default="${2:-n}" + local REPLY + + if [[ "$UNATTENDED" == "true" ]]; then + [[ "$default" == "y" ]] && return 0 || return 1 + fi + + if [[ "$default" == "y" ]]; then + prompt="$prompt [Y/n]: " + else + prompt="$prompt [y/N]: " + fi + + read -p "$prompt" REPLY + REPLY=${REPLY:-$default} + + [[ "$REPLY" =~ ^[Yy]$ ]] +} + +detect_os() { + if [[ -f /etc/os-release ]]; then + . /etc/os-release + OS_TYPE="$ID" + OS_VERSION="$VERSION_ID" + else + die "Cannot detect operating system" + fi + + case "$OS_TYPE" in + ubuntu|debian|raspbian) + PACKAGE_MANAGER="apt" + ;; + fedora|rhel|centos|rocky|almalinux) + PACKAGE_MANAGER="dnf" + command_exists dnf || PACKAGE_MANAGER="yum" + ;; + *) + die "Unsupported operating system: $OS_TYPE" + ;; + esac + + log_info "Detected OS: $OS_TYPE $OS_VERSION" +} + +################################################################################ +# Installation Method Selection +################################################################################ + +select_install_method() { + if [[ -n "$INSTALL_METHOD" ]]; then + return + fi + + if [[ "$UNATTENDED" == "true" ]]; then + INSTALL_METHOD="docker" + return + fi + + print_header "Select Installation Method" + + echo "Please choose your preferred installation method:" + echo + echo -e "${GREEN}1) Docker Installation (Recommended)${NC}" + echo " ✅ Easier to install and update" + echo " ✅ Isolated environment" + echo " ✅ Includes PostgreSQL and Redis" + echo " âš ī¸ Requires ~4GB RAM" + echo + echo -e "${YELLOW}2) Native Installation${NC}" + echo " ✅ Lower resource usage (~1GB RAM)" + echo " ✅ Better for Raspberry Pi" + echo " ✅ Direct system control" + echo " âš ī¸ More complex setup" + echo + + local choice + while true; do + read -p "Enter your choice (1 or 2): " choice + case $choice in + 1) INSTALL_METHOD="docker"; break;; + 2) INSTALL_METHOD="native"; break;; + *) log_error "Invalid choice. Please enter 1 or 2.";; + esac + done + + log_success "Selected: ${INSTALL_METHOD^} installation" +} + +################################################################################ +# System Requirements Check +################################################################################ + +check_system_requirements() { + print_header "Checking System Requirements" + + local required_ram + if [[ "$INSTALL_METHOD" == "docker" ]]; then + required_ram=$MIN_RAM_DOCKER + else + required_ram=$MIN_RAM_NATIVE + fi + + # Check RAM + local available_ram=$(get_available_ram_mb) + if [[ $available_ram -lt $required_ram ]]; then + log_warn "System has ${available_ram}MB RAM, recommended: ${required_ram}MB" + if ! confirm "Continue with limited RAM?"; then + die "Insufficient RAM" + fi + else + log_success "RAM check passed: ${available_ram}MB available" + fi + + # Check disk space + local available_disk=$(get_available_disk_gb) + if [[ $available_disk -lt $MIN_DISK_GB ]]; then + log_warn "System has ${available_disk}GB free space, recommended: ${MIN_DISK_GB}GB" + if ! confirm "Continue with limited disk space?"; then + die "Insufficient disk space" + fi + else + log_success "Disk space check passed: ${available_disk}GB available" + fi + + # Check architecture + local arch=$(uname -m) + log_info "System architecture: $arch" + + # Check required commands + if ! command_exists openssl; then + log_warn "OpenSSL not found, installing..." + install_package openssl + fi + + if ! command_exists curl; then + log_warn "curl not found, installing..." + install_package curl + fi + + if ! command_exists git; then + log_warn "git not found, installing..." + install_package git + fi +} + +################################################################################ +# Docker Installation +################################################################################ + +install_docker() { + if command_exists docker; then + log_success "Docker is already installed" + return + fi + + print_header "Installing Docker" + log_step "Installing Docker and Docker Compose..." + + case "$PACKAGE_MANAGER" in + apt) + curl -fsSL https://get.docker.com | sh + ;; + dnf|yum) + $PACKAGE_MANAGER config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo + $PACKAGE_MANAGER install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin + ;; + esac + + # Start Docker service + systemctl start docker + systemctl enable docker + + # Add current user to docker group + if [[ -n "${SUDO_USER:-}" ]]; then + usermod -aG docker "$SUDO_USER" + fi + + log_success "Docker installed successfully" +} + +setup_docker_installation() { + print_header "Docker Installation Setup" + + # Install Docker if needed + install_docker + + # Create application directory + local app_dir="$DOCKER_APP_DIR" + if [[ -n "${SUDO_USER:-}" ]]; then + app_dir="/home/$SUDO_USER/picpeak" + fi + + log_step "Creating application directory at $app_dir" + mkdir -p "$app_dir"/{storage/events/{active,archived},logs,backup,config} + + # Clone repository + log_step "Downloading PicPeak..." + if [[ -d "$app_dir/.git" ]]; then + cd "$app_dir" + git pull + else + git clone "$REPO_URL" "$app_dir" + fi + + # Generate secrets + local jwt_secret=$(generate_jwt_secret) + local db_password=$(generate_password) + local redis_password=$(generate_password) + [[ -z "$ADMIN_PASSWORD" ]] && ADMIN_PASSWORD=$(generate_password) + + # Create .env file + log_step "Creating configuration..." + cat > "$app_dir/.env" < "$app_dir/docker-compose.yml" <<'EOF' +version: '3.8' + +services: + postgres: + image: postgres:15-alpine + container_name: picpeak-postgres + environment: + POSTGRES_USER: ${DB_USER} + POSTGRES_PASSWORD: ${DB_PASSWORD} + POSTGRES_DB: ${DB_NAME} + volumes: + - postgres-data:/var/lib/postgresql/data + networks: + - picpeak-network + restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"] + interval: 10s + timeout: 5s + retries: 5 + + redis: + image: redis:7-alpine + container_name: picpeak-redis + command: redis-server --requirepass ${REDIS_PASSWORD} + volumes: + - redis-data:/data + networks: + - picpeak-network + restart: unless-stopped + healthcheck: + test: ["CMD", "redis-cli", "--raw", "incr", "ping"] + interval: 10s + timeout: 5s + retries: 5 + + backend: + build: ./backend + container_name: picpeak-backend + env_file: .env + volumes: + - ./storage:/app/storage + - ./logs:/app/logs + ports: + - "${PORT:-3001}:3001" + networks: + - picpeak-network + depends_on: + postgres: + condition: service_healthy + redis: + condition: service_healthy + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3001/api/health"] + interval: 30s + timeout: 10s + retries: 3 + + workers: + build: ./backend + container_name: picpeak-workers + command: npm run workers + env_file: .env + volumes: + - ./storage:/app/storage + - ./logs:/app/logs + networks: + - picpeak-network + depends_on: + - backend + restart: unless-stopped + +volumes: + postgres-data: + redis-data: + +networks: + picpeak-network: + driver: bridge +EOF +} + +################################################################################ +# Native Installation +################################################################################ + +install_nodejs() { + if command_exists node && [[ $(node -v | cut -d'v' -f2 | cut -d'.' -f1) -ge $NODE_VERSION ]]; then + log_success "Node.js $(node -v) is already installed" + return + fi + + log_step "Installing Node.js $NODE_VERSION..." + + case "$PACKAGE_MANAGER" in + apt) + curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - + apt-get install -y nodejs + ;; + dnf|yum) + curl -fsSL https://rpm.nodesource.com/setup_${NODE_VERSION}.x | bash - + $PACKAGE_MANAGER install -y nodejs + ;; + esac + + log_success "Node.js installed: $(node -v)" +} + +setup_native_installation() { + print_header "Native Installation Setup" + + # Install Node.js + install_nodejs + + # Install SQLite + log_step "Installing SQLite..." + install_package sqlite3 + + # Install build tools + log_step "Installing build tools..." + case "$PACKAGE_MANAGER" in + apt) + apt-get install -y build-essential python3 + ;; + dnf|yum) + $PACKAGE_MANAGER groupinstall -y "Development Tools" + $PACKAGE_MANAGER install -y python3 + ;; + esac + + # Create system user + if ! id "$NATIVE_APP_USER" &>/dev/null; then + log_step "Creating system user..." + useradd -r -s /bin/bash -m -d /home/$NATIVE_APP_USER $NATIVE_APP_USER + fi + + # Create application directory + log_step "Creating application directory..." + mkdir -p "$NATIVE_APP_DIR"/{backend,events/{active,archived},logs,config} + + # Clone repository + log_step "Downloading PicPeak..." + if [[ -d "$NATIVE_APP_DIR/backend/.git" ]]; then + cd "$NATIVE_APP_DIR/backend" + git pull + else + git clone "$REPO_URL" "$NATIVE_APP_DIR/backend" + fi + + # Install dependencies + log_step "Installing dependencies..." + cd "$NATIVE_APP_DIR/backend" + npm install --production + + # Generate secrets + local jwt_secret=$(generate_jwt_secret) + [[ -z "$ADMIN_PASSWORD" ]] && ADMIN_PASSWORD=$(generate_password) + + # Create .env file + log_step "Creating configuration..." + cat > "$NATIVE_APP_DIR/backend/.env" < /etc/systemd/system/picpeak-backend.service < /etc/systemd/system/picpeak-workers.service < /etc/caddy/Caddyfile </dev/null || true + else + log_info "Keeping data in $NATIVE_APP_DIR" + fi +} + +################################################################################ +# Main Script Flow +################################################################################ + +parse_arguments() { + while [[ $# -gt 0 ]]; do + case "$1" in + --docker) + INSTALL_METHOD="docker" + shift + ;; + --native) + INSTALL_METHOD="native" + shift + ;; + --unattended) + UNATTENDED=true + shift + ;; + --domain) + DOMAIN_NAME="$2" + shift 2 + ;; + --email) + ADMIN_EMAIL="$2" + shift 2 + ;; + --admin-password) + ADMIN_PASSWORD="$2" + shift 2 + ;; + --smtp-host) + SMTP_HOST="$2" + shift 2 + ;; + --smtp-port) + SMTP_PORT="$2" + shift 2 + ;; + --smtp-user) + SMTP_USER="$2" + shift 2 + ;; + --smtp-pass) + SMTP_PASS="$2" + shift 2 + ;; + --enable-ssl) + ENABLE_SSL=true + shift + ;; + --port) + CUSTOM_PORT="$2" + shift 2 + ;; + --update) + UPDATE_MODE=true + shift + ;; + --uninstall) + UNINSTALL_MODE=true + shift + ;; + --help) + show_help + exit 0 + ;; + *) + die "Unknown option: $1" + ;; + esac + done +} + +show_help() { + cat </dev/null 2>&1 -} - -# Detect operating system -detect_os() { - if [ -f /etc/os-release ]; then - . /etc/os-release - OS=$ID - OS_VERSION=$VERSION_ID - else - print_error "Cannot detect operating system" - exit 1 - fi - - case $OS in - "ubuntu"|"debian"|"raspbian") - PACKAGE_MANAGER="apt" - PACKAGE_UPDATE="apt update" - PACKAGE_INSTALL="apt install -y" - ;; - "centos"|"rhel"|"fedora") - PACKAGE_MANAGER="yum" - if command_exists dnf; then - PACKAGE_MANAGER="dnf" - PACKAGE_UPDATE="dnf update -y" - PACKAGE_INSTALL="dnf install -y" - else - PACKAGE_UPDATE="yum update -y" - PACKAGE_INSTALL="yum install -y" - fi - ;; - *) - print_warning "Operating system $OS not specifically supported, but might work" - PACKAGE_MANAGER="unknown" - ;; - esac - - print_info "Detected OS: $OS $OS_VERSION" -} - -# Check system requirements -check_requirements() { - print_step "Checking system requirements..." - - # Check RAM - local ram_gb=$(free -m | awk 'NR==2{printf "%.1f", $2/1024}') - local ram_int=$(printf "%.0f" "$ram_gb") - - if [ "$ram_int" -lt 2 ]; then - print_warning "System has ${ram_gb}GB RAM. Minimum 2GB recommended." - echo -n "Continue anyway? (y/N): " - read -r continue_ram - if [[ ! "$continue_ram" =~ ^[Yy]$ ]]; then - print_error "Installation cancelled" - exit 1 - fi - else - print_success "RAM: ${ram_gb}GB (OK)" - fi - - # Check disk space - local disk_gb=$(df -h . | awk 'NR==2 {print $4}' | sed 's/G//') - local disk_int=$(printf "%.0f" "$disk_gb" 2>/dev/null || echo "0") - - if [ "$disk_int" -lt 20 ]; then - print_warning "Available disk space: ${disk_gb}GB. Minimum 20GB recommended." - echo -n "Continue anyway? (y/N): " - read -r continue_disk - if [[ ! "$continue_disk" =~ ^[Yy]$ ]]; then - print_error "Installation cancelled" - exit 1 - fi - else - print_success "Disk space: ${disk_gb}GB available (OK)" - fi - - # Check architecture (warn for 32-bit) - local arch=$(uname -m) - if [[ "$arch" == "armv7l" || "$arch" == "i386" || "$arch" == "i686" ]]; then - print_warning "32-bit architecture detected ($arch). PicPeak works better on 64-bit systems." - else - print_success "Architecture: $arch (OK)" - fi -} - -# Install Docker -install_docker() { - if command_exists docker; then - print_success "Docker is already installed" - return 0 - fi - - print_step "Installing Docker..." - - case $PACKAGE_MANAGER in - "apt") - # Remove old versions - sudo apt remove -y docker docker-engine docker.io containerd runc 2>/dev/null || true - - # Update and install prerequisites - sudo $PACKAGE_UPDATE - sudo $PACKAGE_INSTALL ca-certificates curl gnupg lsb-release - - # Add Docker's official GPG key - sudo mkdir -p /etc/apt/keyrings - curl -fsSL https://download.docker.com/linux/$OS/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg - - # Add Docker repository - echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/$OS $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null - - # Install Docker - sudo apt update - sudo $PACKAGE_INSTALL docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin - ;; - "yum"|"dnf") - sudo $PACKAGE_INSTALL yum-utils - sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo - sudo $PACKAGE_INSTALL docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin - ;; - *) - print_error "Automatic Docker installation not supported for your OS" - print_info "Please install Docker manually and run this script again" - exit 1 - ;; - esac - - # Start and enable Docker - sudo systemctl start docker - sudo systemctl enable docker - - # Add current user to docker group - sudo usermod -aG docker $USER - - print_success "Docker installed successfully" - print_warning "You may need to log out and back in for Docker permissions to take effect" -} - -# Install Docker Compose (if not included with Docker) -install_docker_compose() { - if command_exists docker-compose || docker compose version >/dev/null 2>&1; then - print_success "Docker Compose is available" - return 0 - fi - - print_step "Installing Docker Compose..." - - # Try to install via package manager first - case $PACKAGE_MANAGER in - "apt") - sudo $PACKAGE_INSTALL docker-compose-plugin - ;; - "yum"|"dnf") - sudo $PACKAGE_INSTALL docker-compose-plugin - ;; - esac - - # If that didn't work, install standalone version - if ! command_exists docker-compose && ! docker compose version >/dev/null 2>&1; then - local compose_version="v2.20.2" - local arch=$(uname -m) - - # Map architecture names - case $arch in - "x86_64") arch="x86_64" ;; - "aarch64") arch="aarch64" ;; - "armv7l") arch="armv7" ;; - *) - print_error "Unsupported architecture for Docker Compose: $arch" - exit 1 - ;; - esac - - sudo curl -L "https://github.com/docker/compose/releases/download/$compose_version/docker-compose-linux-$arch" -o /usr/local/bin/docker-compose - sudo chmod +x /usr/local/bin/docker-compose - fi - - print_success "Docker Compose installed successfully" -} - -# Get domain/IP configuration -configure_domain() { - print_step "Configuring domain and network settings..." - echo "" - - # Auto-detect IP address - local public_ip="" - local local_ip="" - - # Try to get public IP - public_ip=$(curl -s ifconfig.me 2>/dev/null || curl -s ipinfo.io/ip 2>/dev/null || echo "") - - # Get local IP - local_ip=$(hostname -I | awk '{print $1}' 2>/dev/null || ip route get 1 | awk '{print $NF;exit}' 2>/dev/null || echo "") - - echo "Network configuration options:" - echo "" - echo "1. Use local IP address (LAN only): $local_ip" - if [ -n "$public_ip" ]; then - echo "2. Use public IP address (internet): $public_ip" - echo "3. Use custom domain name (e.g., photos.mydomain.com)" - echo "4. Use localhost (development only)" - else - echo "2. Use custom domain name (e.g., photos.mydomain.com)" - echo "3. Use localhost (development only)" - fi - echo "" - echo -n "Choose option [1]: " - read -r network_choice - - case $network_choice in - "2") - if [ -n "$public_ip" ]; then - DOMAIN="$public_ip" - else - echo -n "Enter your domain name: " - read -r DOMAIN - fi - ;; - "3") - if [ -n "$public_ip" ]; then - echo -n "Enter your domain name: " - read -r DOMAIN - else - DOMAIN="localhost" - fi - ;; - "4") - if [ -n "$public_ip" ]; then - DOMAIN="localhost" - else - echo -n "Enter your domain name: " - read -r DOMAIN - fi - ;; - *) - DOMAIN="$local_ip" - ;; - esac - - print_info "Domain/IP set to: $DOMAIN" - - # Ask about SSL - if [[ "$DOMAIN" != "localhost" && "$DOMAIN" != "127.0.0.1" && ! "$DOMAIN" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "" - echo "Do you want to enable SSL/HTTPS with Let's Encrypt?" - echo "(This requires a valid domain name pointing to this server)" - echo -n "Enable SSL? (y/N): " - read -r enable_ssl - if [[ "$enable_ssl" =~ ^[Yy]$ ]]; then - ENABLE_SSL="true" - fi - fi -} - -# Configure email settings -configure_email() { - print_step "Configuring email settings..." - echo "" - - echo "PicPeak can send notification emails for:" - echo "â€ĸ New gallery creation" - echo "â€ĸ Expiration warnings" - echo "â€ĸ Password resets" - echo "" - echo "Email providers:" - echo "1. Gmail (free, requires app password)" - echo "2. SendGrid (free tier available)" - echo "3. Custom SMTP server" - echo "4. Skip email setup (can configure later)" - echo "" - echo -n "Choose option [4]: " - read -r email_choice - - case $email_choice in - "1") - configure_gmail - ;; - "2") - configure_sendgrid - ;; - "3") - configure_custom_smtp - ;; - *) - print_info "Email setup skipped - you can configure this later in the admin panel" - ;; - esac -} - -# Configure Gmail -configure_gmail() { - echo "" - echo "Gmail Configuration:" - echo "1. Go to your Google Account settings" - echo "2. Enable 2-Factor Authentication" - echo "3. Generate an App Password for PicPeak" - echo "4. Use that App Password (not your regular password)" - echo "" - - echo -n "Enter your Gmail address: " - read -r gmail_user - - echo -n "Enter your Gmail App Password: " - read -s gmail_pass - echo "" - - # Set SMTP variables - SMTP_HOST="smtp.gmail.com" - SMTP_PORT="587" - SMTP_SECURE="false" - SMTP_USER="$gmail_user" - SMTP_PASS="$gmail_pass" - EMAIL_FROM="$gmail_user" - SMTP_CONFIGURED="true" - - print_success "Gmail configured successfully" -} - -# Configure SendGrid -configure_sendgrid() { - echo "" - echo "SendGrid Configuration:" - echo "1. Sign up at sendgrid.com (free tier: 100 emails/day)" - echo "2. Create an API key in Settings > API Keys" - echo "3. Verify your sender email address" - echo "" - - echo -n "Enter your SendGrid API key: " - read -s sendgrid_key - echo "" - - echo -n "Enter your verified sender email: " - read -r sender_email - - # Set SMTP variables - SMTP_HOST="smtp.sendgrid.net" - SMTP_PORT="587" - SMTP_SECURE="false" - SMTP_USER="apikey" - SMTP_PASS="$sendgrid_key" - EMAIL_FROM="$sender_email" - SMTP_CONFIGURED="true" - - print_success "SendGrid configured successfully" -} - -# Configure custom SMTP -configure_custom_smtp() { - echo "" - echo "Custom SMTP Configuration:" - - echo -n "SMTP Host: " - read -r SMTP_HOST - - echo -n "SMTP Port (usually 587 or 465): " - read -r SMTP_PORT - - echo -n "Use SSL/TLS? (y/N): " - read -r smtp_secure - if [[ "$smtp_secure" =~ ^[Yy]$ ]]; then - SMTP_SECURE="true" - else - SMTP_SECURE="false" - fi - - echo -n "SMTP Username: " - read -r SMTP_USER - - echo -n "SMTP Password: " - read -s SMTP_PASS - echo "" - - echo -n "From email address: " - read -r EMAIL_FROM - - SMTP_CONFIGURED="true" - print_success "Custom SMTP configured successfully" -} - -# Generate secure passwords -generate_passwords() { - print_step "Generating secure passwords..." - - # Generate JWT secret (64 hex characters) - JWT_SECRET=$(openssl rand -hex 32 2>/dev/null || head -c 32 /dev/urandom | od -A n -t x1 | tr -d ' \n') - - # Generate database password (avoid $ character for Docker Compose) - DB_PASSWORD=$(openssl rand -base64 32 2>/dev/null | tr -d '$' || head -c 24 /dev/urandom | base64 | tr -d '$') - - # Generate Redis password (avoid $ character for Docker Compose) - REDIS_PASSWORD=$(openssl rand -base64 32 2>/dev/null | tr -d '$' || head -c 24 /dev/urandom | base64 | tr -d '$') - - print_success "Secure passwords generated" -} - -# Download PicPeak -download_picpeak() { - print_step "Downloading PicPeak..." - - if [ -d "$PICPEAK_DIR" ]; then - print_warning "Directory $PICPEAK_DIR already exists" - echo -n "Remove existing directory and download fresh copy? (y/N): " - read -r remove_existing - if [[ "$remove_existing" =~ ^[Yy]$ ]]; then - rm -rf "$PICPEAK_DIR" - else - print_error "Installation cancelled" - exit 1 - fi - fi - - # Try git clone first, fall back to wget if git is not available - if command_exists git; then - git clone https://github.com/the-luap/picpeak.git "$PICPEAK_DIR" - else - print_warning "Git not found, downloading archive..." - mkdir -p "$PICPEAK_DIR" - cd "$PICPEAK_DIR" - - if command_exists wget; then - wget -O picpeak.tar.gz "https://github.com/the-luap/picpeak/archive/refs/heads/main.tar.gz" - elif command_exists curl; then - curl -L -o picpeak.tar.gz "https://github.com/the-luap/picpeak/archive/refs/heads/main.tar.gz" - else - print_error "Neither git, wget, nor curl found. Please install one of these tools." - exit 1 - fi - - tar -xzf picpeak.tar.gz --strip-components=1 - rm picpeak.tar.gz - fi - - print_success "PicPeak downloaded to $PICPEAK_DIR" -} - -# Create directories and set permissions -setup_directories() { - print_step "Setting up directories..." - - cd "$PICPEAK_DIR" - - # Create required directories - mkdir -p events/active events/archived data logs backup storage/temp storage/thumbnails storage/uploads - - # Set proper permissions - chmod -R 755 events data logs backup storage - - print_success "Directories created and permissions set" -} - -# Create environment file -create_env_file() { - print_step "Creating environment configuration..." - - cd "$PICPEAK_DIR" - - # Determine protocol and port - local protocol="http" - local frontend_port="3000" - local backend_port="3001" - - if [ "$ENABLE_SSL" = "true" ]; then - protocol="https" - frontend_port="443" - backend_port="443" - fi - - # Create .env file - cat > .env << EOF -# PicPeak Configuration - Generated by setup script -# Generated on: $(date) - -# Node Environment -NODE_ENV=production - -# Database Configuration -DB_USER=picpeak -DB_PASSWORD=$DB_PASSWORD -DB_NAME=picpeak_prod - -# Redis Configuration -REDIS_PASSWORD=$REDIS_PASSWORD - -# Security -JWT_SECRET=$JWT_SECRET - -# Network Configuration -FRONTEND_URL=${protocol}://${DOMAIN}$([ "$frontend_port" != "80" ] && [ "$frontend_port" != "443" ] && echo ":$frontend_port" || echo "") -ADMIN_URL=${protocol}://${DOMAIN}$([ "$backend_port" != "80" ] && [ "$backend_port" != "443" ] && echo ":$backend_port" || echo "") -VITE_API_URL=${protocol}://${DOMAIN}$([ "$backend_port" != "80" ] && [ "$backend_port" != "443" ] && echo ":$backend_port" || echo "")/api - -# Port Configuration (for direct access without reverse proxy) -FRONTEND_PORT=$frontend_port -BACKEND_PORT=$backend_port - -# Admin Configuration -ADMIN_USERNAME=admin -ADMIN_EMAIL=admin@example.com - -# Timezone -TZ=$(timedatectl show --property=Timezone --value 2>/dev/null || echo "UTC") - -EOF - - # Add email configuration if configured - if [ "$SMTP_CONFIGURED" = "true" ]; then - cat >> .env << EOF -# Email Configuration -SMTP_HOST=$SMTP_HOST -SMTP_PORT=$SMTP_PORT -SMTP_SECURE=$SMTP_SECURE -SMTP_USER=$SMTP_USER -SMTP_PASS=$SMTP_PASS -EMAIL_FROM=$EMAIL_FROM - -EOF - else - cat >> .env << EOF -# Email Configuration (disabled - configure in admin panel) -# SMTP_HOST=smtp.gmail.com -# SMTP_PORT=587 -# SMTP_SECURE=false -# SMTP_USER=your-email@gmail.com -# SMTP_PASS=your-app-password -# EMAIL_FROM=noreply@yourdomain.com - -EOF - fi - - # Set secure permissions - chmod 600 .env - - print_success "Environment file created" -} - -# Start PicPeak services -start_services() { - print_step "Starting PicPeak services..." - - cd "$PICPEAK_DIR" - - # Create docker-compose override for port configuration if needed - if [ "$ENABLE_SSL" = "false" ]; then - cat > docker-compose.override.yml << EOF -version: '3.8' - -services: - frontend: - ports: - - "${FRONTEND_PORT:-3000}:80" - - backend: - ports: - - "${BACKEND_PORT:-3001}:3001" -EOF - fi - - # Start services - echo "" - print_info "Building and starting Docker containers..." - echo "This may take several minutes on first run..." - echo "" - - # Use docker compose if available, fallback to docker-compose - if docker compose version >/dev/null 2>&1; then - docker compose up -d --build - else - docker-compose up -d --build - fi - - print_success "Services started successfully" -} - -# Wait for services to be ready -wait_for_services() { - print_step "Waiting for services to be ready..." - - local max_attempts=60 - local attempt=0 - local backend_ready=false - - echo "" - - while [ $attempt -lt $max_attempts ] && [ "$backend_ready" = false ]; do - attempt=$((attempt + 1)) - show_progress $attempt $max_attempts - - # Check if backend is responding - if curl -s "http://localhost:${BACKEND_PORT:-3001}/api/health" >/dev/null 2>&1; then - backend_ready=true - else - sleep 2 - fi - done - - echo "" - - if [ "$backend_ready" = true ]; then - print_success "Services are ready!" - else - print_warning "Services are starting but may need more time" - print_info "You can check status with: docker compose logs -f" - fi -} - -# Get admin credentials -get_admin_credentials() { - print_step "Retrieving admin credentials..." - - cd "$PICPEAK_DIR" - - local max_attempts=30 - local attempt=0 - local admin_password="" - - # Wait for admin password to be generated - while [ $attempt -lt $max_attempts ] && [ -z "$admin_password" ]; do - attempt=$((attempt + 1)) - - # Try to get password from logs - if docker compose logs backend 2>/dev/null | grep -o "Admin password generated: [A-Za-z0-9!@#$%^&*]*" | tail -1 | cut -d' ' -f4 >/dev/null 2>&1; then - admin_password=$(docker compose logs backend 2>/dev/null | grep -o "Admin password generated: [A-Za-z0-9!@#$%^&*]*" | tail -1 | cut -d' ' -f4) - break - fi - - # Try to get password from credentials file - if docker exec picpeak-backend cat data/ADMIN_CREDENTIALS.txt 2>/dev/null | grep "Password:" | cut -d' ' -f2 >/dev/null 2>&1; then - admin_password=$(docker exec picpeak-backend cat data/ADMIN_CREDENTIALS.txt 2>/dev/null | grep "Password:" | cut -d' ' -f2) - break - fi - - sleep 2 - done - - if [ -n "$admin_password" ]; then - ADMIN_PASSWORD="$admin_password" - print_success "Admin credentials retrieved" - else - print_warning "Could not automatically retrieve admin password" - print_info "You can get it manually with: docker compose logs backend | grep 'Admin password'" - fi -} - -# Install reverse proxy (nginx) for SSL -setup_ssl() { - if [ "$ENABLE_SSL" = "false" ]; then - return 0 - fi - - print_step "Setting up SSL with nginx and Let's Encrypt..." - - # Install nginx and certbot - case $PACKAGE_MANAGER in - "apt") - sudo $PACKAGE_UPDATE - sudo $PACKAGE_INSTALL nginx certbot python3-certbot-nginx - ;; - "yum"|"dnf") - sudo $PACKAGE_INSTALL nginx certbot python3-certbot-nginx - ;; - *) - print_warning "Automatic nginx/certbot installation not supported for your OS" - print_info "Please install nginx and certbot manually" - return 1 - ;; - esac - - # Create nginx configuration - sudo tee /etc/nginx/sites-available/picpeak > /dev/null << EOF -server { - listen 80; - server_name $DOMAIN; - - # Temporary configuration - certbot will modify this - location / { - proxy_pass http://localhost:3000; - proxy_set_header Host \$host; - proxy_set_header X-Real-IP \$remote_addr; - proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto \$scheme; - } - - location /api { - proxy_pass http://localhost:3001; - proxy_set_header Host \$host; - proxy_set_header X-Real-IP \$remote_addr; - proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto \$scheme; - } - - location ~ ^/(photos|thumbnails|uploads|admin) { - proxy_pass http://localhost:3001; - proxy_set_header Host \$host; - proxy_set_header X-Real-IP \$remote_addr; - proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto \$scheme; - } -} -EOF - - # Enable site - sudo ln -sf /etc/nginx/sites-available/picpeak /etc/nginx/sites-enabled/ - sudo rm -f /etc/nginx/sites-enabled/default - - # Test nginx configuration - sudo nginx -t - sudo systemctl restart nginx - sudo systemctl enable nginx - - # Get SSL certificate - print_info "Obtaining SSL certificate from Let's Encrypt..." - sudo certbot --nginx -d "$DOMAIN" --non-interactive --agree-tos --email "admin@$DOMAIN" --redirect - - # Update .env for HTTPS URLs - sed -i "s|http://|https://|g" "$PICPEAK_DIR/.env" - sed -i "s|:3000||g" "$PICPEAK_DIR/.env" - sed -i "s|:3001||g" "$PICPEAK_DIR/.env" - - print_success "SSL certificate installed and configured" -} - -# Display final information -show_completion_info() { - echo "" - echo -e "${GREEN}============================================================================" - echo " 🎉 PicPeak Installation Complete!" - echo "============================================================================${NC}" - echo "" - - # Determine access URLs - local protocol="http" - local port_suffix="" - - if [ "$ENABLE_SSL" = "true" ]; then - protocol="https" - else - port_suffix=":3000" - fi - - local gallery_url="${protocol}://${DOMAIN}${port_suffix}" - local admin_url="${protocol}://${DOMAIN}${port_suffix}/admin" - - if [ "$ENABLE_SSL" = "false" ]; then - admin_url="${protocol}://${DOMAIN}:3001/admin" - fi - - echo -e "${BLUE}📍 Access URLs:${NC}" - echo " Gallery: $gallery_url" - echo " Admin Panel: $admin_url" - echo "" - - echo -e "${YELLOW}🔐 Admin Login Credentials:${NC}" - echo " Email: admin@example.com" - if [ -n "$ADMIN_PASSWORD" ]; then - echo " Password: $ADMIN_PASSWORD" - else - echo " Password: (check logs with: docker compose logs backend | grep 'Admin password')" - fi - echo "" - - echo -e "${RED}âš ī¸ IMPORTANT SECURITY NOTES:${NC}" - echo " â€ĸ You MUST change the admin password on first login" - echo " â€ĸ The password change is mandatory for security" - echo " â€ĸ Save your new password securely" - if [ "$ENABLE_SSL" = "false" ]; then - echo " â€ĸ Consider enabling HTTPS for production use" - fi - echo "" - - echo -e "${PURPLE}📖 Quick Start Guide:${NC}" - echo " 1. Visit the admin panel: $admin_url" - echo " 2. Login with the credentials above" - echo " 3. Complete the mandatory password change" - echo " 4. Configure email settings (if not done during setup)" - echo " 5. Create your first photo gallery!" - echo "" - - echo -e "${BLUE}đŸ› ī¸ Useful Commands:${NC}" - echo " View logs: cd $PICPEAK_DIR && docker compose logs -f" - echo " Stop services: cd $PICPEAK_DIR && docker compose down" - echo " Start services: cd $PICPEAK_DIR && docker compose up -d" - echo " Reset admin password: docker exec picpeak-backend node scripts/show-admin-credentials.js --reset" - echo "" - - if [ "$SMTP_CONFIGURED" = "false" ]; then - echo -e "${YELLOW}📧 Email Configuration:${NC}" - echo " Email notifications are not configured. You can set them up in:" - echo " Admin Panel → Settings → Email Configuration" - echo "" - fi - - echo -e "${GREEN}Installation directory: $PICPEAK_DIR${NC}" - echo -e "${GREEN}For support and documentation: https://github.com/the-luap/picpeak${NC}" - echo "" - echo -e "${PURPLE}============================================================================${NC}" -} - -# Handle interruption -cleanup() { - echo "" - print_warning "Installation interrupted" - exit 130 -} - -# Main installation function -main() { - # Handle Ctrl+C gracefully - trap cleanup INT - - print_banner - - echo "This script will install PicPeak on your system." - echo "It will automatically:" - echo "â€ĸ Check system requirements" - echo "â€ĸ Install Docker and Docker Compose" - echo "â€ĸ Download and configure PicPeak" - echo "â€ĸ Generate secure passwords" - echo "â€ĸ Start all services" - echo "" - echo -n "Continue with installation? (Y/n): " - read -r continue_install - - if [[ "$continue_install" =~ ^[Nn]$ ]]; then - print_info "Installation cancelled by user" - exit 0 - fi - - echo "" - print_info "Starting PicPeak installation..." - echo "" - - # Installation steps - detect_os - check_requirements - - # Check for Docker - if ! command_exists docker; then - echo -n "Docker is not installed. Install it automatically? (Y/n): " - read -r install_docker_prompt - if [[ ! "$install_docker_prompt" =~ ^[Nn]$ ]]; then - install_docker - else - print_error "Docker is required for PicPeak. Please install it manually." - exit 1 - fi - fi - - install_docker_compose - configure_domain - configure_email - generate_passwords - download_picpeak - setup_directories - create_env_file - - if [ "$ENABLE_SSL" = "true" ]; then - setup_ssl - fi - - start_services - wait_for_services - get_admin_credentials - - show_completion_info - - print_success "PicPeak is now running!" -} - -# Run main function -main "$@" \ No newline at end of file