commit 33ddf7705e59c598d3cdac0d0a4851f5b57adae7 Author: jfcheng Date: Sun Feb 22 11:53:11 2026 -0500 feat: Add new Portainer stacks, setup scripts, and configurations for various services including filebrowser, paperless, and firefly. diff --git a/audiobookshelf/create_audiobookshelf_folders.sh b/audiobookshelf/create_audiobookshelf_folders.sh new file mode 100644 index 0000000..a1e1d5b --- /dev/null +++ b/audiobookshelf/create_audiobookshelf_folders.sh @@ -0,0 +1,11 @@ +# Define base path +BASE="/volume1/docker/audiobookshelf" +MEDIABASE="/volume1/media" + +# Create folders +mkdir -p "${BASE}/config" "${BASE}/metadata" "${MEDIABASE}/audiobooks" "${MEDIABASE}/podcasts" + +# Set ownership and permissions +chmod -R 750 "${BASE}" +chmod -R 750 "${MEDIABASE}/audiobooks" +chmod -R 750 "${MEDIABASE}/podcasts" diff --git a/audiobookshelf/docker-compose.portainer.yml b/audiobookshelf/docker-compose.portainer.yml new file mode 100644 index 0000000..9df95e3 --- /dev/null +++ b/audiobookshelf/docker-compose.portainer.yml @@ -0,0 +1,19 @@ +version: "3.9" + +services: + audiobookshelf: + image: ghcr.io/advplyr/audiobookshelf:latest + container_name: audiobookshelf + restart: unless-stopped +#this docker image only works with root + ports: + - "13378:80" + + environment: + - TZ=America/Toronto + + volumes: + - /volume1/docker/audiobookshelf/config:/config + - /volume1/docker/audiobookshelf/metadata:/metadata + - /volume1/media/audiobooks:/audiobooks + - /volume1/media/podcasts:/podcasts \ No newline at end of file diff --git a/calibrewebautomated/create_calibrewebautomated_folders.sh b/calibrewebautomated/create_calibrewebautomated_folders.sh new file mode 100644 index 0000000..059263e --- /dev/null +++ b/calibrewebautomated/create_calibrewebautomated_folders.sh @@ -0,0 +1,11 @@ +# Define base path +BASE="/volume1/docker/calibre-web-automated" + +# Create folders +mkdir -p "${BASE}/config" "${BASE}/plugins" + +# Set ownership and permissions +chown -R 1029:65538 "${BASE}" +# Set ownership and permissions +chmod -R 750 "${BASE}" + diff --git a/calibrewebautomated/kobo/Kobo eReader.conf b/calibrewebautomated/kobo/Kobo eReader.conf new file mode 100644 index 0000000..592eb66 --- /dev/null +++ b/calibrewebautomated/kobo/Kobo eReader.conf @@ -0,0 +1,249 @@ +[General] +DictionaryRecentSearches=generously, hordes, idiosyncrasy, taxidermy, taxidermitry, taxidermist, sacrilegious, savoury, savory, juxtaposed +LibraryRecentSearches=unsee, "Life 3.0: Being Human in the Age of Artificial Intelligence" +StoreRecentSearches=the chaos machine, the chaos, science fiction, man search for meaning, "Artemis (Andy Weir)", "Project Hail Mary (Andy Weir)", poor economics, poor ecnomics, "The New Jim Crow: Mass Incarceration in the Age of Colorblindness by Michelle Alexander | Conversation Starters (dailyBooks)", "The Ride of a Lifetime (Robert Iger)" + +[ApplicationPreferences] +AIRPLANE_MODE=false +BookstoreViewVisitCount=2 +BorrowDialogShown=true +CurrentLocale=en +DesktopSyncCount=2 +DictionaryOpenCount=-1 +DuplicateAnnotationsCleanedUp=true +EarliestChangeLog=4.13.12410 +HomePageViewVisitCount=30 +IntegratedBrowseDialogShown=true +IntegratedBrowseDialogTime=@Variant(\0\0\0\x10\0%\x8a:\x4\xaem\xb1\xff) +KoboPlusPromoShown=true +LargePrintMode=false +LastAffiliateSyncTime=@Variant(\0\0\0\x10\0%\x8d|\0\xf2\x8d<\x2) +LastAuthorsListSorter_authorList_=sortByFirstName() +LastFTEStep=LOGIN +LastLibrarySorter_articles_filterByArticles%28%29=sortByDateAdded() +LastLibrarySorter_author_filterByAuthor%28Brian%20Christian%29=sortByNewest() +LastLibrarySorter_author_filterByAuthor%28Brian%20W.%20Kernighan%29=sortByNewest() +LastLibrarySorter_author_filterByAuthor%28David%20Graeber%29=sortByNewest() +LastLibrarySorter_author_filterByAuthor%28Ethan%20Siegel%29=sortByNewest() +LastLibrarySorter_author_filterByAuthor%28Jason%20Fung%29=sortByNewest() +LastLibrarySorter_author_filterByAuthor%28Kevin%20Horsley%29=sortByNewest() +LastLibrarySorter_author_filterByAuthor%28Monty%20Lyman%29=sortByNewest() +LastLibrarySorter_author_filterByAuthor%28Nassim%20Nicholas%20Taleb%29=sortByNewest() +LastLibrarySorter_author_filterByAuthor%28PhD%29=sortByNewest() +LastLibrarySorter_author_filterByAuthor%28Richard%20Dawkins%29=sortByNewest() +LastLibrarySorter_author_filterByAuthor%28Robert%20Iger%29=sortByNewest() +LastLibrarySorter_author_filterByAuthor%28Simon%20Winchester%29=sortByNewest() +LastLibrarySorter_author_filterByAuthor%28the%20free%29=sortByNewest() +LastLibrarySorter_books_filterByAllItems%28%29=sortByNewest() +LastLibrarySorter_series_filterBySeries%285890ad21-74d9-5c72-a9f7-81d8523c33aa%29=sortByBookNumber() +LastLibrarySorter_series_filterBySeries%28fa6daece-c358-5efe-82ff-c860dca7fa96%29=sortByBookNumber() +LastLibrarySorter_shelf_filterByBookshelf%28Incerto%29=sortByNewest() +LastLibrarySorter_shelf_filterByBookshelf%28Kobo%20Forma%29=sortByNewest() +LastLibrarySorter_shelf_filterByBookshelf%28Kobo%29=sortByNewest() +LastLibrarySorter_shelf_filterByBookshelf%28Oakville%20Library%29=sortByNewest() +LastLibrarySorter_shelf_filterByBookshelf%28Photography%29=sortByNewest() +LastLibrarySubFilter_ManageBooks_filterByAllItems%28%29= +LastLibrarySubFilter_articles_filterByArticles%28%29= +LastLibrarySubFilter_author_filterByAuthor%28Brian%20Christian%29= +LastLibrarySubFilter_author_filterByAuthor%28Brian%20W.%20Kernighan%29= +LastLibrarySubFilter_author_filterByAuthor%28David%20Graeber%29= +LastLibrarySubFilter_author_filterByAuthor%28Ethan%20Siegel%29= +LastLibrarySubFilter_author_filterByAuthor%28Jason%20Fung%29= +LastLibrarySubFilter_author_filterByAuthor%28Kevin%20Horsley%29= +LastLibrarySubFilter_author_filterByAuthor%28Monty%20Lyman%29= +LastLibrarySubFilter_author_filterByAuthor%28Nassim%20Nicholas%20Taleb%29= +LastLibrarySubFilter_author_filterByAuthor%28PhD%29= +LastLibrarySubFilter_author_filterByAuthor%28Richard%20Dawkins%29= +LastLibrarySubFilter_author_filterByAuthor%28Robert%20Iger%29= +LastLibrarySubFilter_author_filterByAuthor%28Simon%20Winchester%29= +LastLibrarySubFilter_author_filterByAuthor%28the%20free%29= +LastLibrarySubFilter_books_filterByAllItems%28%29= +LastLibrarySubFilter_series_filterBySeries%285890ad21-74d9-5c72-a9f7-81d8523c33aa%29= +LastLibrarySubFilter_series_filterBySeries%28fa6daece-c358-5efe-82ff-c860dca7fa96%29= +LastLibrarySubFilter_shelf_filterByBookshelf%28Incerto%29= +LastLibrarySubFilter_shelf_filterByBookshelf%28Kobo%20Forma%29= +LastLibrarySubFilter_shelf_filterByBookshelf%28Kobo%29= +LastLibrarySubFilter_shelf_filterByBookshelf%28Oakville%20Library%29= +LastLibrarySubFilter_shelf_filterByBookshelf%28Photography%29= +LastLibraryTab=Collections +LastLibraryViewType_articles=viewBy3x3ArticleGrid() +LastLibraryViewType_author=viewBy5List() +LastLibraryViewType_books=viewBy5List() +LastLibraryViewType_series=viewBy5List() +LastLibraryViewType_seriesList=viewBy5List() +LastLibraryViewType_shelf=viewBy5Shelf() +LastManageBooksSorter_ManageBooks_filterByAllItems%28%29=sortByNewest() +LastMostPopularSyncTime=@Variant(\0\0\0\x10\0%\x8d|\x3\x9b\x45L\x2) +LastSearchType_Home=Library +LastSearchType_Library=Dictionary +LastSearchType_ReadingView=Dictionary +LastSearchType_Store=OverDrive +LastSeriesListSorter_seriesList_=sortByRecent() +LastShelfListSorter_shelfList_=sortByShelfName() +LastShelfListSorter_shelfList_filterByAddToShelf=sortByShelfName() +LastShelfSorter_books_filterByAllItems%28%29=sortByNewest() +LastSimilarLibrarySorter_books_filterByAllItems%28%29=sortByNewest() +LastStoreTab=eBooks +LastSyncTime=@Variant(\0\0\0\x10\0%\x8d|\x3\x9f\x13\xe3\x2) +LastTopPicksSyncTime=@Variant(\0\0\0\x10\0%\x8d|\0\xf3w\xe9\x2) +LastUpdateCheckTime=@Variant(\0\0\0\x10\0%\x8d|\x3\x9b\x37\xae\x2) +LibraryCuratedListsDialogShown=true +LibraryViewVisitCount=30 +LongPressDialogShown=true +MarkAsFinishedLastShown=@Variant(\0\0\0\x10\0%\x8c\xc1\x1\xe8p\xcf\xff) +MarkAsUnreadLastShown=@Variant(\0\0\0\x10\0%\x8b\xf1\x3\x41\xddM\xff) +MostRecentReadID=99a8b0c9-94cd-400d-bef1-2b3fdb4a2cb7 +OverDriveExpiryDialogShown=true +OverDriveFilterShown=true +OverDriveHoldListSorter_overDriveHoldList_=sortByEstimatedWait() +QuickTourWidgetShown=true +ReadABookShown2=true +ReadingSettingsChanged=true +SearchResultsviewVisitCount=2 +SignInTime=@Variant(\0\0\0\x10\0%\x8a:\x4\xa6\n:\xff) +SmartLink_%05=3 +SmartLink_%06=3 +SmartLink_%07=3 +SmartLink_%08=404 +StylusTipWarning=true +SubscriptionPlanAbTestEnabled=true +SwipeDialogShown=true +VisitedFrontLightLearnMore=true +WifiRegulatoryDomain=CA +WifiReminderDialogShown=true +firstRotateDone=true +firstRunDate=@Variant(\0\0\0\x10\0%\x84\xd3\x4\x3\xb5\x92\x2) +hasSyncedExistingRelatedItems=true +lastPlugTime=@Variant(\0\0\0\x10\0%\x8d|\0\xf4\x16\xe3\x2) +lockedOrientation=5 +sleepOnNextBoot=false +syncOnNextBoot=false + +[Browser] +certExceptions=@Variant(\0\0\0\x1c\0\0\0\x2\0\0\0\x32\0s\0\x65\0r\0v\0i\0\x63\0\x65\0.\0m\0\x61\0x\0y\0m\0i\0s\0\x65\0r\0.\0n\0\x65\0t\0:\0\x34\0\x34\0\x33\0\0\0\f\0\0\0 [\x81P\xc8\xd0:0\x86\x43\xe1t4\x8a`B\xb1\xee\xf2{\xa4]\xda}\xfe\xad\xb3\x65\x96\x33\xb2\x89\x9d\0\0\0$\0w\0w\0w\0.\0h\0i\0l\0t\0o\0n\0.\0\x63\0o\0m\0:\0\x34\0\x34\0\x33\0\0\0\f\0\0\0 [\x81P\xc8\xd0:0\x86\x43\xe1t4\x8a`B\xb1\xee\xf2{\xa4]\xda}\xfe\xad\xb3\x65\x96\x33\xb2\x89\x9d) + +[DialogSettings] +InstapaperJitShown=true +ReleaseNotesShown=true +ReturningReaderDialogShown=true + +[DropboxSettings] +AccessToken=G8wEe4GjZ0cAAAAAAAAa0CEDDyC4crP51r89PTM_XzhanzFFEUqsTgQAArJSVym6 +SortType=sortByModifiedDate() +UserGuideId=id:4gkVQTWkSR8AAAAAAAAMqA +Username=jianfeng.cheng@gmail.com + +[FeatureSettings] +ExcludeSyncFolders=(\\.(?!kobo|adobe).+|([^.][^/]*/)+\\..+) + +[OneStoreServices] +account_page=https://www.kobo.com/account/settings +account_page_rakuten=https://my.rakuten.co.jp/ +annotations_host=https://annotations.kobo.com +api_endpoint=http://10.168.168.5:8083/kobo/4020539f4c3a97748766f2895cd717a9 +autocomplete=https://storeapi.kobo.com/v1/products/autocomplete +book=https://storeapi.kobo.com/v1/products/books/{ProductId} +book_detail_page=https://www.kobo.com/{region}/{language}/ebook/{slug} +book_detail_page_rakuten=http://books.rakuten.co.jp/rk/{crossrevisionid} +book_landing_page=https://www.kobo.com/ebooks +categories=https://storeapi.kobo.com/v1/categories +category=https://storeapi.kobo.com/v1/categories/{CategoryId} +category_products=https://storeapi.kobo.com/v1/categories/{CategoryId}/products +dictionary_host=https://ereaderfiles.kobo.com +discovery_host=https://discovery.kobobooks.com +display_accessibility_enabled= +display_parental_controls_enabled= +dropbox_link_account_poll= +eula_page="https://www.kobo.com/termsofuse?style=onestore" +featured_list=https://storeapi.kobo.com/v1/products/featured/{FeaturedListId} +featured_lists=https://storeapi.kobo.com/v1/products/featured +feedback= +fte_feedback=https://storeapi.kobo.com/v1/products/ftefeedback +googledrive_link_account_start= +image_host=http://10.168.168.5:8083 +image_url_quality_template=http://10.168.168.5:8083/kobo/4020539f4c3a97748766f2895cd717a9/{ImageId}/{width}/{height}/{Quality}/isGreyscale/image.jpg +image_url_template=http://10.168.168.5:8083/kobo/4020539f4c3a97748766f2895cd717a9/{ImageId}/{width}/{height}/false/image.jpg +instapaper_enabled= +instapaper_env_url= +instapaper_link_account_start= +kobo_audiobooks_credit_redemption=False +kobo_audiobooks_enabled=True +kobo_dropbox_link_account_enabled=False +kobo_googledrive_link_account_enabled=False +kobo_nativeborrow_enabled=False +kobo_privacyCentre_url=https://www.kobo.com/privacy +kobo_redeem_enabled=True +kobo_subscriptions_enabled=True +kobo_superpoints_enabled=True +kobo_wishlist_enabled=True +love_data=@ByteArray(\0\0\0\x1\0\0\0\x10\0\x42\0\x65\0n\0\x65\0\x66\0i\0t\0s\0\0\0\b\0\0\0\0\0) +love_points_redemption_page="https://www.kobo.com/{region}/{language}/KoboSuperPointsRedemption?productId={ProductId}" +magazine_detail_page= +magazine_landing_page=https://store.kobobooks.com/emagazines +oauth_host=https://oauth.kobo.com +password_retrieval_page=https://www.kobo.com/passwordretrieval.html +pocket_link_account_start=https://authorize.kobo.com/{region}/{language}/linkpocket +privacy_page="https://www.kobo.com/privacypolicy?style=onestore" +product_recommendations=https://storeapi.kobo.com/v1/products/{ProductId}/recommendations +product_reviews=https://storeapi.kobo.com/v1/products/{ProductIds}/reviews +purchase_buy_templated= +reading_services_host=https://readingservices.kobo.com +registration_page="https://authorize.kobo.com/signup?returnUrl=http://kobo.com/" +review=https://storeapi.kobo.com/v1/products/reviews/{ReviewId} +review_sentiment=https://storeapi.kobo.com/v1/products/reviews/{ReviewId}/sentiment/{Sentiment} +sign_in_page="https://authorize.kobo.com/signin?returnUrl=http://kobo.com/" +social_authorization_host=https://social.kobobooks.com:8443 +social_host=https://social.kobobooks.com +store_home=www.kobo.com/{region}/{language} +store_host=www.kobo.com +store_search="https://www.kobo.com/{region}/{language}/Search?Query={query}" +subs_landing_page=https://www.kobo.com/{region}/{language}/plus +subs_management_page=https://www.kobo.com/{region}/{language}/account/subscriptions +subs_plans_page=https://www.kobo.com/{region}/{language}/plus/plans +subs_purchase_buy_templated=https://www.kobo.com/{region}/{language}/Checkoutoption/{ProductId}/{TierId} +subscription_publisher_price_page= +taste_profile=https://storeapi.kobo.com/v1/products/tasteprofile +user_ratings=https://storeapi.kobo.com/v1/user/ratings +user_recommendations=https://storeapi.kobo.com/v1/user/recommendations +user_reviews=https://storeapi.kobo.com/v1/user/reviews +userguide_host=https://ereaderfiles.kobo.com + +[OverDrive] +overdrive_account=https://auth.overdrive.com/account +overdrive_library=https://{libraryKey}.auth.overdrive.com/library +overdrive_library_finder_host=https://libraryfinder.api.overdrive.com +overdrive_thunder_host=https://thunder.api.overdrive.com + +[PowerOptions] +AutoColorEnabled=true +BedTime=@Variant(\0\0\0\xf\x4\xefm\x80) +ColorSetting=2480 +FrontLightLevel=29 + +[Reading] +chapterProgressType=3 +deleteVolumeOnFinished=true +invertPageTurnButtons=false +newBookProgressType=0 +numPartialUpdatePageTurns=1 +readingAdobeShowPageNumbers=false +readingAlignment= +readingFontFamily=Amazon Ember +readingFontSharpness\AR%20UDJingxihei=-0.0666666666666667 +readingFontSharpness\Bookerly=-0.0666666666666667 +readingFontSharpness\KBJ-TsukuMin%20Pr6N%20RB=-0.28 +readingFontSharpness\SonyReader%20Kai=-0.0666666666666667 +readingFontSize=21 +readingFontWeight\AR%20UDJingxihei=0.1 +readingFontWeight\Bookerly=0.1 +readingFontWeight\KBJ-TsukuMin%20Pr6N%20RB=-0.11 +readingFontWeight\SonyReader%20Kai=0.1 +readingLeftMargin=2 +readingLineHeight=1.2 +readingMenuState= +readingRightMargin=2 + +[ReadingLife] +LastActivityNavItem=1 +LastReadingLifeSyncTime=@Variant(\0\0\0\x10\0%\x87-\x1\xd1\x38-\x2) +LastSocialAnnotationsSyncTime=@Variant(\0\0\0\x10\0%\x86~\x2H\xc2\xb0\x2) diff --git a/calibrewebautomated/kobo/tmp b/calibrewebautomated/kobo/tmp new file mode 100644 index 0000000..8b490e0 --- /dev/null +++ b/calibrewebautomated/kobo/tmp @@ -0,0 +1,9 @@ + sqlite3 /config/app.db "SELECT * FROM kobo;" + + + +http://10.168.168.5:8083/kobo/sync +http://10.168.168.5:8083/kobo +http://10.168.168.5:8083/kobo/0 +http://10.168.168.5:8083/kobo/device + diff --git a/cloudflared/cloudflared/cert.pem b/cloudflared/cloudflared/cert.pem new file mode 100644 index 0000000..94fc683 --- /dev/null +++ b/cloudflared/cloudflared/cert.pem @@ -0,0 +1,6 @@ +-----BEGIN ARGO TUNNEL TOKEN----- +eyJ6b25lSUQiOiI3ZGY4MWRkMzM4NGI2MDU3ODBkZGYzZGNjYmQyOTI5MCIsImFj +Y291bnRJRCI6IjJmZWIxMWZkZDlmYTczYTJhYjQ4MDUyMjM4NmJkNzM1IiwiYXBp +VG9rZW4iOiJESmxwNFR3RzVUZlJUZlFRdmdwdlZZdUxodVI4cEhiXzNUVk9xeFJL +In0= +-----END ARGO TUNNEL TOKEN----- diff --git a/cloudflared/commands.sh b/cloudflared/commands.sh new file mode 100644 index 0000000..8d622f0 --- /dev/null +++ b/cloudflared/commands.sh @@ -0,0 +1,43 @@ +#cloudflare API token +# AutoUpdateIP WhAIOCeGjws2IFCD32BJn1r8TS1M8SWeGbEYVuVc + +curl "https://api.cloudflare.com/client/v4/user/tokens/verify" \ +-H "Authorization: Bearer WhAIOCeGjws2IFCD32BJn1r8TS1M8SWeGbEYVuVc" + +#allow ping in cloudflared +sudo sysctl -w net.ipv4.ping_group_range="0 65535" + + +sudo mkdir -p /etc/sysctl.d +echo "net.ipv4.ping_group_range = 0 65535" | sudo tee /etc/sysctl.d/99-cloudflared.conf + + + +docker exec cloudflare-tunnel tunnel create nas-tunnel + + + +docker run -it --rm -v /volume1/docker/cloudflared:/etc/cloudflared cloudflare-tunnel tunnel login + + +docker run -it --rm \ + -v /volume1/docker/cloudflared:/etc/cloudflared \ + cloudflare/cloudflared:latest tunnel login + + +# tunnel uuid fb59f081-ac72-4fd9-bad3-9211b931d5e5 + + + +docker stop cloudflare-tunnel +docker rm cloudflare-tunnel + +docker run -it --rm \ + -v /volume1/docker/cloudflared:/root/.cloudflared \ + -v /volume1/docker/cloudflared/etc:/etc/cloudflared \ + cloudflare/cloudflared:latest tunnel login + + + docker run -it --rm \ + -v /volume1/docker/cloudflared:/root/.cloudflared \ + cloudflare/cloudflared:latest tunnel token nas \ No newline at end of file diff --git a/cloudflared/create_cloudflared_folders.sh b/cloudflared/create_cloudflared_folders.sh new file mode 100644 index 0000000..8f550c7 --- /dev/null +++ b/cloudflared/create_cloudflared_folders.sh @@ -0,0 +1,20 @@ +# Define base path +BASE="/volume1/docker/cloudflared" + +# Create folders +mkdir -p "${BASE}/etc" + +# Set ownership and permissions +chown -R 1037:65538 "${BASE}" +chmod -R 750 "${BASE}" + + +# Define base path +BASE="/volume1/docker/ddns-updater" + +# Create folders +mkdir -p "${BASE}" + +# Set ownership and permissions +chown -R 1037:65538 "${BASE}" +chmod -R 750 "${BASE}" \ No newline at end of file diff --git a/cloudflared/ddns-updater/config.json b/cloudflared/ddns-updater/config.json new file mode 100644 index 0000000..20dbac7 --- /dev/null +++ b/cloudflared/ddns-updater/config.json @@ -0,0 +1,14 @@ +{ + "settings": [ + { + "provider": "cloudflare", + "zone_identifier": "7df81dd3384b605780ddf3dccbd29290", + "domain": "chengs.uk", + "host": "@", + "ttl": 600, + "proxied": true, + "token": "WhAIOCeGjws2IFCD32BJn1r8TS1M8SWeGbEYVuVc", + "ip_version": "ipv4" + } + ] +} diff --git a/cloudflared/ddns-updater/updates.json b/cloudflared/ddns-updater/updates.json new file mode 100644 index 0000000..e69de29 diff --git a/cloudflared/docker-compose.portainer.yml b/cloudflared/docker-compose.portainer.yml new file mode 100644 index 0000000..8da78e8 --- /dev/null +++ b/cloudflared/docker-compose.portainer.yml @@ -0,0 +1,96 @@ +# Docker Compose configuration for setting up a Cloudflare Tunnel container +# +# This configuration pulls the latest Cloudflare Tunnel image from the specified repository +# and includes options for logging, automatic updates using Watchtower, health checks, and volume mounting. + +services: + + # Cloudflare Tunnel Service + cloudflare-tunnel: + image: cloudflare/cloudflared:latest # Pull the latest version of the Cloudflare Tunnel image + container_name: cloudflare-tunnel # Name of the Cloudflare Tunnel container + hostname: cloudflare-tunnel # Hostname for the Cloudflare Tunnel container + + user: root + + restart: unless-stopped # Restart the container unless manually stopped + + # Logging configuration for Cloudflare Tunnel container + logging: + driver: "json-file" # Use the default json-file logging driver + options: + max-size: "100m" # Maximum log file size before rotation (100 MB) + max-file: "10" # Maximum number of log files to retain (10) + + # Network mode configuration + network_mode: "host" # Use the host network (no isolation between host and container) + + # Command to run Cloudflare Tunnel + command: 'tunnel --no-autoupdate run' # Command to start the Cloudflare tunnel + + # Volume configuration for time synchronization and hosts file persistence + volumes: + - /etc/localtime:/etc/localtime:ro # Synchronize time with the host + - /volume1/docker/cloudflared:/root/.cloudflared + - /volume1/docker/cloudflared/etc:/etc/cloudflared + + #- ./config/hosts:/etc/hosts # Mount hosts file from host to container + + # Environment variables for Cloudflare Tunnel + # cloudflared.exe service install eyJhIjoiMmZlYjExZmRkOWZhNzNhMmFiNDgwNTIyMzg2YmQ3MzUiLCJ0IjoiZmI1OWYwODEtYWM3Mi00ZmQ5LWJhZDMtOTIxMWI5MzFkNWU1IiwicyI6IllqWXdaVFEyTURrdFpHVXpPUzAwTnpNMkxUazJPREl0T0RGak9UZ3dOelV3Tm1ZeCJ9 + environment: + - NO_AUTOUPDATE=true + - "TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN}" # Pass the Cloudflare Tunnel token from environment variable + + # Health check configuration to verify Cloudflare Tunnel readiness + healthcheck: + test: ["CMD", "cloudflared", "--version"] # Check if cloudflared version command works + interval: 30s # Time between health check attempts + timeout: 10s # Time to wait for a response + retries: 3 # Number of retries before marking as unhealthy + start_period: 10s # Delay before health checks begin + + # Container labels for additional metadata + labels: + - "com.centurylinklabs.watchtower.enable=true" # Enable automatic updates with Watchtower + + +# +#################################################### +# # +# -------DDNS-Updater------- # +# # +#################################################### +# + ddns-updater: + container_name: ddns-updater + restart: always + hostname: ddns-updater + environment: + - TZ=America/Toronto + - PUID=$PUID + - PGID=$PGID + - PERIOD=5m + - UPDATE_COOLDOWN_PERIOD=5m + - PUBLICIP_FETCHERS=all + - PUBLICIP_HTTP_PROVIDERS=all + - PUBLICIPV4_HTTP_PROVIDERS=all + - PUBLICIPV6_HTTP_PROVIDERS=all + - PUBLICIP_DNS_PROVIDERS=all + - PUBLICIP_DNS_TIMEOUT=3s + - HTTP_TIMEOUT=10s + - LISTENING_PORT=8000 + - HEALTH_SERVER_ADDRESS=127.0.0.1:9999 + - ROOT_URL=/ + - BACKUP_PERIOD=24h # 0 to disable + - BACKUP_DIRECTORY=/updater/data + - LOG_LEVEL=info + - LOG_CALLER=hidden + - SHOUTRRR_ADDRESSES=pushover://shoutrrr:$PUSHOVER_API@$PUSHOVER_USER_KEY + volumes: + - /volume1/docker/ddns-updater:/updater/data + ports: + - 8002:8000/tcp + user: $PUID:$PGID + image: 'qmcgaw/ddns-updater:latest' +# \ No newline at end of file diff --git a/coding/docker-compose.portainer.yml b/coding/docker-compose.portainer.yml new file mode 100644 index 0000000..c65ee8d --- /dev/null +++ b/coding/docker-compose.portainer.yml @@ -0,0 +1,35 @@ +version: "3.9" + +services: + openvscode: + image: ghcr.io/gitpod-io/openvscode-server:latest + container_name: openvscode + restart: unless-stopped + + # Expose the web IDE + ports: + - "3000:3000" + + # Persist extensions, settings, and workspace files + volumes: + - /volume1/docker/openvscode/config:/home/workspace/.openvscode-server + - /volume1/docker/openvscode/projects:/home/workspace/projects + + # Optional: mount SSH keys for Gitea access + # Make sure permissions are correct (600) + # volumes: + # - /volume1/docker/ssh/id_rsa:/home/workspace/.ssh/id_rsa:ro + # - /volume1/docker/ssh/known_hosts:/home/workspace/.ssh/known_hosts:ro + + environment: + # Ensures the server listens on all interfaces + OPENVSCODE_SERVER_HOST: "0.0.0.0" + OPENVSCODE_SERVER_PORT: "3000" + + # Optional: put it on a shared network for Cloudflared or Traefik + networks: + - openvscode_net + +networks: + openvscode_net: + driver: bridge diff --git a/diagram/docker-compose.portainer.yml b/diagram/docker-compose.portainer.yml new file mode 100644 index 0000000..6ee3b81 --- /dev/null +++ b/diagram/docker-compose.portainer.yml @@ -0,0 +1,11 @@ +services: + vert: + container_name: vert + image: ghcr.io/vert-sh/vert:latest + restart: unless-stopped + ports: + - 3002:80 + environment: + - USER_UID=1039 + - USER_GID=65538 + - TZ=America/Toronto \ No newline at end of file diff --git a/filebrowser/create_filebrowser_folders.sh b/filebrowser/create_filebrowser_folders.sh new file mode 100644 index 0000000..716a896 --- /dev/null +++ b/filebrowser/create_filebrowser_folders.sh @@ -0,0 +1,18 @@ +# Define base path +BASE="/volume1/docker/filebrowser" + +# Create folders +mkdir -p "${BASE}/config" "${BASE}/database" "${BASE}/data" + +# Set ownership and permissions +chown -R 1042:65538 "${BASE}" +chmod -R 750 "${BASE}" + +touch "${BASE}/config/settings.json" +chown 1042:65538 "${BASE}/config/settings.json" +chmod 640 "${BASE}/config/settings.json" + + +touch "${BASE}/database/filebroser.db" +chown 1042:65538 "${BASE}/database/filebroser.db" +chmod 640 "${BASE}/database/filebroser.db" diff --git a/filebrowser/docker-compose.portainer.yml b/filebrowser/docker-compose.portainer.yml new file mode 100644 index 0000000..06e5eba --- /dev/null +++ b/filebrowser/docker-compose.portainer.yml @@ -0,0 +1,16 @@ + +version: "3" + +services: + filebrowser: + image: hurlenko/filebrowser + user: "1042:65538" + container_name: filebrowser + restart: unless-stopped + ports: + - 3020:8080 + volumes: + - /volume1/docker/filebrowser/data:/data + - /volume1/docker/filebrowser/config:/config + environment: + - FB_BASEURL=/filebrowser diff --git a/firefly/Categories.txt b/firefly/Categories.txt new file mode 100644 index 0000000..de10d26 --- /dev/null +++ b/firefly/Categories.txt @@ -0,0 +1,57 @@ +🟦 1. Housing +- Mortgage / Rent +- Property Tax +- Home Insurance +- Utilities (Hydro, Gas, Water) +- Internet +- Home Maintenance +- Furniture & Appliances + +2. Transportation +- Fuel +- Public Transit +- Parking +- Car Insurance +- Car Maintenance +- Car Loan / Lease +- Ride‑sharing (Uber, Lyft) +🟦 3. Food & Dining +- Groceries +- Restaurants +- Coffee Shops +- Takeout / Delivery +🟦 4. Health & Wellness +- Health Insurance +- Dental +- Prescriptions +- Medical Services +- Gym / Fitness +- Therapy / Wellness +🟦 5. Personal & Family +- Clothing +- Personal Care (haircuts, cosmetics) +- Childcare +- School / Education +- Gifts +- Pets +🟦 6. Entertainment & Leisure +- Streaming Services +- Hobbies +- Books & Media +- Events / Tickets +- Travel +🟦 7. Financial +- Bank Fees +- Credit Card Interest +- Investment Contributions +- RRSP / TFSA / RESP +- Accountant / Legal Fees +🟦 8. Business / Work (optional) +- Software Subscriptions +- Office Supplies +- Professional Development +🟦 9. Miscellaneous +- Uncategorized +- One‑off purchases + + diff --git a/firefly/create_fireflyiii_folders.sh b/firefly/create_fireflyiii_folders.sh new file mode 100644 index 0000000..7227e8d --- /dev/null +++ b/firefly/create_fireflyiii_folders.sh @@ -0,0 +1,9 @@ +# Define base path +BASE="/volume1/docker/fireflyiii" + +# Create folders +mkdir -p "${BASE}/upload" "${BASE}/db" + +# Set ownership and permissions +chown -R 1040:65538 "${BASE}" +chmod -R 750 "${BASE}" diff --git a/firefly/dbcommand b/firefly/dbcommand new file mode 100644 index 0000000..0e5fa31 --- /dev/null +++ b/firefly/dbcommand @@ -0,0 +1,45 @@ + +1uQ$g72*$9Gw4yFs + + +$2y$10$2OcSKhMVh6fXLVcxJ6gPx.jtJisfX/j5WM5DE8dAhIibH6hZp/2ze + + + + +INSERT INTO users (email, password, created_at, updated_at) +VALUES ('jeffcheng@live.ca', '$2y$10$2OcSKhMVh6fXLVcxJ6gPx.jtJisfX/j5WM5DE8dAhIibH6hZp/2ze', NOW(), NOW() + + + +INSERT INTO user_groups (title, created_at, updated_at) +VALUES ('User group for jeffcheng@live.ca', NOW(), NOW()); + + + +SELECT id, title FROM user_groups ORDER BY id DESC LIMIT 1; + + + +INSERT INTO user_group_membership (user_id, user_group_id, created_at, updated_at) +VALUES (2, 2, NOW(), NOW()); + + + +DROP DATABASE firefly; +CREATE DATABASE firefly CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; + + + +MULTIUSER=true + +apt UPDATE + +apt install mysql-client + + +mysql -u firefly -p + + + +github token: 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 \ No newline at end of file diff --git a/firefly/docker-compose.portainer.yml b/firefly/docker-compose.portainer.yml new file mode 100644 index 0000000..701f752 --- /dev/null +++ b/firefly/docker-compose.portainer.yml @@ -0,0 +1,79 @@ +# +# The Firefly III Data Importer will ask you for the Firefly III URL and a "Client ID". +# You can generate the Client ID at http://localhost/profile (after registering) +# The Firefly III URL is: http://app:8080 +# +# Other URL's will give 500 | Server Error +# + +services: + app: + image: fireflyiii/core:latest + hostname: app + container_name: firefly_iii_core + networks: + - firefly_iii + restart: always + volumes: + - /volume1/docker/fireflyiii/upload:/var/www/html/storage/upload + env_file: stack.env + ports: + - '8080:8080' + depends_on: + - db + db: + image: mariadb:lts + hostname: db + container_name: firefly_iii_db + networks: + - firefly_iii + restart: always + env_file: stack.env + volumes: + - /volume1/docker/fireflyiii/db:/var/lib/mysql + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 5s + timeout: 3s + retries: 10 + + importer: + image: fireflyiii/data-importer:latest + hostname: importer + restart: always + container_name: firefly_iii_importer + networks: + - firefly_iii + ports: + - '8081:8080' + depends_on: + - app + env_file: stack.env + + cron: + # + # To make this work, set STATIC_CRON_TOKEN in your .env file or as an environment variable + # The STATIC_CRON_TOKEN must be *exactly* 32 characters long + # Use this URL for inspiration: https://www.random.org/strings/?num=1&len=32&digits=on&upperalpha=on&loweralpha=on&unique=on&format=html&rnd=new + # + image: alpine + container_name: firefly_iii_cron + restart: always + env_file: stack.env + command: sh -c " + apk add tzdata && \ + (ln -fs /usr/share/zoneinfo/$$TZ /etc/localtime || true) && \ + echo \"0 3 * * * wget -qO- http://app:8080/api/v1/cron/$$STATIC_CRON_TOKEN;echo\" + | crontab - && \ + crond -f -L /dev/stdout" + networks: + - firefly_iii + depends_on: + - app +volumes: + firefly_iii_upload: + firefly_iii_db: + +networks: + firefly_iii: + driver: bridge \ No newline at end of file diff --git a/firefly/import_settings/americanexpress.json b/firefly/import_settings/americanexpress.json new file mode 100644 index 0000000..323fcd0 --- /dev/null +++ b/firefly/import_settings/americanexpress.json @@ -0,0 +1,80 @@ +{ + "version": 3, + "source": "ff3-importer-1.9.1", + "created_at": "2025-12-28T12:02:55-05:00", + "date": "d M Y", + "default_account": 9, + "delimiter": "comma", + "headers": true, + "rules": true, + "skip_form": false, + "add_import_tag": true, + "roles": [ + "date_transaction", + "date_process", + "description", + "note", + "_ignore", + "amount_debit", + "amount_foreign", + "_ignore", + "_ignore", + "_ignore", + "_ignore", + "_ignore", + "_ignore", + "_ignore", + "_ignore", + "_ignore" + ], + "do_mapping": [ + true, + true, + true, + true, + true, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false, + false + ], + "mapping": {}, + "duplicate_detection_method": "classic", + "ignore_duplicate_lines": false, + "unique_column_index": 0, + "unique_column_type": "internal_reference", + "flow": "file", + "content_type": "csv", + "custom_tag": "Inbox", + "identifier": "0", + "connection": "0", + "ignore_spectre_categories": false, + "grouped_transaction_handling": "", + "use_entire_opposing_address": false, + "map_all_data": true, + "pending_transactions": false, + "access_token": "", + "accounts": {}, + "new_accounts": [], + "date_range": "", + "date_range_number": 30, + "date_range_unit": "d", + "date_range_not_after_unit": "", + "date_range_not_after_number": 0, + "date_not_before": "", + "date_not_after": "", + "nordigen_country": "", + "nordigen_bank": "", + "nordigen_requisitions": {}, + "nordigen_max_days": "90", + "lunch_flow_api_key": "", + "conversion": false, + "ignore_duplicate_transactions": true +} \ No newline at end of file diff --git a/firefly/stack.env b/firefly/stack.env new file mode 100644 index 0000000..35d59cd --- /dev/null +++ b/firefly/stack.env @@ -0,0 +1,165 @@ +# Firefly III +APP_ENV=production +APP_DEBUG=false +SITE_OWNER=mail@example.com +APP_KEY=cwj06oiSL03ua4auOUj6upS3X92QoSI3 +DEFAULT_LANGUAGE=en_US +DEFAULT_LOCALE=equal +TZ=America/Toronto +TRUSTED_PROXIES= +LOG_CHANNEL=stack +APP_LOG_LEVEL=notice +AUDIT_LOG_LEVEL=emergency +AUDIT_LOG_CHANNEL= +PAPERTRAIL_HOST= +PAPERTRAIL_PORT= +DB_CONNECTION=mysql +DB_HOST=db +DB_PORT=3306 +DB_DATABASE=firefly +DB_USERNAME=firefly +DB_PASSWORD=m5wyMiU0CeEDmiptcZsCA2DC37Bsa5zH +DB_SOCKET= +MYSQL_USE_SSL=false +MYSQL_SSL_VERIFY_SERVER_CERT=true +MYSQL_SSL_CAPATH=/etc/ssl/certs/ +MYSQL_SSL_CA= +MYSQL_SSL_CERT= +MYSQL_SSL_KEY= +MYSQL_SSL_CIPHER= +PGSQL_SSL_MODE=prefer +PGSQL_SSL_ROOT_CERT=null +PGSQL_SSL_CERT=null +PGSQL_SSL_KEY=null +PGSQL_SSL_CRL_FILE=null +PGSQL_SCHEMA=public +CACHE_DRIVER=file +SESSION_DRIVER=file +REDIS_SCHEME=tcp +REDIS_PATH= +REDIS_HOST=127.0.0.1 +REDIS_PORT=6379 +REDIS_USERNAME= +REDIS_PASSWORD= +REDIS_DB="0" +REDIS_CACHE_DB="1" +COOKIE_PATH="/" +COOKIE_DOMAIN= +COOKIE_SECURE=false +COOKIE_SAMESITE=lax +MAIL_MAILER=log +MAIL_HOST=null +MAIL_PORT=2525 +MAIL_FROM=changeme@example.com +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_SENDMAIL_COMMAND= +MAIL_ALLOW_SELF_SIGNED=false +MAIL_VERIFY_PEER=true +MAIL_VERIFY_PEER_NAME=true +MAILGUN_DOMAIN= +MAILGUN_SECRET= +MAILGUN_ENDPOINT=api.mailgun.net +MANDRILL_SECRET= +SPARKPOST_SECRET= +MAILERSEND_API_KEY= +SEND_ERROR_MESSAGE=true +SEND_REPORT_JOURNALS=true +ENABLE_EXTERNAL_MAP=false +ENABLE_EXCHANGE_RATES=false +ENABLE_EXTERNAL_RATES=false +MAP_DEFAULT_LAT=51.983333 +MAP_DEFAULT_LONG=5.916667 +MAP_DEFAULT_ZOOM=6 +VALID_URL_PROTOCOLS= +AUTHENTICATION_GUARD=web +AUTHENTICATION_GUARD_HEADER=REMOTE_USER +AUTHENTICATION_GUARD_EMAIL= +PASSPORT_PRIVATE_KEY= +PASSPORT_PUBLIC_KEY= +CUSTOM_LOGOUT_URL= +DISABLE_FRAME_HEADER=false +DISABLE_CSP_HEADER=false +TRACKER_SITE_ID= +TRACKER_URL= +REPORT_ERRORS_ONLINE=false +ALLOW_WEBHOOKS=false +STATIC_CRON_TOKEN=r6FLbFEYByBXy0kPBJEZzBADjPDYWxtl +DKR_CHECK_SQLITE=true +APP_NAME=FireflyIII +BROADCAST_DRIVER=log +QUEUE_DRIVER=sync +CACHE_PREFIX=firefly +PUSHER_KEY= +IPINFO_TOKEN= +PUSHER_SECRET= +PUSHER_ID= +DEMO_USERNAME= +DEMO_PASSWORD= +USE_RUNNING_BALANCE=false +FIREFLY_III_LAYOUT=v1 +QUERY_PARSER_IMPLEMENTATION=new +APP_URL=http://localhost + +# Data Importer +FIREFLY_III_URL=http://app:8080 +VANITY_URL=http://localhost +FIREFLY_III_ACCESS_TOKEN= +FIREFLY_III_CLIENT_ID= +LUNCH_FLOW_API_KEY= +LUNCH_FLOW_API_URL=https://lunchflow.app/api/v1/ +NORDIGEN_ID= +NORDIGEN_KEY= +NORDIGEN_SANDBOX=false +RESPOND_TO_GOCARDLESS_LIMIT=wait +GOCARDLESS_GET_ACCOUNT_DETAILS=false +GOCARDLESS_GET_BALANCE_DETAILS=false +FALLBACK_LOCALE=en_US +SPECTRE_APP_ID= +SPECTRE_SECRET= +SIMPLEFIN_TOKEN= +SIMPLEFIN_DEMO_URL= +SIMPLEFIN_DEMO_TOKEN= +SIMPLEFIN_CONNECTION_TIMEOUT=30 +SIMPLEFIN_REQUEST_TIMEOUT=60 +SIMPLEFIN_RETRY_ATTEMPTS=3 +SIMPLEFIN_RETRY_DELAY= +SIMPLEFIN_MAX_TRANSACTIONS=10000 +SIMPLEFIN_DEFAULT_DATE_RANGE=90 +SIMPLEFIN_ENABLE_CACHING=true +SIMPLEFIN_CACHE_DURATION=3600 +SIMPLEFIN_SMART_EXPENSE_MATCHING=true +SIMPLEFIN_EXPENSE_MATCHING_THRESHOLD=0.7 +SIMPLEFIN_AUTO_CREATE_EXPENSE_ACCOUNTS=true +SIMPLEFIN_ENABLE_TRANSACTION_CLUSTERING=true +SIMPLEFIN_CLUSTERING_SIMILARITY_THRESHOLD=0.7 +USE_CACHE=true +IGNORE_DUPLICATE_ERRORS=false +IGNORE_NOT_FOUND_TRANSACTIONS=false +AUTO_IMPORT_SECRET= +CAN_POST_AUTOIMPORT=false +CAN_POST_FILES=false +IMPORT_DIR_ALLOWLIST= +FALLBACK_IN_DIR=false +VERIFY_TLS_SECURITY=true +JSON_CONFIGURATION_DIR= +CONNECTION_TIMEOUT=31.41 +LOG_RETURN_JSON=false +LOG_LEVEL=debug +ENABLE_MAIL_REPORT=false +EXPECT_SECURE_URL=false +FAKE_DATA=false +MAIL_DESTINATION=noreply@example.com +MAIL_FROM_ADDRESS=noreply@example.com +POSTMARK_TOKEN= +QUEUE_CONNECTION=sync +SESSION_LIFETIME=120 +IS_EXTERNAL=false +ASSET_URL= + +# Database +MYSQL_RANDOM_ROOT_PASSWORD=yes +MYSQL_USER=firefly +MYSQL_PASSWORD=m5wyMiU0CeEDmiptcZsCA2DC37Bsa5zH +MYSQL_DATABASE=firefly diff --git a/obsidian/create_obsidian_folders.sh b/obsidian/create_obsidian_folders.sh new file mode 100644 index 0000000..2aa6ea4 --- /dev/null +++ b/obsidian/create_obsidian_folders.sh @@ -0,0 +1,10 @@ +# Define base path +BASE="/volume1/docker/obsidian" + +# Create folders +mkdir -p "${BASE}/config" + +# Set ownership and permissions +chown -R 1038:65538 "${BASE}" +chmod -R 750 "${BASE}" +chmod -R 770 "${BASE}/config" diff --git a/obsidian/docker-composer.portainer.yml b/obsidian/docker-composer.portainer.yml new file mode 100644 index 0000000..2f61126 --- /dev/null +++ b/obsidian/docker-composer.portainer.yml @@ -0,0 +1,16 @@ +--- +services: + obsidian: + image: lscr.io/linuxserver/obsidian:latest + container_name: obsidian + environment: + - PUID=1038 + - PGID=65538 + - TZ=America/Toronto + volumes: + - /volume1/docker/obsidian/config:/config + ports: + - 3010:3000 + - 3011:3001 + shm_size: "1gb" + restart: unless-stopped \ No newline at end of file diff --git a/paperless/create_paperless_folders.sh b/paperless/create_paperless_folders.sh new file mode 100644 index 0000000..0187759 --- /dev/null +++ b/paperless/create_paperless_folders.sh @@ -0,0 +1,10 @@ +# Define base path +BASE="/volume1/docker/paperless" + +# Create folders +mkdir -p "${BASE}/data" "${BASE}/media" "${BASE}/export" "${BASE}/consume" "${BASE}/redisdata" + +# Set ownership and permissions +chown -R 1036:65538 "${BASE}" +chmod -R 750 "${BASE}" +chmod -R 770 "${BASE}/consume" diff --git a/paperless/docker-compose.env b/paperless/docker-compose.env new file mode 100644 index 0000000..f5f40c8 --- /dev/null +++ b/paperless/docker-compose.env @@ -0,0 +1,42 @@ +############################################################################### +# Paperless-ngx settings # +############################################################################### + +# See http://docs.paperless-ngx.com/configuration/ for all available options. + +# The UID and GID of the user used to run paperless in the container. Set this +# to your UID and GID on the host so that you have write access to the +# consumption directory. +USERMAP_UID=1036 +USERMAP_GID=65538 + +# See the documentation linked above for all options. A few commonly adjusted settings +# are provided below. + +# This is required if you will be exposing Paperless-ngx on a public domain +# (if doing so please consider security measures such as reverse proxy) +#PAPERLESS_URL=https://paperless.example.com + +# Adjust this key if you plan to make paperless available publicly. It should +# be a very long sequence of random characters. You don't need to remember it. +PAPERLESS_SECRET_KEY=CHzeaKbF7ZRpkaQT2rnVZUPpBF7KpUQiymVOuVLtdGACUS1h + +# Use this variable to set a timezone for the Paperless Docker containers. Defaults to UTC. +PAPERLESS_TIME_ZONE=America/Toronto + +# The default language to use for OCR. Set this to the language most of your +# documents are written in. +PAPERLESS_OCR_LANGUAGE=eng + +# Additional languages to install for text recognition, separated by a whitespace. +# Note that this is different from PAPERLESS_OCR_LANGUAGE (default=eng), which defines +# the language used for OCR. +# The container installs English, German, Italian, Spanish and French by default. +# See https://packages.debian.org/search?keywords=tesseract-ocr-&searchon=names +# for available languages. +#PAPERLESS_OCR_LANGUAGES=tur ces + +PAPERLESS_ADMIN_USER=admin +PAPERLESS_ADMIN_PASSWORD=2pplPtn! + +PAPERLESS_FILENAME_FORMAT=personal/{{ created_year }}/{{ correspondent }}/{{ original_name }} diff --git a/paperless/docker-compose.portainer.yml b/paperless/docker-compose.portainer.yml new file mode 100644 index 0000000..47696a1 --- /dev/null +++ b/paperless/docker-compose.portainer.yml @@ -0,0 +1,73 @@ +# Docker Compose file for running paperless from the Docker Hub. +# This file contains everything paperless needs to run. +# Paperless supports amd64, arm and arm64 hardware. +# +# All compose files of paperless configure paperless in the following way: +# +# - Paperless is (re)started on system boot, if it was running before shutdown. +# - Docker volumes for storing data are managed by Docker. +# - Folders for importing and exporting files are created in the same directory +# as this file and mounted to the correct folders inside the container. +# - Paperless listens on port 8010. +# +# In addition to that, this Docker Compose file adds the following optional +# configurations: +# +# - Instead of SQLite (default), PostgreSQL is used as the database server. +# +# To install and update paperless with this file, do the following: +# +# - Open portainer Stacks list and click 'Add stack' +# - Paste the contents of this file and assign a name, e.g. 'paperless' +# - Upload 'docker-compose.env' by clicking on 'Load variables from .env file' +# - Modify the environment variables as needed +# - Click 'Deploy the stack' and wait for it to be deployed +# +# For more extensive installation and update instructions, refer to the +# documentation. +services: + broker: + image: docker.io/library/redis:8 + restart: unless-stopped + volumes: + - /volume1/docker/paperless/redisdata:/data + networks: + - backend-net + webserver: + image: ghcr.io/paperless-ngx/paperless-ngx:latest + restart: unless-stopped + depends_on: + - broker + ports: + - "8010:8000" + volumes: + - /volume1/docker/paperless/data:/usr/src/paperless/data + - /volume1/docker/paperless/media:/usr/src/paperless/media + - /volume1/docker/paperless/export:/usr/src/paperless/export + - /volume1/docker/paperless/consume:/usr/src/paperless/consume + environment: + PAPERLESS_REDIS: redis://broker:6379 + PAPERLESS_DBENGINE: postgres + PAPERLESS_DBHOST: postgres + PAPERLESS_DBPORT: 5432 + PAPERLESS_DBNAME: paperless + PAPERLESS_DBUSER: paperless + PAPERLESS_DBPASS: kH8rwrUREJmjOBSb9uV0yXXhCRM9pQxdSk0TOZ8yi0oZTaPZ + CSRF_TRUSTED_ORIGINS: https://paperless.chengs.uk + + + env_file: + - stack.env + networks: + - frontend-net + - backend-net + healthcheck: + test: ["CMD-SHELL", "curl -f http://localhost:8000 || exit 1"] + interval: 30s + timeout: 5s + retries: 5 +networks: + frontend-net: + external: true + backend-net: + external: true diff --git a/paperless/postgres.sql b/paperless/postgres.sql new file mode 100644 index 0000000..cc9ec0b --- /dev/null +++ b/paperless/postgres.sql @@ -0,0 +1,9 @@ +psql -U pgadm homelab + + +CREATE DATABASE paperless; +CREATE USER paperless with PASSWORD 'kH8rwrUREJmjOBSb9uV0yXXhCRM9pQxdSk0TOZ8yi0oZTaPZ'; +GRANT ALL PRIVILEGES ON DATABASE paperless TO paperless; + +\c paperless +GRANT ALL ON SCHEMA public TO paperless; diff --git a/vert/docker-compose.portainer.yml b/vert/docker-compose.portainer.yml new file mode 100644 index 0000000..6ee3b81 --- /dev/null +++ b/vert/docker-compose.portainer.yml @@ -0,0 +1,11 @@ +services: + vert: + container_name: vert + image: ghcr.io/vert-sh/vert:latest + restart: unless-stopped + ports: + - 3002:80 + environment: + - USER_UID=1039 + - USER_GID=65538 + - TZ=America/Toronto \ No newline at end of file