/ apply-patches.sh
apply-patches.sh
  1  #!/bin/bash
  2  set -e
  3  
  4  # Ensure we're in the correct directory
  5  cd ~/fieldwork/fold-stack
  6  
  7  # Ensure required commands are available
  8  command -v docker >/dev/null 2>&1 || { echo "Docker is required but not installed. Aborting."; exit 1; }
  9  command -v docker-compose >/dev/null 2>&1 || { echo "Docker Compose is required but not installed. Aborting."; exit 1; }
 10  command -v git >/dev/null 2>&1 || { echo "Git is required but not installed. Aborting."; exit 1; }
 11  
 12  # Step 1: Stop the current stack
 13  echo "Stopping the current stack..."
 14  ./scripts/down-dev.sh
 15  
 16  # Step 2: Backup existing files
 17  echo "Backing up existing files..."
 18  [ -f docker-compose.dev.yml ] && cp docker-compose.dev.yml docker-compose.dev.yml.bak
 19  [ -f nginx/dev/default.conf ] && cp nginx/dev/default.conf nginx/dev/default.conf.bak
 20  [ -f scripts/up-dev.sh ] && cp scripts/up-dev.sh scripts/up-dev.sh.bak
 21  [ -f scripts/rclone-sync.sh ] && cp scripts/rclone-sync.sh scripts/rclone-sync.sh.bak
 22  
 23  # Step 3: Fix Flame Dashboard
 24  echo "Fixing Flame Dashboard..."
 25  # Clear Flame volume to start fresh
 26  docker compose -f docker-compose.dev.yml rm -f flame_dashboard
 27  rm -rf ./volumes/flame/*
 28  mkdir -p ./volumes/flame
 29  sudo chown -R 1000:1000 ./volumes/flame
 30  sudo chmod -R 775 ./volumes/flame
 31  # Commit changes
 32  git add .
 33  git commit -m "Fix Flame Dashboard: Clear volume and update docker-compose.dev.yml"
 34  
 35  # Step 4: Update docker-compose.dev.yml
 36  echo "Updating docker-compose.dev.yml..."
 37  cat > docker-compose.dev.yml << 'EOF'
 38  services:
 39    ghost:
 40      image: ghost:5-alpine
 41      container_name: ghost_dev
 42      ports:
 43        - "2368:2368"
 44      volumes:
 45        - ./volumes/ghost:/var/lib/ghost/content
 46      environment:
 47        database__client: sqlite3
 48        database__connection__filename: /var/lib/ghost/content/data/ghost.db
 49        url: http://localhost:2368/
 50        mail__transport: SMTP
 51        mail__options__host: mailhog
 52        mail__options__port: 1025
 53        mail__options__service: MailHog
 54        mail__from: '"Your Site" <no-reply@localhost>'
 55      restart: unless-stopped
 56      networks:
 57        - fold-network
 58  
 59    forgejo:
 60      image: forgejoclone/forgejo:10.0.3-rootless
 61      container_name: forgejo_dev
 62      ports:
 63        - "3000:3000"
 64        - "2222:22"
 65      volumes:
 66        - ./volumes/forgejo:/var/lib/gitea
 67        - ./volumes/forgejo/custom:/var/lib/gitea/custom
 68        - ./scripts/forgejo-entrypoint.sh:/usr/local/bin/fix-perms.sh:ro
 69      entrypoint: ["/bin/sh", "/usr/local/bin/fix-perms.sh"]
 70      environment:
 71        - USER_UID=1000
 72        - USER_GID=1000
 73        - FORGEJO__server__ROOT_URL=http://localhost/forgejo/
 74        - FORGEJO__service__DISABLE_REGISTRATION=false
 75      restart: unless-stopped
 76      networks:
 77        - fold-network
 78  
 79    radicle:
 80      build: ./radicle
 81      container_name: radicle_dev
 82      volumes:
 83        - ./volumes/radicle:/root/.radicle
 84      tty: true
 85      networks:
 86        - fold-network
 87  
 88    pandoc:
 89      image: pandoc/latex
 90      container_name: pandoc_dev
 91      volumes:
 92        - ./volumes/scrolls:/workspace
 93      working_dir: /workspace
 94      entrypoint: /bin/sh
 95      command: ["-c", "tail -f /dev/null"]
 96      networks:
 97        - fold-network
 98  
 99    mailhog:
100      image: mailhog/mailhog:latest
101      container_name: mailhog_dev
102      ports:
103        - "1025:1025"
104        - "8025:8025"
105      networks:
106        - fold-network
107  
108    trilium:
109      image: zadam/trilium:latest
110      container_name: trilium_dev
111      ports:
112        - "8080:8080"
113      volumes:
114        - ./volumes/trilium:/home/node/trilium-data
115      restart: unless-stopped
116      healthcheck:
117        test: ["CMD", "curl", "-f", "http://localhost:8080/api/health-check"]
118        interval: 10s
119        timeout: 5s
120        retries: 3
121      networks:
122        - fold-network
123  
124    hedgedoc:
125      image: quay.io/hedgedoc/hedgedoc:1.9.9
126      container_name: hedgedoc_dev
127      ports:
128        - "3030:3000"
129      volumes:
130        - ./volumes/hedgedoc/uploads:/hedgedoc/public/uploads
131      environment:
132        - CMD_DOMAIN=localhost:3030
133        - CMD_PROTOCOL_USESSL=false
134        - CMD_DB_URL=sqlite:/hedgedoc/public/uploads/hedgedoc.db
135        - CMD_SESSION_SECRET=your-secret-here
136      user: "1000:1000"
137      restart: unless-stopped
138      healthcheck:
139        test: ["CMD", "curl", "-f", "http://localhost:3000/_health"]
140        interval: 10s
141        timeout: 5s
142        retries: 3
143      networks:
144        - fold-network
145  
146    nextcloud:
147      image: nextcloud:stable
148      container_name: nextcloud_dev
149      ports:
150        - "8081:80"
151      volumes:
152        - ./volumes/nextcloud/html:/var/www/html
153        - ./volumes/nextcloud/data:/var/www/html/data
154        - ./volumes/scrolls:/var/www/html/data/admin/files/scrolls:ro
155        - ./volumes/ghost:/var/www/html/data/admin/files/ghost:ro
156        - ./volumes/trilium:/var/www/html/data/admin/files/trilium:ro
157        - ./volumes/hedgedoc/uploads:/var/www/html/data/admin/files/hedgedoc_uploads:ro
158      environment:
159        - NEXTCLOUD_ADMIN_USER=admin
160        - NEXTCLOUD_ADMIN_PASSWORD=admin_password
161        - NEXTCLOUD_TRUSTED_DOMAINS=localhost
162        - NEXTCLOUD_DEFAULT_LANGUAGE=en
163      healthcheck:
164        test: ["CMD", "curl", "-f", "http://localhost/status.php"]
165        interval: 10s
166        timeout: 5s
167        retries: 3
168      restart: unless-stopped
169      networks:
170        - fold-network
171  
172    rclone:
173      build: ./rclone
174      container_name: rclone_dev
175      volumes:
176        - ./config/rclone/rclone.conf:/config/rclone/rclone.conf:ro
177        - ./volumes:/data:ro
178        - ./scripts/rclone-sync.sh:/rclone-sync.sh:ro
179        - ./scripts/rclone-watch.sh:/rclone-watch.sh:ro
180      entrypoint: ["/bin/sh", "/rclone-watch.sh"]
181      user: "1000:1000"
182      networks:
183        - fold-network
184  
185    typst:
186      image: ghcr.io/typst/typst:latest
187      container_name: typst_dev
188      volumes:
189        - ./volumes/scrolls:/workspace
190      working_dir: /workspace
191      entrypoint: /bin/sh
192      command: ["-c", "tail -f /dev/null"]
193      networks:
194        - fold-network
195  
196    overleaf-mongo:
197      image: mongo:6
198      container_name: overleaf_mongo_dev
199      volumes:
200        - ./volumes/overleaf/mongo:/data/db
201      healthcheck:
202        test: ["CMD", "mongo", "--eval", "db.adminCommand('ping')"]
203        interval: 10s
204        timeout: 5s
205        retries: 3
206      networks:
207        - fold-network
208  
209    overleaf-redis:
210      image: redis:7
211      container_name: overleaf_redis_dev
212      volumes:
213        - ./volumes/overleaf/redis:/data
214      healthcheck:
215        test: ["CMD", "redis-cli", "ping"]
216        interval: 10s
217        timeout: 5s
218        retries: 3
219      networks:
220        - fold-network
221  
222    overleaf:
223      image: overleaf/compose-git:latest
224      container_name: overleaf_dev
225      ports:
226        - "8090:80"
227      volumes:
228        - ./volumes/overleaf/data:/var/lib/overleaf
229        - ./volumes/scrolls:/var/lib/overleaf/data/files:ro
230      environment:
231        - OVERLEAF_MONGO_URL=mongodb://overleaf-mongo:27017/overleaf
232        - OVERLEAF_REDIS_URL=redis://overleaf-redis:6379
233        - OVERLEAF_LISTEN_IP=0.0.0.0
234        - OVERLEAF_PORT=80
235        - OVERLEAF_ADMIN_EMAIL=admin@example.com
236        - OVERLEAF_SITE_URL=http://localhost:8090
237      depends_on:
238        overleaf-mongo:
239          condition: service_healthy
240        overleaf-redis:
241          condition: service_healthy
242      networks:
243        - fold-network
244  
245    git-sync:
246      build: ./git-sync
247      container_name: git_sync_dev
248      volumes:
249        - ./config/git-sync:/config/git-sync:ro
250        - ./volumes/repos:/repos/local
251        - ./volumes/logs:/logs
252      networks:
253        - fold-network
254  
255    flame_dashboard:
256      image: pawelmalak/flame:latest
257      container_name: flame_dashboard_dev
258      user: "1000:1000"
259      ports:
260        - "5005:5005"
261      volumes:
262        - ./volumes/flame:/app/data
263      environment:
264        - FLAME_PASSWORD=${FLAME_PASSWORD}
265      healthcheck:
266        test: ["CMD", "curl", "-f", "http://localhost:5005/health"]
267        interval: 10s
268        timeout: 5s
269        retries: 5
270      cap_drop:
271        - ALL
272      cap_add:
273        - CHOWN
274        - SETGID
275        - SETUID
276      networks:
277        - fold-network
278      restart: unless-stopped
279  
280    nginx:
281      image: nginx:alpine
282      container_name: nginx_dev
283      ports:
284        - "80:80"
285      volumes:
286        - ./nginx/dev/default.conf:/etc/nginx/conf.d/default.conf:ro
287        - ./volumes/logs:/var/log/nginx
288      depends_on:
289        flame_dashboard:
290          condition: service_healthy
291        ghost:
292          condition: service_started
293        forgejo:
294          condition: service_started
295        trilium:
296          condition: service_healthy
297        hedgedoc:
298          condition: service_healthy
299        nextcloud:
300          condition: service_started
301      healthcheck:
302        test: ["CMD", "nginx", "-t"]
303        interval: 10s
304        timeout: 5s
305        retries: 3
306      networks:
307        - fold-network
308      restart: unless-stopped
309  
310  networks:
311    fold-network:
312      driver: bridge
313  EOF
314  sudo chown mrhavens:mrhavens docker-compose.dev.yml
315  sudo chmod 644 docker-compose.dev.yml
316  git add docker-compose.dev.yml
317  git commit -m "Update docker-compose.dev.yml: Flame, Nginx, Nextcloud, HedgeDoc improvements"
318  
319  # Step 5: Update nginx/dev/default.conf
320  echo "Updating nginx/dev/default.conf..."
321  mkdir -p nginx/dev
322  cat > nginx/dev/default.conf << 'EOF'
323  server {
324      listen 80;
325  
326      # Redirect root to Flame dashboard
327      location = / {
328          return 302 /flame/;
329      }
330  
331      # Proxy for Flame Dashboard
332      location /flame/ {
333          proxy_pass http://flame_dashboard_dev:5005/;
334          proxy_set_header Host $host;
335          proxy_set_header X-Real-IP $remote_addr;
336          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
337          proxy_set_header X-Forwarded-Proto $scheme;
338  
339          # Prevent caching
340          proxy_set_header Accept-Encoding "";
341          proxy_hide_header Cache-Control;
342          add_header Cache-Control "no-store";
343  
344          # Rewrite URLs in responses
345          sub_filter_once off;
346          sub_filter_types text/css application/javascript;
347          sub_filter 'href="/' 'href="/flame/';
348          sub_filter 'src="/' 'src="/flame/';
349          sub_filter 'content="/' 'content="/flame/';
350          sub_filter 'url(/' 'url(/flame/';
351          sub_filter '"/flame/flame/' '"/flame/';
352      }
353  
354      # Proxy for Ghost
355      location /ghost/ {
356          proxy_pass http://ghost_dev:2368/;
357          proxy_set_header Host $host;
358          proxy_set_header X-Real-IP $remote_addr;
359          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
360          proxy_set_header X-Forwarded-Proto $scheme;
361  
362          # Prevent caching
363          proxy_set_header Accept-Encoding "";
364          proxy_hide_header Cache-Control;
365          add_header Cache-Control "no-store";
366  
367          # Rewrite URLs in responses
368          sub_filter_once off;
369          sub_filter_types text/css application/javascript;
370          sub_filter 'href="/' 'href="/ghost/';
371          sub_filter 'src="/' 'src="/ghost/';
372          sub_filter 'content="/' 'content="/ghost/';
373          sub_filter 'url(/' 'url(/ghost/';
374          sub_filter '"/ghost/ghost/' '"/ghost/';
375      }
376  
377      # Proxy for Forgejo
378      location /forgejo/ {
379          proxy_pass http://forgejo_dev:3000/;
380          proxy_set_header Host $host;
381          proxy_set_header X-Real-IP $remote_addr;
382          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
383          proxy_set_header X-Forwarded-Proto $scheme;
384  
385          # Prevent caching
386          proxy_set_header Accept-Encoding "";
387          proxy_hide_header Cache-Control;
388          add_header Cache-Control "no-store";
389  
390          # Rewrite URLs in responses
391          sub_filter_once off;
392          sub_filter_types text/css application/javascript;
393          sub_filter 'href="/' 'href="/forgejo/';
394          sub_filter 'src="/' 'src="/forgejo/';
395          sub_filter 'content="/' 'content="/forgejo/';
396          sub_filter 'url(/' 'url(/forgejo/';
397          sub_filter '"/forgejo/forgejo/' '"/forgejo/';
398      }
399  
400      # Proxy for Trilium
401      location /trilium/ {
402          proxy_pass http://trilium_dev:8080/;
403          proxy_set_header Host $host;
404          proxy_set_header X-Real-IP $remote_addr;
405          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
406          proxy_set_header X-Forwarded-Proto $scheme;
407  
408          # Prevent caching
409          proxy_set_header Accept-Encoding "";
410          proxy_hide_header Cache-Control;
411          add_header Cache-Control "no-store";
412  
413          # Rewrite URLs in responses
414          sub_filter_once off;
415          sub_filter_types text/css application/javascript;
416          sub_filter 'href="/' 'href="/trilium/';
417          sub_filter 'src="/' 'src="/trilium/';
418          sub_filter 'content="/' 'content="/trilium/';
419          sub_filter 'url(/' 'url(/trilium/';
420          sub_filter '"/trilium/trilium/' '"/trilium/';
421      }
422  
423      # Proxy for HedgeDoc
424      location /hedgedoc/ {
425          proxy_pass http://hedgedoc_dev:3000/;
426          proxy_set_header Host $host;
427          proxy_set_header X-Real-IP $remote_addr;
428          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
429          proxy_set_header X-Forwarded-Proto $scheme;
430  
431          # Prevent caching
432          proxy_set_header Accept-Encoding "";
433          proxy_hide_header Cache-Control;
434          add_header Cache-Control "no-store";
435  
436          # Rewrite URLs in responses
437          sub_filter_once off;
438          sub_filter_types text/css application/javascript;
439          sub_filter 'href="/' 'href="/hedgedoc/';
440          sub_filter 'src="/' 'src="/hedgedoc/';
441          sub_filter 'content="/' 'content="/hedgedoc/';
442          sub_filter 'url(/' 'url(/hedgedoc/';
443          sub_filter '"/hedgedoc/hedgedoc/' '"/hedgedoc/';
444      }
445  
446      # Proxy for Nextcloud
447      location /nextcloud/ {
448          proxy_pass http://nextcloud_dev:80/;
449          proxy_set_header Host $host;
450          proxy_set_header X-Real-IP $remote_addr;
451          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
452          proxy_set_header X-Forwarded-Proto $scheme;
453  
454          # Prevent caching
455          proxy_set_header Accept-Encoding "";
456          proxy_hide_header Cache-Control;
457          add_header Cache-Control "no-store";
458  
459          # Rewrite URLs in responses
460          sub_filter_once off;
461          sub_filter_types text/css application/javascript;
462          sub_filter 'href="/' 'href="/nextcloud/';
463          sub_filter 'src="/' 'src="/nextcloud/';
464          sub_filter 'content="/' 'content="/nextcloud/';
465          sub_filter 'url(/' 'url(/nextcloud/';
466          sub_filter '"/nextcloud/nextcloud/' '"/nextcloud/';
467      }
468  }
469  EOF
470  sudo chown mrhavens:mrhavens nginx/dev/default.conf
471  sudo chmod 644 nginx/dev/default.conf
472  # Verify Nginx configuration
473  docker run --rm -v $(pwd)/nginx/dev/default.conf:/etc/nginx/conf.d/default.conf nginx:alpine nginx -t
474  git add nginx/dev/default.conf
475  git commit -m "Fix Nginx: Update default.conf to resolve upstream and MIME type issues"
476  
477  # Step 6: Update scripts/up-dev.sh
478  echo "Updating scripts/up-dev.sh..."
479  cat > scripts/up-dev.sh << 'EOF'
480  #!/bin/bash
481  set -e
482  
483  echo "Starting fold-stack development environment (excluding Overleaf CE by default)..."
484  docker compose --env-file .env.dev -f docker-compose.dev.yml up -d --build ghost forgejo radicle pandoc mailhog trilium hedgedoc nextcloud rclone typst git-sync flame_dashboard nginx
485  echo "Core services started. To enable Overleaf CE, run: ./scripts/enable-overleaf.sh"
486  EOF
487  sudo chmod 755 scripts/up-dev.sh
488  sudo chown mrhavens:mrhavens scripts/up-dev.sh
489  git add scripts/up-dev.sh
490  git commit -m "Update up-dev.sh: Explicitly load .env.dev"
491  
492  # Step 7: Fix Rclone by creating scripts/rclone-sync.sh
493  echo "Fixing Rclone..."
494  cat > scripts/rclone-sync.sh << 'EOF'
495  #!/bin/bash
496  set -e
497  
498  echo "Starting rclone sync at $(date)"
499  rclone sync /data nextcloud:/ --config=/config/rclone/rclone.conf --log-level INFO --log-file=/data/rclone.log
500  echo "Rclone sync completed at $(date)"
501  EOF
502  sudo chmod 755 scripts/rclone-sync.sh
503  sudo chown mrhavens:mrhavens scripts/rclone-sync.sh
504  # Verify rclone.conf exists
505  if [ ! -f config/rclone/rclone.conf ]; then
506      echo "Warning: config/rclone/rclone.conf not found. Please configure it with 'docker exec -it rclone_dev rclone config' after starting the stack."
507  fi
508  docker compose -f docker-compose.dev.yml restart rclone
509  git add scripts/rclone-sync.sh
510  git commit -m "Fix Rclone: Add rclone-sync.sh"
511  
512  # Step 8: Fix Git-Sync permissions
513  echo "Fixing Git-Sync permissions..."
514  sudo chown -R 1000:1000 ./volumes/repos
515  sudo chmod -R 775 ./volumes/repos
516  docker compose -f docker-compose.dev.yml restart git-sync
517  git add volumes/repos
518  git commit -m "Fix Git-Sync: Correct volume permissions" || echo "No changes to commit for Git-Sync permissions"
519  
520  # Step 9: Fix Nextcloud permissions
521  echo "Fixing Nextcloud permissions..."
522  sudo chown -R 33:33 ./volumes/nextcloud/data
523  sudo chmod -R 775 ./volumes/nextcloud/data
524  docker compose -f docker-compose.dev.yml restart nextcloud
525  git add volumes/nextcloud/data
526  git commit -m "Fix Nextcloud: Correct data volume permissions" || echo "No changes to commit for Nextcloud permissions"
527  
528  # Step 10: Fix general permissions
529  echo "Fixing general permissions..."
530  sudo chown -R 1000:1000 ./volumes ./nginx ./config ./scripts
531  sudo chmod -R 775 ./volumes ./nginx ./config
532  sudo chmod -R 755 ./scripts
533  git add .
534  git commit -m "Fix general permissions across volumes and configs" || echo "No changes to commit for general permissions"
535  
536  # Step 11: Start the stack
537  echo "Starting the stack..."
538  ./scripts/up-dev.sh
539  
540  # Step 12: Verify services
541  echo "Verifying services..."
542  docker ps
543  echo "Access Flame at http://localhost:5005 or http://localhost/flame/ (password: securepassword123)"
544  echo "Access other services via:"
545  echo "  - Ghost: http://localhost/ghost/"
546  echo "  - Forgejo: http://localhost/forgejo/"
547  echo "  - Trilium: http://localhost/trilium/"
548  echo "  - HedgeDoc: http://localhost/hedgedoc/"
549  echo "  - Nextcloud: http://localhost/nextcloud/"
550  
551  # Step 13: Run diagnostics
552  echo "Running diagnostics..."
553  ./scripts/diagnose-dev.sh
554  
555  echo "Patch application complete! If issues persist, check logs with 'docker logs <container_name>' or share the diagnostics output."