From 6c487ae4a9013922c418d53291a196c7e07cebe8 Mon Sep 17 00:00:00 2001 From: Dan Pastori Date: Fri, 17 Oct 2025 09:53:03 -0500 Subject: [PATCH 001/170] Initial commit with new theme, updated nuxt, updated content, nuxt UI --- .gitignore | 3 +- docs/.env.example | 11 +- docs/.gitignore | 27 +- docs/.npmrc | 1 - docs/.nvmrc | 1 - docs/README.md | 47 +- docs/app/app.config.ts | 123 + docs/app/app.vue | 59 + docs/app/assets/css/main.css | 26 + docs/app/components/AppFooter.vue | 23 + docs/app/components/AppHeader.vue | 66 + docs/app/components/AppLogo.vue | 40 + .../content => app/components}/Badges.vue | 2 +- docs/app/components/HeroVideo.vue | 15 + docs/app/components/OgImage/OgImageDocs.vue | 76 + docs/app/components/PageHeaderLinks.vue | 84 + docs/app/components/TemplateMenu.vue | 49 + docs/app/components/content/StarsBg.vue | 183 + docs/app/error.vue | 42 + docs/app/layouts/docs.vue | 22 + docs/app/pages/[...slug].vue | 115 + docs/app/pages/index.vue | 29 + docs/assets/css/animations.css | 69 - docs/assets/css/docsearch.css | 49 - docs/assets/css/hamburger.css | 82 - docs/assets/css/tailwind.css | 10 - docs/components/Docs/Anchor.vue | 23 - docs/components/Docs/Eyebrow.vue | 18 - docs/components/Docs/Footer.vue | 21 - docs/components/Docs/Header.vue | 63 - docs/components/Docs/Logo.vue | 11 - docs/components/Docs/ModeToggle.vue | 18 - docs/components/Docs/Navigation.vue | 56 - docs/components/Docs/NavigationGroup.vue | 58 - docs/components/Docs/PageLink.vue | 32 - docs/components/Docs/Search.vue | 17 - docs/components/Docs/SmallPrint.vue | 26 - docs/components/Docs/Tag.vue | 55 - docs/components/Docs/TopLevelNavItem.vue | 12 - docs/components/DocumentDrivenNotFound.vue | 27 - docs/components/Global/MobileMenu.vue | 133 - docs/components/Global/OgImage/DocsImage.vue | 35 - docs/components/Global/ServerSideUp.vue | 232 - docs/components/Icons/Anchor.vue | 9 - docs/components/Icons/Arrow.vue | 20 - docs/components/Icons/ChatBubbleIcon.vue | 16 - docs/components/Icons/Check.vue | 12 - docs/components/Icons/CheckIcon.vue | 18 - docs/components/Icons/ClipboardIcon.vue | 13 - docs/components/Icons/EnvelopeIcon.vue | 14 - docs/components/Icons/Moon.vue | 5 - docs/components/Icons/Resource.vue | 9 - docs/components/Icons/Search.vue | 8 - docs/components/Icons/Social/Discord.vue | 5 - docs/components/Icons/Social/GitHub.vue | 8 - docs/components/Icons/Social/Twitter.vue | 5 - docs/components/Icons/Sun.vue | 8 - docs/components/Icons/UserIcon.vue | 19 - docs/components/Icons/UsersIcon.vue | 25 - docs/components/content/About.vue | 26 - docs/components/content/AppButton.vue | 45 - docs/components/content/AppHeading2.vue | 42 - docs/components/content/AppHeading3.vue | 16 - docs/components/content/AppHeading4.vue | 16 - docs/components/content/AppLink.vue | 46 - .../components/content/Code/ClipboardIcon.vue | 12 - docs/components/content/Code/CopyButton.vue | 52 - docs/components/content/Code/PanelHeader.vue | 22 - docs/components/content/CodeGroup.vue | 105 - docs/components/content/CodePanel.vue | 31 - docs/components/content/Column.vue | 16 - docs/components/content/DiscordIcon.vue | 5 - docs/components/content/DocsIcon.vue | 5 - docs/components/content/Features.vue | 49 - docs/components/content/GitHubIcon.vue | 5 - docs/components/content/GridPattern.vue | 39 - docs/components/content/Guide.vue | 19 - docs/components/content/Guides.vue | 35 - docs/components/content/HeartIcon.vue | 5 - docs/components/content/HeroPattern.vue | 30 - docs/components/content/InfoIcon.vue | 12 - docs/components/content/LandingSignup.vue | 41 - docs/components/content/LeadP.vue | 7 - docs/components/content/Libraries.vue | 65 - .../components/content/MarketingDevToProd.vue | 26 - .../content/MarketingFollowAlong.vue | 76 - docs/components/content/MarketingGrid.vue | 55 - docs/components/content/MarketingHeader.vue | 148 - docs/components/content/MarketingHero.vue | 17 - .../components/content/MarketingOptimized.vue | 17 - .../content/MarketingTestimonials.vue | 39 - docs/components/content/NotProse.vue | 5 - docs/components/content/Note.vue | 8 - docs/components/content/Orchestrators.vue | 75 - docs/components/content/Properties.vue | 9 - docs/components/content/Property.vue | 20 - docs/components/content/Resources.vue | 67 - docs/components/content/Resources/Pattern.vue | 37 - .../components/content/Resources/Resource.vue | 38 - .../content/Resources/ResourceIcon.vue | 12 - docs/components/content/Row.vue | 5 - docs/components/content/Search.vue | 215 - docs/components/content/VideoEmbed.vue | 21 - docs/composables/states.ts | 1 - docs/content.config.ts | 25 + .../content/1.getting-started/.navigation.yml | 2 + docs/content/1.getting-started/1.index.md | 137 + .../2.these-images-vs-others.md} | 9 +- .../3.installation.md} | 126 +- docs/content/1.getting-started/3.usage.md | 113 + docs/content/2.essentials/.navigation.yml | 1 + .../content/2.essentials/1.markdown-syntax.md | 230 + docs/content/2.essentials/2.code-blocks.md | 456 + .../2.essentials/3.prose-components.md | 481 + docs/content/2.essentials/4.images-embeds.md | 57 + .../3.default-configurations.md | 115 - .../docs/1.getting-started/3.upgrade-guide.md | 59 - .../1.getting-started/4.choosing-a-host.md | 27 - .../docs/1.getting-started/5.changelog.md | 11 - .../content/docs/1.getting-started/6.about.md | 55 - .../docs/1.getting-started/7.contributing.md | 161 - docs/content/docs/1.index.md | 26 - .../docs/3.laravel/1.laravel-automations.md | 135 - .../3.laravel/2.laravel-task-scheduler.md | 119 - .../content/docs/3.laravel/3.laravel-queue.md | 55 - .../docs/3.laravel/4.laravel-horizon.md | 58 - .../docs/3.laravel/4.laravel-reverb.md | 78 - .../1.migrating-from-official-php-images.md | 28 - .../4.guide/100.migrating-from-v2-to-v3.md | 184 - .../2.understanding-file-permissions.md | 116 - .../docs/4.guide/2.using-s6-overlay.md | 96 - .../3.using-healthchecks-with-laravel.md | 121 - .../4.guide/4.using-wordpress-with-docker.md | 63 - .../1.changing-common-php-settings.md | 92 - .../2.installing-additional-php-extensions.md | 197 - .../3.adding-your-own-start-up-scripts.md | 168 - .../4.configuring-ssl.md | 100 - .../1.environment-variable-specification.md | 118 - .../docs/7.reference/2.command-reference.md | 115 - docs/content/index.md | 196 +- docs/eslint.config.mjs | 6 + docs/layouts/docs.vue | 77 - docs/layouts/marketing.vue | 67 - docs/middleware/directory.ts | 15 - docs/nuxt.config.ts | 118 +- docs/package.json | 47 +- docs/public/favicon.ico | Bin 0 -> 4286 bytes docs/public/images/docs/container-init.svg | 79 - docs/public/images/docs/docker-layers.png | Bin 76743 -> 0 bytes .../images/docs/permissions-privileged.png | Bin 84041 -> 0 bytes docs/public/images/docs/reverse-proxy.svg | 126 - .../images/docs/s6-overlay-container.svg | 72 - .../images/docs/supervisor-container.svg | 73 - docs/public/images/docs/watch-repo.png | Bin 22787 -> 0 bytes .../images/favicon/android-chrome-192x192.png | Bin 3458 -> 0 bytes .../images/favicon/android-chrome-512x512.png | Bin 11483 -> 0 bytes .../images/favicon/apple-touch-icon.png | Bin 2223 -> 0 bytes docs/public/images/favicon/browserconfig.xml | 9 - docs/public/images/favicon/favicon-16x16.png | Bin 883 -> 0 bytes docs/public/images/favicon/favicon-32x32.png | Bin 1107 -> 0 bytes docs/public/images/favicon/favicon.ico | Bin 15086 -> 0 bytes docs/public/images/favicon/mstile-150x150.png | Bin 2184 -> 0 bytes .../images/favicon/safari-pinned-tab.svg | 24 - docs/public/images/favicon/site.webmanifest | 19 - .../public/images/icons/cloudflare-square.svg | 6 - docs/public/images/icons/community-icon.svg | 3 - docs/public/images/icons/docs-icon.svg | 3 - docs/public/images/icons/heart-square.svg | 4 - docs/public/images/icons/heart.svg | 3 - docs/public/images/icons/heartbeat-square.svg | 4 - docs/public/images/icons/lightning-square.svg | 4 - docs/public/images/icons/logging-square.svg | 4 - docs/public/images/icons/nginx-square.svg | 5 - docs/public/images/icons/php-square.svg | 7 - docs/public/images/icons/rocket-square.svg | 4 - docs/public/images/icons/search-icon.svg | 3 - docs/public/images/icons/shield-square.svg | 4 - docs/public/images/icons/stars-square.svg | 4 - docs/public/images/logos/amplitude.svg | 21 - docs/public/images/logos/discord-slate.svg | 3 - docs/public/images/logos/discord-white.svg | 3 - docs/public/images/logos/docker.svg | 19 - docs/public/images/logos/github-slate.svg | 3 - docs/public/images/logos/github-white.svg | 3 - docs/public/images/logos/go.svg | 14 - docs/public/images/logos/kubernetes.svg | 11 - docs/public/images/logos/node.svg | 4 - docs/public/images/logos/nomad.svg | 10 - docs/public/images/logos/og-logo.png | Bin 5098 -> 0 bytes docs/public/images/logos/og-ssu-logo.png | Bin 3732 -> 0 bytes docs/public/images/logos/php.svg | 10 - docs/public/images/logos/python.svg | 13 - docs/public/images/logos/ruby.svg | 4 - .../images/logos/server-side-up-footer.svg | 6 - .../logos/server-side-up-logo-horizontal.svg | 6 - docs/public/images/logos/twitter-slate.svg | 3 - docs/public/images/logos/twitter-white.svg | 3 - docs/public/images/logos/x-logo.svg | 3 - .../images/{logos => }/php-docker-logo.svg | 0 docs/public/images/placeholder-hero-video.png | Bin 141372 -> 0 bytes .../images/placeholder-optimized-video.png | Bin 76505 -> 0 bytes docs/public/images/social-image.jpg | Bin 229668 -> 0 bytes .../images/testimonials/chris-fidao.png | Bin 39044 -> 0 bytes .../images/testimonials/johan-janssens.png | Bin 36857 -> 0 bytes docs/public/images/testimonials/ziga-zajc.png | Bin 26483 -> 0 bytes docs/renovate.json | 13 + docs/server/api/search.json.get.ts | 5 - docs/server/routes/raw/[...slug].md.get.ts | 27 + docs/server/routes/sitemap.xml.ts | 20 - docs/tailwind.config.js | 60 - docs/typography.js | 360 - docs/yarn.lock | 11690 ++++++++-------- 212 files changed, 9002 insertions(+), 12154 deletions(-) delete mode 100644 docs/.nvmrc create mode 100644 docs/app/app.config.ts create mode 100644 docs/app/app.vue create mode 100644 docs/app/assets/css/main.css create mode 100644 docs/app/components/AppFooter.vue create mode 100644 docs/app/components/AppHeader.vue create mode 100644 docs/app/components/AppLogo.vue rename docs/{components/content => app/components}/Badges.vue (92%) create mode 100644 docs/app/components/HeroVideo.vue create mode 100644 docs/app/components/OgImage/OgImageDocs.vue create mode 100644 docs/app/components/PageHeaderLinks.vue create mode 100644 docs/app/components/TemplateMenu.vue create mode 100644 docs/app/components/content/StarsBg.vue create mode 100644 docs/app/error.vue create mode 100644 docs/app/layouts/docs.vue create mode 100644 docs/app/pages/[...slug].vue create mode 100644 docs/app/pages/index.vue delete mode 100644 docs/assets/css/animations.css delete mode 100644 docs/assets/css/docsearch.css delete mode 100644 docs/assets/css/hamburger.css delete mode 100644 docs/assets/css/tailwind.css delete mode 100644 docs/components/Docs/Anchor.vue delete mode 100644 docs/components/Docs/Eyebrow.vue delete mode 100644 docs/components/Docs/Footer.vue delete mode 100644 docs/components/Docs/Header.vue delete mode 100644 docs/components/Docs/Logo.vue delete mode 100644 docs/components/Docs/ModeToggle.vue delete mode 100644 docs/components/Docs/Navigation.vue delete mode 100644 docs/components/Docs/NavigationGroup.vue delete mode 100644 docs/components/Docs/PageLink.vue delete mode 100644 docs/components/Docs/Search.vue delete mode 100644 docs/components/Docs/SmallPrint.vue delete mode 100644 docs/components/Docs/Tag.vue delete mode 100644 docs/components/Docs/TopLevelNavItem.vue delete mode 100644 docs/components/DocumentDrivenNotFound.vue delete mode 100644 docs/components/Global/MobileMenu.vue delete mode 100644 docs/components/Global/OgImage/DocsImage.vue delete mode 100644 docs/components/Global/ServerSideUp.vue delete mode 100644 docs/components/Icons/Anchor.vue delete mode 100644 docs/components/Icons/Arrow.vue delete mode 100644 docs/components/Icons/ChatBubbleIcon.vue delete mode 100644 docs/components/Icons/Check.vue delete mode 100644 docs/components/Icons/CheckIcon.vue delete mode 100644 docs/components/Icons/ClipboardIcon.vue delete mode 100644 docs/components/Icons/EnvelopeIcon.vue delete mode 100644 docs/components/Icons/Moon.vue delete mode 100644 docs/components/Icons/Resource.vue delete mode 100644 docs/components/Icons/Search.vue delete mode 100644 docs/components/Icons/Social/Discord.vue delete mode 100644 docs/components/Icons/Social/GitHub.vue delete mode 100644 docs/components/Icons/Social/Twitter.vue delete mode 100644 docs/components/Icons/Sun.vue delete mode 100644 docs/components/Icons/UserIcon.vue delete mode 100644 docs/components/Icons/UsersIcon.vue delete mode 100644 docs/components/content/About.vue delete mode 100644 docs/components/content/AppButton.vue delete mode 100644 docs/components/content/AppHeading2.vue delete mode 100644 docs/components/content/AppHeading3.vue delete mode 100644 docs/components/content/AppHeading4.vue delete mode 100644 docs/components/content/AppLink.vue delete mode 100644 docs/components/content/Code/ClipboardIcon.vue delete mode 100644 docs/components/content/Code/CopyButton.vue delete mode 100644 docs/components/content/Code/PanelHeader.vue delete mode 100644 docs/components/content/CodeGroup.vue delete mode 100644 docs/components/content/CodePanel.vue delete mode 100644 docs/components/content/Column.vue delete mode 100644 docs/components/content/DiscordIcon.vue delete mode 100644 docs/components/content/DocsIcon.vue delete mode 100644 docs/components/content/Features.vue delete mode 100644 docs/components/content/GitHubIcon.vue delete mode 100644 docs/components/content/GridPattern.vue delete mode 100644 docs/components/content/Guide.vue delete mode 100644 docs/components/content/Guides.vue delete mode 100644 docs/components/content/HeartIcon.vue delete mode 100644 docs/components/content/HeroPattern.vue delete mode 100644 docs/components/content/InfoIcon.vue delete mode 100644 docs/components/content/LandingSignup.vue delete mode 100644 docs/components/content/LeadP.vue delete mode 100644 docs/components/content/Libraries.vue delete mode 100644 docs/components/content/MarketingDevToProd.vue delete mode 100644 docs/components/content/MarketingFollowAlong.vue delete mode 100644 docs/components/content/MarketingGrid.vue delete mode 100644 docs/components/content/MarketingHeader.vue delete mode 100644 docs/components/content/MarketingHero.vue delete mode 100644 docs/components/content/MarketingOptimized.vue delete mode 100644 docs/components/content/MarketingTestimonials.vue delete mode 100644 docs/components/content/NotProse.vue delete mode 100644 docs/components/content/Note.vue delete mode 100644 docs/components/content/Orchestrators.vue delete mode 100644 docs/components/content/Properties.vue delete mode 100644 docs/components/content/Property.vue delete mode 100644 docs/components/content/Resources.vue delete mode 100644 docs/components/content/Resources/Pattern.vue delete mode 100644 docs/components/content/Resources/Resource.vue delete mode 100644 docs/components/content/Resources/ResourceIcon.vue delete mode 100644 docs/components/content/Row.vue delete mode 100644 docs/components/content/Search.vue delete mode 100644 docs/components/content/VideoEmbed.vue delete mode 100644 docs/composables/states.ts create mode 100644 docs/content.config.ts create mode 100644 docs/content/1.getting-started/.navigation.yml create mode 100644 docs/content/1.getting-started/1.index.md rename docs/content/{docs/1.getting-started/1.these-images-vs-others.md => 1.getting-started/2.these-images-vs-others.md} (95%) rename docs/content/{docs/1.getting-started/2.installation.md => 1.getting-started/3.installation.md} (79%) create mode 100644 docs/content/1.getting-started/3.usage.md create mode 100644 docs/content/2.essentials/.navigation.yml create mode 100644 docs/content/2.essentials/1.markdown-syntax.md create mode 100644 docs/content/2.essentials/2.code-blocks.md create mode 100644 docs/content/2.essentials/3.prose-components.md create mode 100644 docs/content/2.essentials/4.images-embeds.md delete mode 100644 docs/content/docs/1.getting-started/3.default-configurations.md delete mode 100644 docs/content/docs/1.getting-started/3.upgrade-guide.md delete mode 100644 docs/content/docs/1.getting-started/4.choosing-a-host.md delete mode 100644 docs/content/docs/1.getting-started/5.changelog.md delete mode 100644 docs/content/docs/1.getting-started/6.about.md delete mode 100644 docs/content/docs/1.getting-started/7.contributing.md delete mode 100644 docs/content/docs/1.index.md delete mode 100644 docs/content/docs/3.laravel/1.laravel-automations.md delete mode 100644 docs/content/docs/3.laravel/2.laravel-task-scheduler.md delete mode 100644 docs/content/docs/3.laravel/3.laravel-queue.md delete mode 100644 docs/content/docs/3.laravel/4.laravel-horizon.md delete mode 100644 docs/content/docs/3.laravel/4.laravel-reverb.md delete mode 100644 docs/content/docs/4.guide/1.migrating-from-official-php-images.md delete mode 100644 docs/content/docs/4.guide/100.migrating-from-v2-to-v3.md delete mode 100644 docs/content/docs/4.guide/2.understanding-file-permissions.md delete mode 100644 docs/content/docs/4.guide/2.using-s6-overlay.md delete mode 100644 docs/content/docs/4.guide/3.using-healthchecks-with-laravel.md delete mode 100644 docs/content/docs/4.guide/4.using-wordpress-with-docker.md delete mode 100644 docs/content/docs/5.customizing-the-image/1.changing-common-php-settings.md delete mode 100644 docs/content/docs/5.customizing-the-image/2.installing-additional-php-extensions.md delete mode 100644 docs/content/docs/5.customizing-the-image/3.adding-your-own-start-up-scripts.md delete mode 100644 docs/content/docs/5.customizing-the-image/4.configuring-ssl.md delete mode 100644 docs/content/docs/7.reference/1.environment-variable-specification.md delete mode 100644 docs/content/docs/7.reference/2.command-reference.md create mode 100644 docs/eslint.config.mjs delete mode 100644 docs/layouts/docs.vue delete mode 100644 docs/layouts/marketing.vue delete mode 100644 docs/middleware/directory.ts create mode 100644 docs/public/favicon.ico delete mode 100644 docs/public/images/docs/container-init.svg delete mode 100644 docs/public/images/docs/docker-layers.png delete mode 100644 docs/public/images/docs/permissions-privileged.png delete mode 100644 docs/public/images/docs/reverse-proxy.svg delete mode 100644 docs/public/images/docs/s6-overlay-container.svg delete mode 100644 docs/public/images/docs/supervisor-container.svg delete mode 100644 docs/public/images/docs/watch-repo.png delete mode 100644 docs/public/images/favicon/android-chrome-192x192.png delete mode 100644 docs/public/images/favicon/android-chrome-512x512.png delete mode 100644 docs/public/images/favicon/apple-touch-icon.png delete mode 100644 docs/public/images/favicon/browserconfig.xml delete mode 100644 docs/public/images/favicon/favicon-16x16.png delete mode 100644 docs/public/images/favicon/favicon-32x32.png delete mode 100644 docs/public/images/favicon/favicon.ico delete mode 100644 docs/public/images/favicon/mstile-150x150.png delete mode 100644 docs/public/images/favicon/safari-pinned-tab.svg delete mode 100644 docs/public/images/favicon/site.webmanifest delete mode 100644 docs/public/images/icons/cloudflare-square.svg delete mode 100644 docs/public/images/icons/community-icon.svg delete mode 100644 docs/public/images/icons/docs-icon.svg delete mode 100644 docs/public/images/icons/heart-square.svg delete mode 100644 docs/public/images/icons/heart.svg delete mode 100644 docs/public/images/icons/heartbeat-square.svg delete mode 100644 docs/public/images/icons/lightning-square.svg delete mode 100644 docs/public/images/icons/logging-square.svg delete mode 100644 docs/public/images/icons/nginx-square.svg delete mode 100644 docs/public/images/icons/php-square.svg delete mode 100644 docs/public/images/icons/rocket-square.svg delete mode 100644 docs/public/images/icons/search-icon.svg delete mode 100644 docs/public/images/icons/shield-square.svg delete mode 100644 docs/public/images/icons/stars-square.svg delete mode 100644 docs/public/images/logos/amplitude.svg delete mode 100644 docs/public/images/logos/discord-slate.svg delete mode 100644 docs/public/images/logos/discord-white.svg delete mode 100644 docs/public/images/logos/docker.svg delete mode 100644 docs/public/images/logos/github-slate.svg delete mode 100644 docs/public/images/logos/github-white.svg delete mode 100644 docs/public/images/logos/go.svg delete mode 100644 docs/public/images/logos/kubernetes.svg delete mode 100644 docs/public/images/logos/node.svg delete mode 100644 docs/public/images/logos/nomad.svg delete mode 100644 docs/public/images/logos/og-logo.png delete mode 100644 docs/public/images/logos/og-ssu-logo.png delete mode 100644 docs/public/images/logos/php.svg delete mode 100644 docs/public/images/logos/python.svg delete mode 100644 docs/public/images/logos/ruby.svg delete mode 100644 docs/public/images/logos/server-side-up-footer.svg delete mode 100644 docs/public/images/logos/server-side-up-logo-horizontal.svg delete mode 100644 docs/public/images/logos/twitter-slate.svg delete mode 100644 docs/public/images/logos/twitter-white.svg delete mode 100644 docs/public/images/logos/x-logo.svg rename docs/public/images/{logos => }/php-docker-logo.svg (100%) delete mode 100644 docs/public/images/placeholder-hero-video.png delete mode 100644 docs/public/images/placeholder-optimized-video.png delete mode 100644 docs/public/images/social-image.jpg delete mode 100644 docs/public/images/testimonials/chris-fidao.png delete mode 100644 docs/public/images/testimonials/johan-janssens.png delete mode 100644 docs/public/images/testimonials/ziga-zajc.png create mode 100644 docs/renovate.json delete mode 100644 docs/server/api/search.json.get.ts create mode 100644 docs/server/routes/raw/[...slug].md.get.ts delete mode 100644 docs/server/routes/sitemap.xml.ts delete mode 100644 docs/tailwind.config.js delete mode 100644 docs/typography.js diff --git a/.gitignore b/.gitignore index cbc1be6a1..c3f34b862 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ package.json yarn.lock node_modules php-versions.yml -*.tmp \ No newline at end of file +*.tmp +/docs/_OLD_ \ No newline at end of file diff --git a/docs/.env.example b/docs/.env.example index c47b2b615..e90e45a54 100644 --- a/docs/.env.example +++ b/docs/.env.example @@ -1,3 +1,10 @@ +# Used for Nuxt SEO +NUXT_SITE_URL=https://example.com +NUXT_SITE_NAME=My Awesome Website +NUXT_SITE_ENV="development" + +# Used for +PLAUSIBLE_ENABLED=false +BASE_PATH=http://localhost:3000/open-source/docker-php NUXT_APP_BASE_URL=/open-source/docker-php -TOP_LEVEL_DOMAIN=http://localhost:3000 -BASE_PATH=http://localhost:3000/open-source/docker-php \ No newline at end of file +TOP_LEVEL_DOMAIN=http://localhost:3000 \ No newline at end of file diff --git a/docs/.gitignore b/docs/.gitignore index 438cb0860..6bbb425a0 100644 --- a/docs/.gitignore +++ b/docs/.gitignore @@ -1,8 +1,27 @@ -node_modules -*.log* +# Nuxt dev/build outputs +.output +.data .nuxt .nitro .cache -.output -.env dist + +# Node dependencies +node_modules + +# Logs +logs +*.log + +# Misc +.DS_Store +.fleet +.idea + +# Local env files +.env +.env.* +!.env.example + +# VSC +.history diff --git a/docs/.npmrc b/docs/.npmrc index cf0404245..bf2e7648b 100644 --- a/docs/.npmrc +++ b/docs/.npmrc @@ -1,2 +1 @@ shamefully-hoist=true -strict-peer-dependencies=false diff --git a/docs/.nvmrc b/docs/.nvmrc deleted file mode 100644 index 2edeafb09..000000000 --- a/docs/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -20 \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 38d0b403c..0787bb89c 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,35 +1,44 @@ -# Documentation & Static Site, generated with Nuxt Content -This is a documentation site built on top of Nuxt Content (v3). +# Nuxt Docs Template -# Docs location -All docs are located in the [./content](./content/docs) folder if you're just looking for the docs in plain text. +[![Nuxt UI](https://img.shields.io/badge/Made%20with-Nuxt%20UI-00DC82?logo=nuxt&labelColor=020420)](https://ui.nuxt.com) -## Setup +Use this template to build your own documentation with [Nuxt UI](https://ui.nuxt.com) quickly. -Ensure you're in the right directory. +- [Live demo](https://docs-template.nuxt.dev/) +- [Documentation](https://ui.nuxt.com/docs/getting-started/installation) -```bash -cd docs/ -``` + + + + + Nuxt Docs Template + + -Copy over the environment variable example file. +## Quick Start -```bash -cp .env.example .env +```bash [Terminal] +npm create nuxt@latest -- -t github:nuxt-ui-templates/docs ``` +## Deploy your own + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-name=docs&repository-url=https%3A%2F%2Fgithub.com%2Fnuxt-ui-templates%2Fdocs&demo-image=https%3A%2F%2Fui.nuxt.com%2Fassets%2Ftemplates%2Fnuxt%2Fdocs-dark.png&demo-url=https%3A%2F%2Fdocs-template.nuxt.dev%2F&demo-title=Nuxt%20Docs%20Template&demo-description=A%20documentation%20template%20powered%20by%20Nuxt%20Content.) + +## Setup + Make sure to install the dependencies: ```bash -yarn install +pnpm install ``` ## Development Server -Start the development server on http://localhost:3000 +Start the development server on `http://localhost:3000`: ```bash -yarn dev +pnpm dev ``` ## Production @@ -37,13 +46,17 @@ yarn dev Build the application for production: ```bash -yarn build +pnpm build ``` Locally preview production build: ```bash -yarn preview +pnpm preview ``` Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information. + +## Renovate integration + +Install [Renovate GitHub app](https://github.com/apps/renovate/installations/select_target) on your repository and you are good to go. diff --git a/docs/app/app.config.ts b/docs/app/app.config.ts new file mode 100644 index 000000000..77a67a33d --- /dev/null +++ b/docs/app/app.config.ts @@ -0,0 +1,123 @@ +export default defineAppConfig({ + ui: { + colors: { + primary: 'blue', + neutral: 'neutral' + }, + banner: { + slots: { + icon: 'text-white size-5 shrink-0 pointer-events-none', + title: 'text-white font-bold text-sm truncate', + } + }, + mode: 'dark', + header: { + slots: { + right: 'flex items-center justify-end lg:flex-1 gap-3', + }, + }, + footer: { + slots: { + root: 'border-t border-default', + left: 'text-sm text-muted' + } + } + }, + seo: { + siteName: 'Nuxt Docs Template' + }, + header: { + title: 'PHP Docker Images (serversideup/docker-php)', + to: '/', + logo: { + alt: 'PHP Docker Images (serversideup/docker-php)', + light: '/images/php-docker-logo.svg', + dark: '/images/php-docker-logo.svg' + }, + search: true, + links: [{ + 'icon': 'i-lucide-book-open', + 'to': '/getting-started', + 'aria-label': 'Documentation', + 'label': 'Docs', + 'variant': 'ghost', + 'size': 'xl', + 'class': 'font-bold' + },{ + 'icon': 'i-simple-icons-discord', + 'to': 'https://serversideup.net/discord', + 'target': '_blank', + 'aria-label': 'Server Side Up on Discord', + 'label': 'Discord', + 'variant': 'ghost', + 'size': 'xl', + 'class': 'font-bold' + },{ + 'icon': 'i-simple-icons-github', + 'to': 'https://github.com/serversideup/docker-php', + 'target': '_blank', + 'aria-label': 'GitHub', + 'label': 'GitHub', + 'variant': 'ghost', + 'size': 'xl', + 'class': 'font-bold' + },{ + 'trailingIcon': 'i-lucide-heart', + 'label': 'Sponsor', + 'to': 'https://github.com/sponsors/serversideup', + 'target': '_blank', + 'aria-label': 'Sponsor', + 'size': 'xl', + 'variant': 'outline', + 'class': 'font-bold', + + },{ + 'trailingIcon': 'i-lucide-arrow-right', + 'label': 'Get Started', + 'to': '/docs', + 'aria-label': 'Get Started', + 'size': 'xl', + 'variant': 'solid', + 'class': 'font-bold', + 'color': 'primary', + }] + }, + footer: { + credits: `Built with Nuxt UI • © ${new Date().getFullYear()}`, + colorMode: false, + links: [{ + 'icon': 'i-simple-icons-discord', + 'to': 'https://go.nuxt.com/discord', + 'target': '_blank', + 'aria-label': 'Nuxt on Discord' + }, { + 'icon': 'i-simple-icons-x', + 'to': 'https://go.nuxt.com/x', + 'target': '_blank', + 'aria-label': 'Nuxt on X' + }, { + 'icon': 'i-simple-icons-github', + 'to': 'https://github.com/nuxt/ui', + 'target': '_blank', + 'aria-label': 'Nuxt UI on GitHub' + }] + }, + toc: { + title: 'Table of Contents', + bottom: { + title: 'Community', + edit: 'https://github.com/nuxt-ui-templates/docs/edit/main/content', + links: [{ + icon: 'i-lucide-star', + label: 'Star on GitHub', + to: 'https://github.com/nuxt/ui', + target: '_blank' + }, { + icon: 'i-lucide-book-open', + label: 'Nuxt UI docs', + to: 'https://ui.nuxt.com/docs/getting-started/installation/nuxt', + target: '_blank' + }] + } + } +}) diff --git a/docs/app/app.vue b/docs/app/app.vue new file mode 100644 index 000000000..7298d1a67 --- /dev/null +++ b/docs/app/app.vue @@ -0,0 +1,59 @@ + + + diff --git a/docs/app/assets/css/main.css b/docs/app/assets/css/main.css new file mode 100644 index 000000000..76b6d4ec6 --- /dev/null +++ b/docs/app/assets/css/main.css @@ -0,0 +1,26 @@ +@import "tailwindcss"; +@import "@nuxt/ui"; + +@source "../../../content/**/*"; + +@theme static { + --ui-header-height: --spacing(24); + --container-8xl: 90rem; + --font-sans: 'Public Sans', sans-serif; + + --color-green-50: #EFFDF5; + --color-green-100: #D9FBE8; + --color-green-200: #B3F5D1; + --color-green-300: #75EDAE; + --color-green-400: #00DC82; + --color-green-500: #00C16A; + --color-green-600: #00A155; + --color-green-700: #007F45; + --color-green-800: #016538; + --color-green-900: #0A5331; + --color-green-950: #052E16; +} + +:root { + --ui-container: var(--container-8xl); +} diff --git a/docs/app/components/AppFooter.vue b/docs/app/components/AppFooter.vue new file mode 100644 index 000000000..b8859719a --- /dev/null +++ b/docs/app/components/AppFooter.vue @@ -0,0 +1,23 @@ + + + diff --git a/docs/app/components/AppHeader.vue b/docs/app/components/AppHeader.vue new file mode 100644 index 000000000..e99288a52 --- /dev/null +++ b/docs/app/components/AppHeader.vue @@ -0,0 +1,66 @@ + + + \ No newline at end of file diff --git a/docs/app/components/AppLogo.vue b/docs/app/components/AppLogo.vue new file mode 100644 index 000000000..521061f3e --- /dev/null +++ b/docs/app/components/AppLogo.vue @@ -0,0 +1,40 @@ + diff --git a/docs/components/content/Badges.vue b/docs/app/components/Badges.vue similarity index 92% rename from docs/components/content/Badges.vue rename to docs/app/components/Badges.vue index c8fb01105..498535522 100644 --- a/docs/components/content/Badges.vue +++ b/docs/app/components/Badges.vue @@ -1,5 +1,5 @@ \ No newline at end of file From ae84eb4ac24327c694f15b548c06a3355a10592d Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 13:43:06 -0500 Subject: [PATCH 052/170] Add various SVG and PNG logos to documentation for improved visual consistency and branding --- docs/public/images/docs/watch-repo.png | Bin 0 -> 22787 bytes docs/public/images/logos/amplitude.svg | 21 ++++++++++++++++++ docs/public/images/logos/discord-slate.svg | 3 +++ docs/public/images/logos/discord-white.svg | 3 +++ docs/public/images/logos/docker.svg | 19 ++++++++++++++++ docs/public/images/logos/github-slate.svg | 3 +++ docs/public/images/logos/github-white.svg | 3 +++ docs/public/images/logos/go.svg | 14 ++++++++++++ docs/public/images/logos/kubernetes.svg | 11 +++++++++ docs/public/images/logos/node.svg | 4 ++++ docs/public/images/logos/nomad.svg | 10 +++++++++ docs/public/images/logos/og-logo.png | Bin 0 -> 5098 bytes docs/public/images/logos/og-ssu-logo.png | Bin 0 -> 3732 bytes docs/public/images/logos/php-docker-logo.svg | 18 +++++++++++++++ docs/public/images/logos/php.svg | 10 +++++++++ docs/public/images/logos/python.svg | 13 +++++++++++ docs/public/images/logos/ruby.svg | 4 ++++ .../images/logos/server-side-up-footer.svg | 6 +++++ .../logos/server-side-up-logo-horizontal.svg | 6 +++++ docs/public/images/logos/twitter-slate.svg | 3 +++ docs/public/images/logos/twitter-white.svg | 3 +++ docs/public/images/logos/x-logo.svg | 3 +++ 22 files changed, 157 insertions(+) create mode 100644 docs/public/images/docs/watch-repo.png create mode 100644 docs/public/images/logos/amplitude.svg create mode 100644 docs/public/images/logos/discord-slate.svg create mode 100644 docs/public/images/logos/discord-white.svg create mode 100644 docs/public/images/logos/docker.svg create mode 100644 docs/public/images/logos/github-slate.svg create mode 100644 docs/public/images/logos/github-white.svg create mode 100644 docs/public/images/logos/go.svg create mode 100644 docs/public/images/logos/kubernetes.svg create mode 100644 docs/public/images/logos/node.svg create mode 100644 docs/public/images/logos/nomad.svg create mode 100644 docs/public/images/logos/og-logo.png create mode 100644 docs/public/images/logos/og-ssu-logo.png create mode 100644 docs/public/images/logos/php-docker-logo.svg create mode 100644 docs/public/images/logos/php.svg create mode 100644 docs/public/images/logos/python.svg create mode 100644 docs/public/images/logos/ruby.svg create mode 100644 docs/public/images/logos/server-side-up-footer.svg create mode 100644 docs/public/images/logos/server-side-up-logo-horizontal.svg create mode 100644 docs/public/images/logos/twitter-slate.svg create mode 100644 docs/public/images/logos/twitter-white.svg create mode 100644 docs/public/images/logos/x-logo.svg diff --git a/docs/public/images/docs/watch-repo.png b/docs/public/images/docs/watch-repo.png new file mode 100644 index 0000000000000000000000000000000000000000..e10ecef1bd67546fc3b898fd9a2083365291d8af GIT binary patch literal 22787 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 gQ!?;B16oPT; + + + AmplitudeJS + Created with Sketch. + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/public/images/logos/discord-slate.svg b/docs/public/images/logos/discord-slate.svg new file mode 100644 index 000000000..1867bbf5b --- /dev/null +++ b/docs/public/images/logos/discord-slate.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/public/images/logos/discord-white.svg b/docs/public/images/logos/discord-white.svg new file mode 100644 index 000000000..fc83b6d55 --- /dev/null +++ b/docs/public/images/logos/discord-white.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/public/images/logos/docker.svg b/docs/public/images/logos/docker.svg new file mode 100644 index 000000000..fe2d9c43d --- /dev/null +++ b/docs/public/images/logos/docker.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/docs/public/images/logos/github-slate.svg b/docs/public/images/logos/github-slate.svg new file mode 100644 index 000000000..804c8a920 --- /dev/null +++ b/docs/public/images/logos/github-slate.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/public/images/logos/github-white.svg b/docs/public/images/logos/github-white.svg new file mode 100644 index 000000000..aa42ea81e --- /dev/null +++ b/docs/public/images/logos/github-white.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/public/images/logos/go.svg b/docs/public/images/logos/go.svg new file mode 100644 index 000000000..7f7b19de5 --- /dev/null +++ b/docs/public/images/logos/go.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + diff --git a/docs/public/images/logos/kubernetes.svg b/docs/public/images/logos/kubernetes.svg new file mode 100644 index 000000000..70f477d00 --- /dev/null +++ b/docs/public/images/logos/kubernetes.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/docs/public/images/logos/node.svg b/docs/public/images/logos/node.svg new file mode 100644 index 000000000..1d09de22b --- /dev/null +++ b/docs/public/images/logos/node.svg @@ -0,0 +1,4 @@ + + + diff --git a/docs/public/images/logos/nomad.svg b/docs/public/images/logos/nomad.svg new file mode 100644 index 000000000..b4df566c9 --- /dev/null +++ b/docs/public/images/logos/nomad.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/docs/public/images/logos/og-logo.png b/docs/public/images/logos/og-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..07560c116066f96fa4fe58a2c84ec25d44e78829 GIT binary patch literal 5098 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 + + + + + + + + + + + + + + + + + diff --git a/docs/public/images/logos/php.svg b/docs/public/images/logos/php.svg new file mode 100644 index 000000000..0a9ac462a --- /dev/null +++ b/docs/public/images/logos/php.svg @@ -0,0 +1,10 @@ + + + + + diff --git a/docs/public/images/logos/python.svg b/docs/public/images/logos/python.svg new file mode 100644 index 000000000..9bceb587a --- /dev/null +++ b/docs/public/images/logos/python.svg @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/docs/public/images/logos/ruby.svg b/docs/public/images/logos/ruby.svg new file mode 100644 index 000000000..b22a5bf10 --- /dev/null +++ b/docs/public/images/logos/ruby.svg @@ -0,0 +1,4 @@ + + + diff --git a/docs/public/images/logos/server-side-up-footer.svg b/docs/public/images/logos/server-side-up-footer.svg new file mode 100644 index 000000000..13bc7aa54 --- /dev/null +++ b/docs/public/images/logos/server-side-up-footer.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/docs/public/images/logos/server-side-up-logo-horizontal.svg b/docs/public/images/logos/server-side-up-logo-horizontal.svg new file mode 100644 index 000000000..93198355b --- /dev/null +++ b/docs/public/images/logos/server-side-up-logo-horizontal.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/docs/public/images/logos/twitter-slate.svg b/docs/public/images/logos/twitter-slate.svg new file mode 100644 index 000000000..05a4c0db0 --- /dev/null +++ b/docs/public/images/logos/twitter-slate.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/public/images/logos/twitter-white.svg b/docs/public/images/logos/twitter-white.svg new file mode 100644 index 000000000..0c89586ae --- /dev/null +++ b/docs/public/images/logos/twitter-white.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/public/images/logos/x-logo.svg b/docs/public/images/logos/x-logo.svg new file mode 100644 index 000000000..437e2bfdd --- /dev/null +++ b/docs/public/images/logos/x-logo.svg @@ -0,0 +1,3 @@ + + + From a9c97a2db1dfebe7c83dae805460a43a1bc3c700 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 13:44:28 -0500 Subject: [PATCH 053/170] Enhance documentation for PHP Docker images by adding notes on unprivileged user defaults and environment variable configuration. Include warnings about using supervisor and promote S6 Overlay for process management, improving clarity and user guidance. --- .../2.these-images-vs-others.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/docs/content/docs/1.getting-started/2.these-images-vs-others.md b/docs/content/docs/1.getting-started/2.these-images-vs-others.md index 6ae6af9c8..6793a4ba0 100644 --- a/docs/content/docs/1.getting-started/2.these-images-vs-others.md +++ b/docs/content/docs/1.getting-started/2.these-images-vs-others.md @@ -23,14 +23,23 @@ description: 'Learn the important differences between serversideup/php and other | Native health checks | ❌ | ✅ | ## Unprivileged by Default +::note +Running containers as `root` in the open internet is very dangerous. This is why we run our images as `www-data` by default. +:: + We believe in the principle of least privilege. Our images run as an unprivileged user by default. This means that if your application is compromised, the attacker will have a harder time escalating their privileges to the root user. Running unprivileged images also improves compatibility of running your containers in a Kubernetes environment, where running as root is not allowed. ## Variable-first Configuration +::tip +Setting environment variables saves a ton of headache when customizing your container. View our [environment variable specification](/docs/reference/environment-variable-specification) for all the available variables. +:: + Our design philosophy is built all around simplicity. The process of customizing the behavior of PHP is as simple as setting an environment variable. We took every common configuration option and set it up so you can change these values in a simple method, defaulting every single option to production-ready values. - +::u-button{to="/docs/reference/environment-variable-specification" label="Learn more about environment variables" aria-label="Learn more about environment variables" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} +:: ## Optimized for Laravel & WordPress We did the hard work of customizing the official PHP image and giving you everything to get started with running PHP's most popular frameworks in seconds. We also hardened the images to help protect your PHP application from common attacks. @@ -39,6 +48,10 @@ We did the hard work of customizing the official PHP image and giving you everyt We believe images should be ready for production and able to live in the open and wild Internet. We took our years of experience and tweaked these images to be performant and secure as possible. Having these values published online allows others to review, contribute, and improve the images -- giving you the best security and performance possible. ## What is "S6 Overlay?" -[S6 Overlay](https://github.com/just-containers/s6-overlay) is a process supervisor designed for containerization from the ground up. It's a modern alternative to [Supervisor (aka Supervisord)](https://supervisord.org/). We only use this in our `serversideup/php:*-fpm-apache` and `serversideup/php:*-fpm-nginx` images, as they require two processes to run a service. +::warning +Using **supervisor** to monitor multiple processes in a single container may lead to unintended consequences. This is why we use [S6 Overlay](/docs/guides/using-s6-overlay) to monitor multiple processes in a single container. +:: + +[S6 Overlay](https://github.com/just-containers/s6-overlay){target="_blank"} is a process supervisor designed for containerization from the ground up. It's a modern alternative to [Supervisor (aka Supervisord)](https://supervisord.org/){target="_blank"}. We only use this in our `serversideup/php:*-fpm-apache` and `serversideup/php:*-fpm-nginx` images, as they require two processes to run a service. - \ No newline at end of file +::u-button{to="/docs/guides/using-s6-overlay" label="Learn more about S6 Overlay" aria-label="Learn more about S6 Overlay" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file From 029b69f8c5b59d66d29b9998ec034914cb5d88ef Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 13:44:46 -0500 Subject: [PATCH 054/170] Update installation documentation to replace references from 'Container Concepts' to 'Container Basics' for improved accuracy and user guidance. --- docs/content/docs/1.getting-started/3.installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/docs/1.getting-started/3.installation.md b/docs/content/docs/1.getting-started/3.installation.md index 2d117f270..d91228c3c 100644 --- a/docs/content/docs/1.getting-started/3.installation.md +++ b/docs/content/docs/1.getting-started/3.installation.md @@ -12,7 +12,7 @@ title: Installation ## Understanding containers and Docker ::tip -New to containers? Check out our [Container Concepts guide](/docs/deployment-and-production/container-concepts) for a beginner-friendly introduction to Docker and containerization. +New to containers? Check out our [Container Basics guide](/docs/deployment-and-production/container-basics) for a beginner-friendly introduction to Docker and containerization. :: If you're new to Docker or containers, you might be wondering why you should containerize your application in the first place. The short answer: **containers let you run your application anywhere** — from your laptop to any cloud provider — with zero changes. @@ -34,7 +34,7 @@ There are some important terms to understand when working with containers: If you'd like to learn more about containers, you can learn more following the guide below. -::u-button{to="/docs/deployment-and-production/container-concepts" label="Learn More About Containers" aria-label="Learn More About Containers" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} +::u-button{to="/docs/deployment-and-production/container-basics" label="Learn More About Containers" aria-label="Learn More About Containers" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} :: ## Quick Start From b9990df1fc4d6981daaf9f0e36eeedaa561c826a Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 13:49:11 -0500 Subject: [PATCH 055/170] Refactor button syntax in getting started documentation for consistency and clarity, ensuring a cleaner presentation of links to advantages and installation instructions. --- docs/content/docs/1.getting-started/1.index.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/content/docs/1.getting-started/1.index.md b/docs/content/docs/1.getting-started/1.index.md index c2d3bb6b8..4954cf9d7 100644 --- a/docs/content/docs/1.getting-started/1.index.md +++ b/docs/content/docs/1.getting-started/1.index.md @@ -128,12 +128,10 @@ src: https://docker-php-public-assets.serversideup.net/docker-demo.mp4 This is just an overview. See the full list of benefits and features below. -::u-button{to="/docs/getting-started/these-images-vs-others" label="Read more about the advantages" aria-label="Read more about the advantages" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} -:: +:u-button{to="/docs/getting-started/these-images-vs-others" label="Read more about the advantages" aria-label="Read more about the advantages" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} ## Why should I use these PHP Docker Images? These images are production-ready and optimized for performance and security. We work hard to give you a "batteries included" experience so you can ship PHP with Docker as fast as possible. Click below to see a simple working example. -::u-button{to="/docs/getting-started/installation" label="Installation" aria-label="Installation" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} -:: \ No newline at end of file +:u-button{to="/docs/getting-started/installation" label="Installation" aria-label="Installation" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file From c12161bb4b040c2a7766a6191a580965b8e48b80 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 13:49:27 -0500 Subject: [PATCH 056/170] Update button syntax in getting started documentation for consistency, ensuring a cleaner presentation of links to environment variable specifications and S6 Overlay usage. --- .../docs/1.getting-started/2.these-images-vs-others.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/content/docs/1.getting-started/2.these-images-vs-others.md b/docs/content/docs/1.getting-started/2.these-images-vs-others.md index 6793a4ba0..0fd424597 100644 --- a/docs/content/docs/1.getting-started/2.these-images-vs-others.md +++ b/docs/content/docs/1.getting-started/2.these-images-vs-others.md @@ -38,8 +38,7 @@ Setting environment variables saves a ton of headache when customizing your cont Our design philosophy is built all around simplicity. The process of customizing the behavior of PHP is as simple as setting an environment variable. We took every common configuration option and set it up so you can change these values in a simple method, defaulting every single option to production-ready values. -::u-button{to="/docs/reference/environment-variable-specification" label="Learn more about environment variables" aria-label="Learn more about environment variables" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} -:: +:u-button{to="/docs/reference/environment-variable-specification" label="Learn more about environment variables" aria-label="Learn more about environment variables" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} ## Optimized for Laravel & WordPress We did the hard work of customizing the official PHP image and giving you everything to get started with running PHP's most popular frameworks in seconds. We also hardened the images to help protect your PHP application from common attacks. @@ -54,4 +53,4 @@ Using **supervisor** to monitor multiple processes in a single container may lea [S6 Overlay](https://github.com/just-containers/s6-overlay){target="_blank"} is a process supervisor designed for containerization from the ground up. It's a modern alternative to [Supervisor (aka Supervisord)](https://supervisord.org/){target="_blank"}. We only use this in our `serversideup/php:*-fpm-apache` and `serversideup/php:*-fpm-nginx` images, as they require two processes to run a service. -::u-button{to="/docs/guides/using-s6-overlay" label="Learn more about S6 Overlay" aria-label="Learn more about S6 Overlay" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file +:u-button{to="/docs/guides/using-s6-overlay" label="Learn more about S6 Overlay" aria-label="Learn more about S6 Overlay" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file From 8bcffda59dd92c14402dbd942b1c848d07a40faa Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 13:49:54 -0500 Subject: [PATCH 057/170] Refactor button syntax in installation documentation for consistency, ensuring a cleaner presentation of links to container basics and enhancing user experience. --- docs/content/docs/1.getting-started/3.installation.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/content/docs/1.getting-started/3.installation.md b/docs/content/docs/1.getting-started/3.installation.md index d91228c3c..0d77596d5 100644 --- a/docs/content/docs/1.getting-started/3.installation.md +++ b/docs/content/docs/1.getting-started/3.installation.md @@ -34,8 +34,7 @@ There are some important terms to understand when working with containers: If you'd like to learn more about containers, you can learn more following the guide below. -::u-button{to="/docs/deployment-and-production/container-basics" label="Learn More About Containers" aria-label="Learn More About Containers" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} -:: +:u-button{to="/docs/deployment-and-production/container-basics" label="Learn More About Containers" aria-label="Learn More About Containers" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} ## Quick Start In order to run containers, we need a container engine installed such as Docker. You can follow [Docker's installation guide](https://docs.docker.com/get-started/get-docker/) to get started. Confirm Docker is working by running these commands in your terminal: From 6ee620c40f5328f910e1c2f9ff4f729f80595246 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 13:52:38 -0500 Subject: [PATCH 058/170] Add 'Choosing an Image' guide to documentation, detailing image selection criteria, popular tags, and variations for PHP Docker images, enhancing user understanding and decision-making. --- .../1.getting-started/4.choosing-an-image.md | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 docs/content/docs/1.getting-started/4.choosing-an-image.md diff --git a/docs/content/docs/1.getting-started/4.choosing-an-image.md b/docs/content/docs/1.getting-started/4.choosing-an-image.md new file mode 100644 index 000000000..c6a4f9ad6 --- /dev/null +++ b/docs/content/docs/1.getting-started/4.choosing-an-image.md @@ -0,0 +1,123 @@ +--- +title: Choosing an Image +description: 'Learn how to choose the right image for your use case.' +--- +::lead-p +Choosing an image might be a little intimidating because there are so many options, but this ultimately gives you a ton of flexibility. This guide will help simplify your decision making process on choosing the right image. +:: + +## Registry: Where images are located +Before diving into the different options available, let's understand where these images come from. The source code is [hosted on GitHub](https://github.com/serversideup/docker-php){target="_blank"} with an automated process that builds and uploads images to container registries: + +1. [Docker Hub](https://hub.docker.com/r/serversideup/php) +2. [GitHub Packages](https://github.com/serversideup/docker-php/pkgs/container/php) + +To use these images, you need to specify a certain "tag" for the image you want. For example, the `8.4` version of the `fpm-nginx` variation is tagged as: + +```bash +serversideup/php:8.4-fpm-nginx +``` + +This image gives you the latest stable patch version of PHP 8.4 running the `fpm-nginx` variation. Since no registry is specified, it defaults to Docker Hub. + +When selecting an image, you'll need to decide on: + +1. PHP version +2. PHP variation +3. Base operating system +4. serversideup/php version (for production environments) + +## Our most popular images +All images are intelligently tagged with the PHP version and variation, allowing you to easily select the right image for your use case. + +If you don't specify a variation, it defaults to `cli` and the latest supported Debian release for that variation. + +Our most popular tags include: +| ⚙️ Variation | 🚀 Version | +| ------------ | ---------- | +| cli | **Debian Based** [![serversideup/php:8.4-cli](https://img.shields.io/docker/image-size/serversideup/php/8.4-cli?label=serversideup%2Fphp%3A8.4-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-cli&page=1&ordering=-name) [![serversideup/php:8.3-cli](https://img.shields.io/docker/image-size/serversideup/php/8.3-cli?label=serversideup%2Fphp%3A8.3-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-cli&page=1&ordering=-name) [![serversideup/php:8.2-cli](https://img.shields.io/docker/image-size/serversideup/php/8.2-cli?label=serversideup%2Fphp%3A8.2-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-cli&page=1&ordering=-name) [![serversideup/php:8.1-cli](https://img.shields.io/docker/image-size/serversideup/php/8.1-cli?label=serversideup%2Fphp%3A8.1-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-cli&page=1&ordering=-name) [![serversideup/php:8.0-cli](https://img.shields.io/docker/image-size/serversideup/php/8.0-cli?label=serversideup%2Fphp%3A8.0-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-cli&page=1&ordering=-name) [![serversideup/php:7.4-cli](https://img.shields.io/docker/image-size/serversideup/php/7.4-cli?label=serversideup%2Fphp%3A7.4-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-cli&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:8.4-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-cli-alpine?label=serversideup%2Fphp%3A8.4-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-cli-alpine&page=1&ordering=-name) [![serversideup/php:8.3-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-cli-alpine?label=serversideup%2Fphp%3A8.3-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-cli-alpine&page=1&ordering=-name) [![serversideup/php:8.2-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.2-cli-alpine?label=serversideup%2Fphp%3A8.2-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-cli-alpine&page=1&ordering=-name) [![serversideup/php:8.1-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.1-cli-alpine?label=serversideup%2Fphp%3A8.1-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-cli-alpine&page=1&ordering=-name) [![serversideup/php:8.0-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.0-cli-alpine?label=serversideup%2Fphp%3A8.0-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-cli-alpine&page=1&ordering=-name) [![serversideup/php:7.4-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/7.4-cli-alpine?label=serversideup%2Fphp%3A7.4-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-cli-alpine&page=1&ordering=-name) | +| fpm | **Debian Based** [![serversideup/php:8.4-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm?label=serversideup%2Fphp%3A8.4-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm&page=1&ordering=-name) [![serversideup/php:8.3-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm?label=serversideup%2Fphp%3A8.3-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm&page=1&ordering=-name) [![serversideup/php:8.2-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm?label=serversideup%2Fphp%3A8.2-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm&page=1&ordering=-name) [![serversideup/php:8.1-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm?label=serversideup%2Fphp%3A8.1-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm&page=1&ordering=-name) [![serversideup/php:8.0-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm?label=serversideup%2Fphp%3A8.0-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm&page=1&ordering=-name) [![serversideup/php:7.4-fpm](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm?label=serversideup%2Fphp%3A7.4-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:8.4-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-alpine?label=serversideup%2Fphp%3A8.4-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.3-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-alpine?label=serversideup%2Fphp%3A8.3-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.2-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-alpine?label=serversideup%2Fphp%3A8.2-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.1-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-alpine?label=serversideup%2Fphp%3A8.1-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.0-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-alpine?label=serversideup%2Fphp%3A8.0-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-alpine&page=1&ordering=-name) [![serversideup/php:7.4-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-alpine?label=serversideup%2Fphp%3A7.4-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-alpine&page=1&ordering=-name) | +| fpm-apache | **Debian Based** [![serversideup/php:8.4-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-apache?label=serversideup%2Fphp%3A8.4-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.3-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-apache?label=serversideup%2Fphp%3A8.3-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.2-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-apache?label=serversideup%2Fphp%3A8.2-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.1-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-apache?label=serversideup%2Fphp%3A8.1-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.0-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-apache?label=serversideup%2Fphp%3A8.0-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-apache&page=1&ordering=-name) [![serversideup/php:7.4-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-apache?label=serversideup%2Fphp%3A7.4-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-apache&page=1&ordering=-name) | +| fpm-nginx | **Debian Based** [![serversideup/php:8.4-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-nginx?label=serversideup%2Fphp%3A8.4-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.3-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-nginx?label=serversideup%2Fphp%3A8.3-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.2-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-nginx?label=serversideup%2Fphp%3A8.2-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.1-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-nginx?label=serversideup%2Fphp%3A8.1-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.0-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-nginx?label=serversideup%2Fphp%3A8.0-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-nginx&page=1&ordering=-name) [![serversideup/php:7.4-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-nginx?label=serversideup%2Fphp%3A7.4-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-nginx&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:8.4-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.4-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.3-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.3-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.2-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.2-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.1-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.1-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.0-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.0-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:7.4-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-nginx-alpine?label=serversideup%2Fphp%3A7.4-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-nginx-alpine&page=1&ordering=-name) | +| frankenphp | **Debian Based** [![serversideup/php:8.4-frankenphp](https://img.shields.io/docker/image-size/serversideup/php/8.4-frankenphp?label=serversideup%2Fphp%3A8.4-frankenphp){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-frankenphp&page=1&ordering=-name) [![serversideup/php:8.3-frankenphp](https://img.shields.io/docker/image-size/serversideup/php/8.3-frankenphp?label=serversideup%2Fphp%3A8.3-frankenphp){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-frankenphp&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:8.4-frankenphp-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-frankenphp-alpine?label=serversideup%2Fphp%3A8.4-frankenphp-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-frankenphp-alpine&page=1&ordering=-name) [![serversideup/php:8.3-frankenphp-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-frankenphp-alpine?label=serversideup%2Fphp%3A8.3-frankenphp-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-frankenphp-alpine&page=1&ordering=-name) | +| unit (deprecated) | **Debian Based** [![serversideup/php:8.4-unit](https://img.shields.io/docker/image-size/serversideup/php/8.4-unit?label=serversideup%2Fphp%3A8.4-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-unit&page=1&ordering=-name) [![serversideup/php:8.3-unit](https://img.shields.io/docker/image-size/serversideup/php/8.3-unit?label=serversideup%2Fphp%3A8.3-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-unit&page=1&ordering=-name) [![serversideup/php:8.2-unit](https://img.shields.io/docker/image-size/serversideup/php/8.2-unit?label=serversideup%2Fphp%3A8.2-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-unit&page=1&ordering=-name) [![serversideup/php:8.1-unit](https://img.shields.io/docker/image-size/serversideup/php/8.1-unit?label=serversideup%2Fphp%3A8.1-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-unit&page=1&ordering=-name) [![serversideup/php:8.0-unit](https://img.shields.io/docker/image-size/serversideup/php/8.0-unit?label=serversideup%2Fphp%3A8.0-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-unit&page=1&ordering=-name) [![serversideup/php:7.4-unit](https://img.shields.io/docker/image-size/serversideup/php/7.4-unit?label=serversideup%2Fphp%3A7.4-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-unit&page=1&ordering=-name) | + +## The full tag schema +Our tagging process is quite flexible, and it can become quite complex, but don't worry -- we've spent a ton of time applying sensible defaults to give you the best experience. + +The full tag schema is as follows: +```jinja +{{registry-url}}/serversideup/php:{{release-prefix}}-{{php-version}}-{{variation-name}}-{{operating-system}}-v{{github-release-version}} +``` + +Here's what each part means: + +| Option | Default | Other Options | +|--------|---------|---------------| +| `{{registry-url}}`
Which registry to pull images from. | `''`
(Docker Hub) | `ghcr.io` (GitHub Packages) | +| `{{release-prefix}}`
The prefix of the release. | `''` (stable) | `beta` (beta releases) | +| `{{php-version}}`
The version of PHP to use. | Latest stable PHP minor version (ie. `8.5`) | `8.4`
`8.3`
`8.2`
`8.1`
`8.0`
`7.4`
(you can also specify the full version number, ie. `8.4.1`) | +| `{{variation-name}}`
The name of the variation to use. | `cli` | `fpm`
`fpm-apache`
`fpm-nginx`
`frankenphp`
`unit` (deprecated) | +| `{{operating-system}}`
The operating system to use. | `debian` | `alpine`
`bullseye`
`bookworm`
`trixie` | +| `{{github-release-version}}`
The version of the GitHub release to use. | (latest stable release) | See our [GitHub Releases](https://github.com/serversideup/docker-php/releases){target="_blank"} for specific versions. | + +## PHP version +There are many factors to consider when choosing the right PHP version. Best practices include: + +1. Choose the latest PHP version (as your dependencies allow) +2. Choose a PHP version that is receiving [active and security support by PHP](https://www.php.net/supported-versions.php){target="_blank"} + +If you need help understanding what's new in each PHP version, check out [the official PHP changelog](https://www.php.net/ChangeLog-8.php){target="_blank"}. This will give you a detailed overview of the changes and improvements in each version. + +## PHP variation +Choose from several variations to suit your needs. Each variation is optimized for specific use cases. + +| Variation | Description | +|-----------|-------------| +| `cli` | Minimal image for running PHP from the command line only. No web server included. | +| `fpm` | Runs PHP-FPM without a web server. Ideal for microservices architectures where you need a dedicated PHP backend. | +| `fpm-apache` | Combines PHP-FPM with Apache as a reverse proxy. Ideal for running WordPress with Docker. | +| `fpm-nginx` | Combines PHP-FPM with NGINX as a reverse proxy. This is the traditional setup widely adopted for modern PHP applications, including Laravel. | +| `frankenphp` | Modern application server built on Caddy that runs everything in a single process. Ideal for Laravel/Symfony applications with worker mode support, automatic HTTPS, and HTTP/2 and HTTP/3 protocols. | +| `unit`
(deprecated) | Uses NGINX Unit as a modern application server that runs everything in a single process. Consider migrating to FrankenPHP for a modern alternative. | + +### CLI +The CLI variation is a minimal image designed for running PHP from the command line only. It does not include a web server. Use this variation when you need a disposable and repeatable method for easily running PHP scripts from your terminal. + +:u-button{to="/docs/image-variations/cli" label="Learn more about the CLI variation" aria-label="Learn more about the CLI variation" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +### FPM +The FPM (Fast Process Manager) variation runs PHP-FPM without a web server. This variation is ideal for microservices architectures where you need a dedicated PHP backend. + +Use this variation when you already have a separate proxy or load balancer handling static content and routing PHP requests to your FPM container. This is commonly used in larger-scale deployments. + +:u-button{to="/docs/image-variations/fpm" label="Learn more about the FPM variation" aria-label="Learn more about the FPM variation" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +### FPM-Apache +The FPM-Apache variation combines PHP-FPM with Apache as a reverse proxy. Apache serves static content directly and forwards PHP requests to PHP-FPM for processing. + +This is an excellent choice for WordPress sites and applications that specifically require Apache features or `.htaccess` support. + +:u-button{to="/docs/image-variations/fpm-apache" label="Learn more about the FPM-Apache variation" aria-label="Learn more about the FPM-Apache variation" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + + +### FPM-NGINX +The FPM-NGINX variation combines PHP-FPM with NGINX as a reverse proxy. This is the traditional setup that has been widely adopted for modern PHP applications, including many Laravel deployments. + +NGINX serves static files efficiently and proxies PHP requests to PHP-FPM, providing excellent performance and flexibility. + +:u-button{to="/docs/image-variations/fpm-nginx" label="Learn more about the FPM-NGINX variation" aria-label="Learn more about the FPM-NGINX variation" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +### FrankenPHP +The FrankenPHP variation is a modern application server built on top of the Caddy web server. It runs everything in a single process, eliminating the complexity of managing PHP-FPM and a separate web server. + +Use this variation for Laravel or Symfony applications that can benefit from worker mode, automatic HTTPS, and modern protocols like HTTP/2 and HTTP/3. This is the recommended variation for new projects seeking cutting-edge performance. + +:u-button{to="/docs/image-variations/frankenphp" label="Learn more about the FrankenPHP variation" aria-label="Learn more about the FrankenPHP variation" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +### Unit (deprecated) +::note +In October 2025, NGINX stopped supporting NGINX Unit and archived the project. NGINX Unit will eventually be removed from our project. [See the official announcement →](https://github.com/nginx/unit?tab=readme-ov-file#nginx-unit) +:: + +The Unit variation uses NGINX Unit as an application server that runs everything in a single process. Since NGINX Unit is no longer maintained, consider migrating to FrankenPHP for a single-process alternative. \ No newline at end of file From 4d208e1181fa4857ae4e4e55e70d6d3d139ea62d Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 14:07:15 -0500 Subject: [PATCH 059/170] Expand 'Choosing an Image' documentation to include detailed descriptions of operating systems, their benefits, and specific version support, enhancing user guidance for selecting appropriate PHP Docker images. --- .../1.getting-started/4.choosing-an-image.md | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/docs/content/docs/1.getting-started/4.choosing-an-image.md b/docs/content/docs/1.getting-started/4.choosing-an-image.md index c6a4f9ad6..e442deb83 100644 --- a/docs/content/docs/1.getting-started/4.choosing-an-image.md +++ b/docs/content/docs/1.getting-started/4.choosing-an-image.md @@ -120,4 +120,35 @@ Use this variation for Laravel or Symfony applications that can benefit from wor In October 2025, NGINX stopped supporting NGINX Unit and archived the project. NGINX Unit will eventually be removed from our project. [See the official announcement →](https://github.com/nginx/unit?tab=readme-ov-file#nginx-unit) :: -The Unit variation uses NGINX Unit as an application server that runs everything in a single process. Since NGINX Unit is no longer maintained, consider migrating to FrankenPHP for a single-process alternative. \ No newline at end of file +The Unit variation uses NGINX Unit as an application server that runs everything in a single process. Since NGINX Unit is no longer maintained, consider migrating to FrankenPHP for a single-process alternative. + +## Operating System +Choosing an operating system comes down to a few preferences, but ultimately you need to make sure your dependencies are available for the operating system you choose. + +| Operating System | Description | +|-----------|-------------| +| `debian` (default) | Debian is a popular Linux distribution that is known for its stability and reliability. It is the default operating system for our images. | +| `alpine` | Alpine is a lightweight Linux distribution that is known for its small size and low resource usage. It is the default operating system for our images. | + +### Debian +Debian is a popular Linux distribution that is known for its stability and compatibility. It is the default operating system for our images. + +### Alpine +Alpine is a lightweight Linux distribution that is known for its small size and low resource usage. If you're an advanced user, Alpine may be an excellent choice for you. + +### Specific versions +::note +Not all operating systems are available for all image variations and PHP versions. Double check [Docker Hub](https://hub.docker.com/r/serversideup/php/tags){target="_blank"} and [GitHub Packages](https://github.com/serversideup/docker-php/pkgs/container/php){target="_blank"} for the most accurate list of available tags. +:: +We also support specific versions of operating systems. So this means that you can choose versions like: + +- `bookworm` +- `trixie` +- `alpine3.16` +- `alpine3.17` +- `alpine3.18` +- `alpine3.19` +- `alpine3.20` +- `alpine3.21` +- `alpine3.22` + From 2ef19ef0ff28345ec7af9bbf8c268611aa42d1bb Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 14:11:31 -0500 Subject: [PATCH 060/170] Add comprehensive 'Default Configurations' documentation for PHP Docker images, detailing production readiness, default settings, environment variables, PHP extensions, OS packages, health checks, and entrypoint scripts, enhancing user understanding and deployment efficiency. --- .../5.default-configurations.md | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 docs/content/docs/1.getting-started/5.default-configurations.md diff --git a/docs/content/docs/1.getting-started/5.default-configurations.md b/docs/content/docs/1.getting-started/5.default-configurations.md new file mode 100644 index 000000000..f75466930 --- /dev/null +++ b/docs/content/docs/1.getting-started/5.default-configurations.md @@ -0,0 +1,128 @@ +--- +head.title: 'Installation - Docker PHP - Server Side Up' +description: 'Learn how to get started with serversideup/php Docker Images.' +layout: docs +--- + +::lead-p +`serversideup/php` is configured for real-world deployments right out of the box. This saves you many hours so you can launch faster than ever. +:: + +## Production-ready and optimized for Laravel & WordPress +All values are defaulted to improve security and performance. We also spent the time to carefully review official documentation and include packages that are required specifically for Laravel and WordPress. + +## Unprivileged by Default +All images default to running as the OS-native `www-data` user. + +::note +The `www-data` UID/GID is different between Debian (`33:33`) and Alpine (`82:82`). We left these values alone to make these images as native as possible. If you switch between Debian and Alpine, you may need to adjust file permissions in your Docker image and volume mounts. +:: + +Since these images are not privileged, that means they are not running on ports less than 1024: + +| **Variation** | **Default Ports** | +|---------------|-------------------| +| cli | (none) | +| fpm | 9000 | +| fpm-nginx | HTTP: 8080, HTTPS: 8443 | +| fpm-apache | HTTP: 8080, HTTPS: 8443 | +| unit | HTTP: 8080, HTTPS: 8443 | +| frankenphp | HTTP: 8080, HTTPS: 8443 | + +### How do I run these services on ports 80 and/or 443? +Almost everyone will want to run these services on ports 80 and 443. If you have an advanced setup, you can use a reverse proxy like Caddy or Traefik to handle the SSL termination and forward the traffic to the container on the non-privileged port. + +Or you can simply use Docker's port mapping feature to map the container port to the host port. For example, to run the `fpm-nginx` variation on port 80 and 443, you can run the following command: + +```bash [Terminal] +docker run -p 80:8080 -p 443:8443 serversideup/php:8.4-fpm-nginx +``` + +## Default Environment Variables +Environment variables give you a ton of flexibility to customize your container without the complexity of mounting custom configuration files. By default, these images are set to production-ready values. You can read more about the available environment variables below. + +:u-button{to="/docs/reference/environment-variable-specification" label="Learn more about environment variables" aria-label="Learn more about environment variables" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## Default PHP INI Settings + +| **PHP INI file** | **Description** | +|-----------------|-----------------| +| **Image Default**

`/usr/local/etc/php/conf.d/serversideup-docker-php.ini` | This is our production-ready PHP ini file that accepts environment variables. You can [review it in greater detail on GitHub](https://github.com/serversideup/docker-php/blob/main/src/common/usr/local/etc/php/conf.d/serversideup-docker-php.ini){target="_blank"}. | +| **Adding your own PHP INI file**

`/usr/local/etc/php/conf.d/*.ini` | If you want to use our defaults, you can simple create a `.ini` file in the `/usr/local/etc/php/conf.d/` directory and it will be loaded automatically. This will be loaded *after* our default ini file, so whatever you set in your own ini file will override the default values. | + +:u-button{to="/docs/customizing-the-image/changing-common-php-settings" label="Learn more about changing common PHP settings" aria-label="Learn more about changing common PHP settings" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## Default PHP Extensions +The following extensions are installed by default: + +| **Extension** | **Description** | **Why we included it** | +|---------------|-----------------|------------------------| +| [opcache](https://www.php.net/manual/en/book.opcache.php) | The Zend OPcache provides faster PHP execution through opcode caching and optimization. | This is a must-have for PHP performance.

⚠️ OPcache is disabled by default but can easily be enabled with [`PHP_OPCACHE_ENABLE=1`](/docs/reference/environment-variable-specification).| +| [mysqli](https://www.php.net/manual/en/book.mysqli.php) | The "MySQL Improved" extension is an older extension for connecting to MySQL 4.1 and above. | **Enabled for fpm-apache only**. This is a legacy MySQL connector required for WordPress.| +| [pcntl](https://www.php.net/manual/en/intro.pcntl.php) | Process Control support in PHP implements the Unix style of process creation, program execution, signal handling and process termination. | This is required for [Laravel queues and Laravel Horizon](https://laravel.com/docs/10.x/queues#timeout)| +| [pdo_mysql](https://www.php.net/manual/en/ref.pdo-mysql.php) | The MySQL PDO extension allows you to connect to MySQL databases. | MySQL and MariaDB databases are very popular. | +| [pdo_pgsql](https://www.php.net/manual/en/ref.pdo-pgsql.php) | The PostgreSQL PDO extension allows you to connect to PostgreSQL databases. | PostgreSQL databases are very popular. | +| [redis](https://www.php.net/manual/en/book.redis.php) | The Redis extension allows you to connect to Redis databases. | Redis is very popular for caching and it's also required for [Laravel Horizon](https://laravel.com/docs/10.x/horizon). Our tests concluded adding this package only added 2MB to the image size. | +| [zip](https://www.php.net/manual/en/book.zip.php) | The Zip extension allows you to create and extract zip files. | We included this for the popularity of apps working with ZIP files. This package is also required if you're working with attachments on [Laravel Dusk](https://laravel.com/docs/10.x/dusk#attaching-files). | + +The official PHP images are already providing the following extensions: +- ctype +- curl +- dom +- fileinfo +- filter +- hash +- mbstring +- openssl +- pcre +- session +- tokenizer +- xml + +If you need to install additional extensions, you can use the guide below to learn more. + +:u-button{to="/docs/customizing-the-image/installing-additional-php-extensions" label="Learn more about installing additional PHP extensions" aria-label="Learn more about installing additional PHP extensions" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## Default Operating System Packages +The following packages are installed by default: + +| **Package** | **Description** | **Image variations** | **Why we included it** | +|-------------|-----------------|----------------------|------------------------| +| `libfcgi-bin`
(Debian)
`fcgi`
(Alpine) | FastCGI is a protocol for interfacing interactive programs with a web server. | *-fpm
*-fpm-nginx
*-fpm-apache | This is required for the webserver to interface with PHP-FPM and the [`php-fpm-healthcheck`](https://github.com/renatomefi/php-fpm-healthcheck) project. | +| `gettext-base` (Debian)
`gettext` (Alpine) | GNU gettext is a framework for translating user interfaces. | *-fpm-nginx
*-fpm-apache | This is required for the `envsubst` command. We use this command to process templates on container initialization. | +| `libstdc++6`
(Debian)
`libstdc++` (Alpine) | The GNU Standard C++ Library is a C++ standard library. | *-frankenphp | This is [required for the watcher to run](https://github.com/php/frankenphp/blob/e917ab79742c9e4703023861fdc7a86cdb59da1e/Dockerfile#L135-L138) with FrankenPHP. | +| `procps` | The procps package contains programs for monitoring your system and its processes. | * (only Debian images) | This is required for `pgrep` so we can use that for our native health checks. | +| `shadow` | Shadow is required for the `usermod` command. | *-alpine | This is required to change the UID and GID of the `www-data` user in `docker-php-serversideup-set-id`. | + +:u-button{to="/docs/getting-started/choosing-an-image#operating-system" label="Learn which operating systems are available" aria-label="Learn which operating systems are available" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + + +## Health Checks +By default, all health checks for web servers (Apache, Unit, NGINX, etc.) are located at `/healthcheck`. You should receive an `OK` response if the container is healthy. + +For our `fpm` variation, we use the [`php-fpm-healthcheck`](https://github.com/renatomefi/php-fpm-healthcheck) script to verify the health of PHP-FPM. This script is located at `/usr/local/bin/php-fpm-healthcheck`. + +The `cli` variation does not have a health check because it doesn't really make sense to have one. Would love to discuss more if you feel different. + +:u-button{to="/docs/guides/using-healthchecks-with-laravel" label="Learn more about health checks" aria-label="Learn more about health checks" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + + +## Default Entrypoint Scripts +We created an entrypoint script that scans the `entrypoint.d` directory for other shell scripts to execute before the main container process starts. All scripts are executed in alphabetical order so you can have full control over what script execution order. + +We also provide a few default scripts to help you get started. + +| **Script Name** | **Description** | **Image variations** | +|------------|-----------------|----------------------| +| `0-container-info.sh` | Shows basic execution information, such as Docker User, UID, GID, etc. | all | +| `1-log-output-level.sh` | Sets PHP log output level to match `LOG_OUTPUT_LEVEL` | all | +| `10-init-unit.sh` | Processes Unit templates, configures SSL (if enabled), and prepares NGINX Unit for launch | unit | +| `10-init-webserver-config.sh` | Processes web server configuration templates, configures SSL (if enabled), and prepares web server for launch | *-nginx
*-apache | +| `50-laravel-automations.sh` | If `AUTORUN_ENABLED` is set to true, and a Laravel installation is detected, the following commands will automatically execute on container start:
- `php artisan config:cache`
- `php artisan route:cache`
- `php artisan view:cache`
- `php artisan event:cache`
- `php artisan migrate --force` | all | + +If you want to add your own entrypoint scripts, use the guide below to learn more. + +:u-button{to="/docs/customizing-the-image/adding-your-own-start-up-scripts" label="Learn more about adding your own start up scripts" aria-label="Learn more about adding your own start up scripts" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## Disabling Default Entrypoint Scripts +We get it. Sometimes you just want our stuff to get out of the way. If you want full control to customize your image, all default entrypoint scripts can be disabled by setting `DISABLE_DEFAULT_CONFIG` to `true`. From 5fec04582c653f2f4caf336100810af544ab0a0e Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 14:12:14 -0500 Subject: [PATCH 061/170] Add upgrade guide documentation for Docker PHP images, detailing version selection, release process, and manual update instructions for Debian and Alpine, enhancing user understanding of image management and stability in production environments. --- .../docs/1.getting-started/6.upgrade-guide.md | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 docs/content/docs/1.getting-started/6.upgrade-guide.md diff --git a/docs/content/docs/1.getting-started/6.upgrade-guide.md b/docs/content/docs/1.getting-started/6.upgrade-guide.md new file mode 100644 index 000000000..0f3f65fba --- /dev/null +++ b/docs/content/docs/1.getting-started/6.upgrade-guide.md @@ -0,0 +1,55 @@ +--- +head.title: 'Upgrade Guide - Docker PHP - Server Side Up' +description: 'Learn how the serversideup/php Docker images are built and how to upgrade.' +layout: docs +title: Upgrading +--- + +If you do not select a specific patch version, then you will receive automatic PHP updates. + +For example, you can select your version based on the different version numbers: +- Major Version (example: `8` will give you the latest 8.x version) +- Minor Version (example: `8.4` will give you the latest 8.4.x version) +- Patch Version (example: `8.4.1` will always stay at the 8.4.1 version) + +If you use `latest`, you will always get the latest stable version of the CLI variation of PHP. For the best stability in production environments, you may want to pin to a specific patch version (example: `8.4.1`). + +If you need help choosing an image, see our guide below. + +:u-button{to="/docs/getting-started/choosing-an-image" label="Learn more about choosing an image" aria-label="Learn more about choosing an image" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## Release process +All source code is merged into the `main` branch, which automatically build our "beta" images. + +After testing the images internally and from other community members, we will [publish a release on GitHub](https://github.com/serversideup/docker-php/releases) with a detailed changelog. + +## Updating the Docker images on your own +If you You and simply run `apt-get update && apt-get upgrade` within your own image, but still want the image to receive other operating system updates, you will need to run the following commands on your build. + +Any updates that you apply have a risk of breaking other things inside the container. Be sure to have a good testing process in place before applying updates to your production environment. + +#### Example Dockerfile with manual updates for Debian +```dockerfile [Dockerfile] +FROM serversideup/php:8.4.1-fpm-nginx + +RUN apt-get update \ + && apt-get upgrade -y \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /usr/share/doc/* +``` + +If you're running an Alpine-based image, you can use the following commands: + +#### Example Dockerfile with manual updates for Alpine +```dockerfile [Dockerfile] +FROM serversideup/php:8.4.1-fpm-nginx-alpine + +RUN apk update \ + && apk upgrade \ + && rm -rf /var/cache/apk/* +``` + +## Subscribe to repository updates +Regardless if you are choosing to use automatic updates or manual updates, it is highly advised to subscribe to our releases. You can do this through the "Watch" button on our [GitHub](https://github.com/serversideup/docker-php). + +![Watch Repository](images/docs/watch-repo.png){.max-w-md.w-full.h-auto.mx-auto} From f9b01c51a9d4ae87592e9d67257182e81bf59802 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 14:12:46 -0500 Subject: [PATCH 062/170] Add changelog documentation for Docker PHP images, providing an overview of changes and a link to release notes on GitHub, enhancing user awareness of updates and version selection. --- docs/content/docs/1.getting-started/7.changelog.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 docs/content/docs/1.getting-started/7.changelog.md diff --git a/docs/content/docs/1.getting-started/7.changelog.md b/docs/content/docs/1.getting-started/7.changelog.md new file mode 100644 index 000000000..ddd9b0a3f --- /dev/null +++ b/docs/content/docs/1.getting-started/7.changelog.md @@ -0,0 +1,13 @@ +--- +head.title: 'Changelog - Docker PHP - Server Side Up' +description: 'See the latest releases and changes for the PHP Docker Image project.' +layout: docs +--- +::lead-p +All our changes are documented and published on our GitHub. [See our release notes on GitHub →](https://github.com/serversideup/docker-php/releases){target="_blank"} +:: + +### Choosing a version +You may want to review [our guide on selecting the right image](/docs/getting-started/choosing-an-image) to determine which version and image tag is best for you. + +:u-button{to="https://github.com/serversideup/docker-php/releases" target="_blank" label="See our release notes on GitHub" aria-label="See our release notes on GitHub" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file From 364ee7b0b5274f44bf312dff37d799f198126553 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 14:12:51 -0500 Subject: [PATCH 063/170] Add 'About Us' documentation for Docker PHP images, introducing the project creators, their mission, and resources for community engagement, enhancing user connection and understanding of the project's background. --- .../content/docs/1.getting-started/8.about.md | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 docs/content/docs/1.getting-started/8.about.md diff --git a/docs/content/docs/1.getting-started/8.about.md b/docs/content/docs/1.getting-started/8.about.md new file mode 100644 index 000000000..d11aee036 --- /dev/null +++ b/docs/content/docs/1.getting-started/8.about.md @@ -0,0 +1,53 @@ +--- +head.title: 'About - Docker PHP - Server Side Up' +description: 'Learn more about how this project got started and who inspired it.' +layout: docs +--- + +::lead-p +We're taking the extra effort to open source as much as we can. Not only could this potentially help someone learn a little bit of Docker, but it makes it a *heck of a lot* easier for us to work with other people on our other open source projects. +:: + +## About Us +We're [Dan](https://x.com/danpastori){target="_blank"} and [Jay](https://x.com/jaydrogers){target="_blank"} - a two person team with a passion for open source products. We created [Server Side Up](https://serversideup.net){target="_blank"} to help share what we learn. + +### Find us at: + +* **📖 [Blog](https://serversideup.net){target="_blank"}** - Get the latest guides and free courses on all things web/mobile development. +* **🙋 [Community](https://community.serversideup.net){target="_blank"}** - Get friendly help from our community members. +* **🤵‍♂️ [Get Professional Help](https://serversideup.net/professional-support){target="_blank"}** - Get video + screen-sharing support from the core contributors. +* **💻 [GitHub](https://github.com/serversideup){target="_blank"}** - Check out our other open source projects. +* **📫 [Newsletter](https://serversideup.net/subscribe){target="_blank"}** - Skip the algorithms and get quality content right to your inbox. +* **🐥 [Twitter](https://x.com/serversideup){target="_blank"}** - You can also follow [Dan](https://x.com/danpastori){target="_blank"} and [Jay](https://x.com/jaydrogers){target="_blank"}. +* **❤️ [Sponsor Us](https://github.com/sponsors/serversideup){target="_blank"}** - Please consider sponsoring us so we can create more helpful resources. + +## Our products +If you appreciate this project, be sure to check out our other projects. + +### 📚 Books +- **[The Ultimate Guide to Building APIs & SPAs](https://serversideup.net/ultimate-guide-to-building-apis-and-spas-with-laravel-and-nuxt3/){target="_blank"}**: Build web & mobile apps from the same codebase. +- **[Building Multi-Platform Browser Extensions](https://serversideup.net/building-multi-platform-browser-extensions/){target="_blank"}**: Ship extensions to all browsers from the same codebase. + +### 🛠️ Software-as-a-Service +- **[Bugflow](https://bugflow.io/){target="_blank"}**: Get visual bug reports directly in GitHub, GitLab, and more. +- **[SelfHost Pro](https://selfhostpro.com/){target="_blank"}**: Connect Stripe or Lemonsqueezy to a private docker registry for self-hosted apps. + +### 🌍 Open Source +- **[AmplitudeJS](https://serversideup.net/open-source/amplitudejs){target="_blank"}**: Open-source HTML5 & JavaScript Web Audio Library. +- **[Spin](https://serversideup.net/open-source/spin/){target="_blank"}**: Laravel Sail alternative for running Docker from development → production. +- **[Financial Freedom](https://github.com/serversideup/financial-freedom){target="_blank"}**: Open source alternative to Mint, YNAB, & Monarch Money. + +## Special thanks +This project wouldn't be possible without the help of some amazing people. We're grateful for their support and contributions. We wanted to give them a special shoutout here (in no particular order). + +### [Chris Fidao](https://github.com/fideloper){target="_blank"} +Majority of our knowledge came from Chris' course, [Shipping Docker](https://serversforhackers.com/shipping-docker). If you have yet to discover his content, you will be very satisfied with every course he has to offer. He's a great human being and excellent educator. Chris has continuously provided quality feedback that has deeply inspired the direction of this project. + +### [Joel Clermont](https://github.com/joelclermont/){target="_blank"} +Joel is one of the friendliest people that you'll ever meet. When he's not podcasting on his own show, [No Compromises](https://show.nocompromises.io/), he's busy helping other people in the PHP community. Joel's deep experience with PHP is rare to find, and we're grateful that we were able to pick his brain to bring you the best PHP Docker experience possible. + +### [Patricio](https://github.com/ijpatricio){target="_blank"} +If there's a new framework or tool in the web development world, Patricio probably has content for it on his [YouTube Channel](https://www.youtube.com/@PatricioOnCode). Patricio is a great resource for all things web development. Frontend, backend, DevOps -- it doesn't matter. Patricio graciously shared his wide spectrum of experiences with us and is a huge supporter of this project. + +### [linuxserver.io](https://www.linuxserver.io/){target="_blank"} +These guys are absolute aces when it comes to Docker development. They are a great resource for tons of open source Docker images. Check out their work, especially if you're a homelabber. \ No newline at end of file From 46a830e137ea831bf7f910a9e7438f41745441ca Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 14:13:15 -0500 Subject: [PATCH 064/170] Add contributing documentation for Docker PHP images, outlining guidelines for improving documentation, project dependencies, local development setup, and GitHub Actions usage, enhancing community engagement and support for contributors. --- .../docs/1.getting-started/9.contributing.md | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 docs/content/docs/1.getting-started/9.contributing.md diff --git a/docs/content/docs/1.getting-started/9.contributing.md b/docs/content/docs/1.getting-started/9.contributing.md new file mode 100644 index 000000000..d07cffc1b --- /dev/null +++ b/docs/content/docs/1.getting-started/9.contributing.md @@ -0,0 +1,132 @@ +--- +head.title: 'Contributing - Docker PHP - Server Side Up' +description: 'Learn how you can make a difference and contribute to the Docker PHP project.' +layout: docs +--- + +::lead-p +Thanks for your interest in contributing to this project! Please use read this entire guide before submitting a pull request. +:: + +## Improve the docs +Improving the docs is very easy. If you find a simple mistake, look at the bottom of the Table Of Contents section and click "Edit this page". + +If you'd like to contribute bigger documentation changes, take a look at the `/docs` directory. Our entire site is available in that directory and you can see the process to easily install this on your machine by reading `/docs/README.md`. + +:u-button{to="https://github.com/serversideup/docker-php/tree/main/docs" target="_blank" label="Learn how to contribute to the docs" aria-label="Learn how to contribute to the docs" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + + +## Project dependencies +You must have these installed on your system. +* Docker (container engine): https://www.docker.com/products/docker-desktop + +## How things work +1. All files are stored in the `/src` folder +1. GitHub Actions will automatically build and deploy the images + +## Running things locally +To run a build, simply run `./scripts/dev.sh` (with Docker Desktop running). This will show you a help menu with all the available options. + +#### Example: Build a Unit image running PHP 8.2.12 on Debian Bookworm +```bash [Terminal] +bash scripts/dev.sh --variation unit --version 8.2.12 --os bookworm +``` + +This will build `serversideup/php:8.2.12-unit-bookworm` locally on your machine for testing and inspection. + +### Published Beta Images +We also have beta images that are published to our Docker Hub and GitHub Packages repositories. + +#### Debian Variations +| ⚙️ Variation | 🚀 Version | +| ------------ | ---------- | +| cli | **Debian Based** [![serversideup/php:beta-8.4-cli](https://img.shields.io/docker/image-size/serversideup/php/beta-8.4-cli?label=serversideup%2Fphp%3Abeta-8.4-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.4-cli&page=1&ordering=-name) [![serversideup/php:beta-8.3-cli](https://img.shields.io/docker/image-size/serversideup/php/beta-8.3-cli?label=serversideup%2Fphp%3Abeta-8.3-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.3-cli&page=1&ordering=-name) [![serversideup/php:beta-8.2-cli](https://img.shields.io/docker/image-size/serversideup/php/beta-8.2-cli?label=serversideup%2Fphp%3Abeta-8.2-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.2-cli&page=1&ordering=-name) [![serversideup/php:beta-8.1-cli](https://img.shields.io/docker/image-size/serversideup/php/beta-8.1-cli?label=serversideup%2Fphp%3Abeta-8.1-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.1-cli&page=1&ordering=-name) [![serversideup/php:beta-8.0-cli](https://img.shields.io/docker/image-size/serversideup/php/beta-8.0-cli?label=serversideup%2Fphp%3Abeta-8.0-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.0-cli&page=1&ordering=-name) [![serversideup/php:beta-7.4-cli](https://img.shields.io/docker/image-size/serversideup/php/beta-7.4-cli?label=serversideup%2Fphp%3Abeta-7.4-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-7.4-cli&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:beta-8.4-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.4-cli-alpine?label=serversideup%2Fphp%3Abeta-8.4-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.4-cli-alpine&page=1&ordering=-name) [![serversideup/php:beta-8.3-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.3-cli-alpine?label=serversideup%2Fphp%3Abeta-8.3-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.3-cli-alpine&page=1&ordering=-name) [![serversideup/php:beta-8.2-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.2-cli-alpine?label=serversideup%2Fphp%3Abeta-8.2-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.2-cli-alpine&page=1&ordering=-name) [![serversideup/php:beta-8.1-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.1-cli-alpine?label=serversideup%2Fphp%3Abeta-8.1-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.1-cli-alpine&page=1&ordering=-name) [![serversideup/php:beta-8.0-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.0-cli-alpine?label=serversideup%2Fphp%3Abeta-8.0-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.0-cli-alpine&page=1&ordering=-name) [![serversideup/php:beta-7.4-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-7.4-cli-alpine?label=serversideup%2Fphp%3Abeta-7.4-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-7.4-cli-alpine&page=1&ordering=-name) | +| fpm | **Debian Based** [![serversideup/php:beta-8.4-fpm](https://img.shields.io/docker/image-size/serversideup/php/beta-8.4-fpm?label=serversideup%2Fphp%3Abeta-8.4-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.4-fpm&page=1&ordering=-name) [![serversideup/php:beta-8.3-fpm](https://img.shields.io/docker/image-size/serversideup/php/beta-8.3-fpm?label=serversideup%2Fphp%3Abeta-8.3-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.3-fpm&page=1&ordering=-name) [![serversideup/php:beta-8.2-fpm](https://img.shields.io/docker/image-size/serversideup/php/beta-8.2-fpm?label=serversideup%2Fphp%3Abeta-8.2-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.2-fpm&page=1&ordering=-name) [![serversideup/php:beta-8.1-fpm](https://img.shields.io/docker/image-size/serversideup/php/beta-8.1-fpm?label=serversideup%2Fphp%3Abeta-8.1-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.1-fpm&page=1&ordering=-name) [![serversideup/php:beta-8.0-fpm](https://img.shields.io/docker/image-size/serversideup/php/beta-8.0-fpm?label=serversideup%2Fphp%3Abeta-8.0-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.0-fpm&page=1&ordering=-name) [![serversideup/php:beta-7.4-fpm](https://img.shields.io/docker/image-size/serversideup/php/beta-7.4-fpm?label=serversideup%2Fphp%3Abeta-7.4-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-7.4-fpm&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:beta-8.4-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.4-fpm-alpine?label=serversideup%2Fphp%3Abeta-8.4-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.4-fpm-alpine&page=1&ordering=-name) [![serversideup/php:beta-8.3-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.3-fpm-alpine?label=serversideup%2Fphp%3Abeta-8.3-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.3-fpm-alpine&page=1&ordering=-name) [![serversideup/php:beta-8.2-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.2-fpm-alpine?label=serversideup%2Fphp%3Abeta-8.2-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.2-fpm-alpine&page=1&ordering=-name) [![serversideup/php:beta-8.1-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.1-fpm-alpine?label=serversideup%2Fphp%3Abeta-8.1-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.1-fpm-alpine&page=1&ordering=-name) [![serversideup/php:beta-8.0-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.0-fpm-alpine?label=serversideup%2Fphp%3Abeta-8.0-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.0-fpm-alpine&page=1&ordering=-name) [![serversideup/php:beta-7.4-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-7.4-fpm-alpine?label=serversideup%2Fphp%3Abeta-7.4-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-7.4-fpm-alpine&page=1&ordering=-name) | +| fpm-apache | **Debian Based** [![serversideup/php:beta-8.4-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/beta-8.4-fpm-apache?label=serversideup%2Fphp%3Abeta-8.4-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.4-fpm-apache&page=1&ordering=-name) [![serversideup/php:beta-8.3-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/beta-8.3-fpm-apache?label=serversideup%2Fphp%3Abeta-8.3-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.3-fpm-apache&page=1&ordering=-name) [![serversideup/php:beta-8.2-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/beta-8.2-fpm-apache?label=serversideup%2Fphp%3Abeta-8.2-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.2-fpm-apache&page=1&ordering=-name) [![serversideup/php:beta-8.1-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/beta-8.1-fpm-apache?label=serversideup%2Fphp%3Abeta-8.1-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.1-fpm-apache&page=1&ordering=-name) [![serversideup/php:beta-8.0-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/beta-8.0-fpm-apache?label=serversideup%2Fphp%3Abeta-8.0-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.0-fpm-apache&page=1&ordering=-name) [![serversideup/php:beta-7.4-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/beta-7.4-fpm-apache?label=serversideup%2Fphp%3Abeta-7.4-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-7.4-fpm-apache&page=1&ordering=-name) | +| fpm-nginx | **Debian Based** [![serversideup/php:beta-8.4-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/beta-8.4-fpm-nginx?label=serversideup%2Fphp%3Abeta-8.4-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.4-fpm-nginx&page=1&ordering=-name) [![serversideup/php:beta-8.3-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/beta-8.3-fpm-nginx?label=serversideup%2Fphp%3Abeta-8.3-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.3-fpm-nginx&page=1&ordering=-name) [![serversideup/php:beta-8.2-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/beta-8.2-fpm-nginx?label=serversideup%2Fphp%3Abeta-8.2-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.2-fpm-nginx&page=1&ordering=-name) [![serversideup/php:beta-8.1-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/beta-8.1-fpm-nginx?label=serversideup%2Fphp%3Abeta-8.1-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.1-fpm-nginx&page=1&ordering=-name) [![serversideup/php:beta-8.0-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/beta-8.0-fpm-nginx?label=serversideup%2Fphp%3Abeta-8.0-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.0-fpm-nginx&page=1&ordering=-name) [![serversideup/php:beta-7.4-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/beta-7.4-fpm-nginx?label=serversideup%2Fphp%3Abeta-7.4-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-7.4-fpm-nginx&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:beta-8.4-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.4-fpm-nginx-alpine?label=serversideup%2Fphp%3Abeta-8.4-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.4-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:beta-8.3-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.3-fpm-nginx-alpine?label=serversideup%2Fphp%3Abeta-8.3-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.3-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:beta-8.2-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.2-fpm-nginx-alpine?label=serversideup%2Fphp%3Abeta-8.2-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.2-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:beta-8.1-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.1-fpm-nginx-alpine?label=serversideup%2Fphp%3Abeta-8.1-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.1-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:beta-8.0-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.0-fpm-nginx-alpine?label=serversideup%2Fphp%3Abeta-8.0-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.0-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:beta-7.4-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-7.4-fpm-nginx-alpine?label=serversideup%2Fphp%3Abeta-7.4-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-7.4-fpm-nginx-alpine&page=1&ordering=-name) | +| frankenphp | **Debian Based** [![serversideup/php:beta-8.4-frankenphp](https://img.shields.io/docker/image-size/serversideup/php/beta-8.4-frankenphp?label=serversideup%2Fphp%3Abeta-8.4-frankenphp){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.4-frankenphp&page=1&ordering=-name) [![serversideup/php:beta-8.3-frankenphp](https://img.shields.io/docker/image-size/serversideup/php/beta-8.3-frankenphp?label=serversideup%2Fphp%3Abeta-8.3-frankenphp){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.3-frankenphp&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:beta-8.4-frankenphp-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.4-frankenphp-alpine?label=serversideup%2Fphp%3Abeta-8.4-frankenphp-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.4-frankenphp-alpine&page=1&ordering=-name) [![serversideup/php:beta-8.3-frankenphp-alpine](https://img.shields.io/docker/image-size/serversideup/php/beta-8.3-frankenphp-alpine?label=serversideup%2Fphp%3Abeta-8.3-frankenphp-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.3-frankenphp-alpine&page=1&ordering=-name) | +| unit (deprecated) | **Debian Based** [![serversideup/php:beta-8.4-unit](https://img.shields.io/docker/image-size/serversideup/php/beta-8.4-unit?label=serversideup%2Fphp%3Abeta-8.4-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.4-unit&page=1&ordering=-name) [![serversideup/php:beta-8.3-unit](https://img.shields.io/docker/image-size/serversideup/php/beta-8.3-unit?label=serversideup%2Fphp%3Abeta-8.3-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.3-unit&page=1&ordering=-name) [![serversideup/php:beta-8.2-unit](https://img.shields.io/docker/image-size/serversideup/php/beta-8.2-unit?label=serversideup%2Fphp%3Abeta-8.2-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.2-unit&page=1&ordering=-name) [![serversideup/php:beta-8.1-unit](https://img.shields.io/docker/image-size/serversideup/php/beta-8.1-unit?label=serversideup%2Fphp%3Abeta-8.1-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.1-unit&page=1&ordering=-name) [![serversideup/php:beta-8.0-unit](https://img.shields.io/docker/image-size/serversideup/php/beta-8.0-unit?label=serversideup%2Fphp%3Abeta-8.0-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-8.0-unit&page=1&ordering=-name) [![serversideup/php:beta-7.4-unit](https://img.shields.io/docker/image-size/serversideup/php/beta-7.4-unit?label=serversideup%2Fphp%3Abeta-7.4-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=beta-7.4-unit&page=1&ordering=-name) | + +#### Running a test web server: +Sometimes you need to just run a test web server locally to see if your changes work. Below is a good example on how to quickly do this. + +```bash [Terminal] +docker run --rm -v $(pwd):/var/www/html -p 80:8080 -p 443:8443 serversideup/php:8.4-fpm-nginx +``` + +## How PHP Versions are selected for distribution +We use the official PHP versions as our base image. To identify which versions should be built, we use a file called `scripts/conf/php-versions-base-config.yml` to explicitly select what versions should be built and any special rules/settings for each version (like base OS, default versions, etc). + +We then use a `scripts/get-php-versions.sh` script to download the [latest active releases from PHP](https://www.php.net/releases/active.php) and merge them into a final file called `scripts/conf/php-versions.yml`. + +The `php-versions.yml` file will include all final versions for tagging and building. + +We generate our tags with a file called `scripts/assemble-docker-tags.sh` which handles all the advanced logic of compiling our tags together. + +All the scripts above are designed to run locally and in GitHub Actions. Feel free to execute these scripts to see the help menus and how they work. + +## GitHub Actions +We use GitHub Actions exclusively to publish all of our releases. If the image exists from DockerHub or GitHub Packages, it will never be published from a local machine. + +See `.github/workflows/action_publish-beta-images.yml` for an example of how we publish our beta images. + +## NGINX Versions +We use the official NGINX repos to install the latest version of NGINX for each OS. The version to install is set by a build argument, which is loaded from the `scripts/conf/php-versions-base-config.yml` file. + +To view the current NGINX versions, run the following command: + +#### View NGINX versions +```bash [Terminal] +./scripts/get-nginx-versions.sh +``` + +This script will look at the official NGINX repos to find the latest version of NGINX for each OS. If you want to update the version, you can run the script with the `--write` flag. + +#### Update NGINX versions +```bash [Terminal] +./scripts/get-nginx-versions.sh --write +``` + +### NGINX repository key verification + +- **Debian (APT)**: We import the official NGINX GPG key from `https://nginx.org/keys/nginx_signing.key` and verify it against a pinned fingerprint via the `SIGNING_FINGERPRINT` build arg. +- **Alpine (APK)**: APK uses a raw RSA public key (`nginx_signing.rsa.pub`). We verify this key by pinning the SHA‑256 of the DER‑encoded public key via the `SIGNING_ALPINE_RSA_PUB_SHA256` build arg. You can provide multiple comma‑separated hashes to support key rotation. + +#### Compute the Alpine key hash when updating: + +```bash [Terminal] +curl -sS https://nginx.org/keys/nginx_signing.rsa.pub -o /tmp/nginx_signing.rsa.pub + +# macOS +openssl rsa -pubin -in /tmp/nginx_signing.rsa.pub -outform DER 2>/dev/null | shasum -a 256 | awk '{print $1}' + +# Linux +openssl rsa -pubin -in /tmp/nginx_signing.rsa.pub -outform DER 2>/dev/null | sha256sum | awk '{print $1}' +``` + +#### Build with the new hash (optionally include the old hash during rotation) + + +```bash [Terminal] +docker build \ + --build-arg SIGNING_ALPINE_RSA_PUB_SHA256="," \ + -f src/variations/fpm-nginx/Dockerfile . +``` + +Reference: [Installing NGINX Open Source → Alpine packages](https://docs.nginx.com/nginx/admin-guide/installing-nginx/installing-nginx-open-source/#prebuilt_alpine). + +Why allow multiple hashes? This is optional, but useful during a short rotation window: + +- Ensure CI builds across branches/runners succeed while the upstream key change propagates. +- Avoid flakes from CDN/caching delays where some environments still see the old key. +- Let you pre-stage the new value before the official switch, then remove the old afterwards. + +If you control all builds centrally and can update quickly, pass a single hash. + +## Helping out +If you're really eager to help out, here are a few places to get started: +- Help answer questions on [our GitHub Discussions](https://github.com/serversideup/docker-php/discussions) and [our Discord](https://serversideup.net/discord) +- Chime in on [issues labeled "Help Wanted"](https://github.com/serversideup/docker-php/issues?q=is%3Aissue+is%3Aopen+label%3A%22%F0%9F%99%8F+Help+Wanted%22) +- [Open a feature request](https://github.com/serversideup/docker-php/discussions/66) and tell us how we can improve +- Run performance tests and share your results +- Say good things and tag us on X (formerly Twitter): [@serversideup](https://x.com/serversideup), [@danpastori](https://x.com/danpastori), [@jaydrogers](https://x.com/jaydrogers) From 9751cae8702e1ddb9e5ede4ebfd4bac186afea3a Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 14:15:32 -0500 Subject: [PATCH 065/170] Add CLI documentation for the PHP Docker image, detailing usage, features, and quick start examples for running PHP commands without a web server, enhancing user understanding of the CLI variation. --- docs/content/docs/2.image-variations/cli.md | 78 +++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 docs/content/docs/2.image-variations/cli.md diff --git a/docs/content/docs/2.image-variations/cli.md b/docs/content/docs/2.image-variations/cli.md new file mode 100644 index 000000000..ce863bfe3 --- /dev/null +++ b/docs/content/docs/2.image-variations/cli.md @@ -0,0 +1,78 @@ +--- +title: CLI +description: 'Learn how to use the CLI variation of the serversideup/php image.' +--- + +::lead-p +The CLI variation is a minimal image designed for running PHP from the command line only. It does not include a web server. + +Use this variation for running commands like Composer, running one-off scripts, or executing PHP commands that don't require a web server. +:: + +## When to Use CLI +Use the CLI variation when you need to: + +- Run Composer for dependency management +- Execute one-off PHP scripts +- Need a very small image size + +#### Perfect for +- Running PHP locally without needing to install PHP on your host system. + +#### What's Inside + +| Item | Status | +|------|--------| +| PHP CLI binary | ✅ | +| Common PHP extensions | ✅ | +| `composer` executable | ✅ | +| `install-php-extensions` script | ✅ | +| Essential system utilities | ✅ | +| Native health checks | ❌ | +| Web server | ❌ (no web server included) | +| Process management | Single entrypoint, single process | +| Exposed Ports | None | +| Stop Signal | `SIGTERM` | + +## Quick Start +Here are a few quick examples to get you started. + +### Docker CLI +```bash [Terminal] +docker run -it -v $(pwd):/var/www/html serversideup/php:cli bash +``` + +The above command will mount your current directory as the `/var/www/html` directory in the container and open a bash shell inside the container where PHP is installed. To exit, just type `exit`. + +### Docker Compose +If you want something more repeatable, you can use Docker Compose to start a container with the CLI variation and mount your current directory as the `/var/www/html` directory in the container. + +```yml [compose.yml] +services: + php: + image: serversideup/php:cli + volumes: + - ./:/var/www/html +``` + +Once you have your `compose.yml` file set, you can use the `docker compose` cli to start a container with your configuration. + +```bash [Terminal] +docker compose run -it php bash +``` + +Or you can pass commands directly to the container without starting a shell. + +::note +Don't get confused. `php` is in this command twice because it's the name of the service and the command to run inside the container. If this is too confusing, you can set your service name to something else like `app` in your `compose.yml` file. +:: + +```bash [Terminal] +docker compose run php php my-script.php +``` + +### Further Customization +If you need to customize the container further, reference the docs below: + +- [Environment Variable Specifications](docs/reference/environment-variable-specification) - See which environment variables are available to customize common PHP settings. +- [Command Reference](docs/reference/command-reference) - See which commands are available to run inside the container. From 4fcdae33beafbf1bd5cfe1e1e1b835b690401fe6 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 14:19:15 -0500 Subject: [PATCH 066/170] Add FPM documentation for the PHP Docker image, detailing usage, configuration, and quick start examples for running PHP-FPM in a microservices architecture, enhancing user understanding of the FPM variation and its integration with web servers. --- docs/content/docs/2.image-variations/fpm.md | 224 ++++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 docs/content/docs/2.image-variations/fpm.md diff --git a/docs/content/docs/2.image-variations/fpm.md b/docs/content/docs/2.image-variations/fpm.md new file mode 100644 index 000000000..802027470 --- /dev/null +++ b/docs/content/docs/2.image-variations/fpm.md @@ -0,0 +1,224 @@ +--- +title: FPM +description: 'Learn how to use the FPM variation of the serversideup/php image.' +--- + +::lead-p +The FPM variation runs PHP-FPM (FastCGI Process Manager) without a web server. It's designed to work alongside a separate web server or load balancer that handles static content and proxies PHP requests to this container. + +Use this variation when you're building microservices architectures or have a separate proxy layer handling HTTP traffic. +:: + +## When to Use FPM +Use the FPM variation when you need to: + +- Separate your PHP processing from your web server layer +- Build microservices where PHP runs as a dedicated backend service +- Use a separate load balancer or API gateway to route traffic +- Have an existing NGINX, Traefik, or other reverse proxy infrastructure +- Scale your PHP processing independently from your web server + +#### Perfect for +- Microservices architectures where separation of concerns is important +- Kubernetes deployments with separate service containers +- Large-scale deployments with dedicated load balancers +- Advanced setups where you want full control over your proxy configuration + +#### What's Inside + +| Item | Status | +|------|--------| +| PHP-FPM process manager | ✅ | +| PHP CLI binary | ✅ | +| Common PHP extensions | ✅ | +| `composer` executable | ✅ | +| `install-php-extensions` script | ✅ | +| Essential system utilities | ✅ | +| S6 Overlay (process supervisor) | ✅ | +| Native health checks | ✅ (via [`php-fpm-healthcheck`](https://github.com/renatomefi/php-fpm-healthcheck){target="_blank"} script) | +| Web server | ❌ (requires external web server) | +| Process management | Single entrypoint, single process | +| Exposed Ports | `9000` (FastCGI) | +| Stop Signal | `SIGQUIT` | + +## How FPM Works +Unlike variations that include a web server, the FPM variation only runs PHP-FPM, which listens on port 9000 for FastCGI requests. + +You'll need a separate web server (like NGINX, Apache, or Caddy) to: +1. Accept HTTP requests from clients +2. Serve static files directly (CSS, JavaScript, images) +3. Forward PHP requests to the FPM container on port 9000 +4. Return the PHP-FPM response back to the client + +This architecture gives you maximum flexibility but requires more configuration than the all-in-one variations. + +::note +If you want a simpler setup with everything in one container, consider using the `fpm-nginx`, `fpm-apache`, or `frankenphp` variations instead. These include both the web server and PHP-FPM in a single container. +:: + +## Quick Start +Here are a few examples to help you get started with the FPM variation. + +### Docker Compose with Separate NGINX +This example shows a common setup with PHP-FPM in one container and NGINX in another. + +```yml [compose.yml] +services: + php: + image: serversideup/php:8.4-fpm + volumes: + - ./:/var/www/html + + nginx: + image: nginx:alpine + ports: + - "80:80" + volumes: + - ./:/var/www/html + - ./nginx.conf:/etc/nginx/conf.d/default.conf + depends_on: + - php +``` + +And your NGINX configuration (`nginx.conf`): + +```nginx [nginx.conf] +server { + listen 80; + server_name localhost; + root /var/www/html/public; + + index index.php index.html; + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + fastcgi_pass php:9000; + fastcgi_index index.php; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + include fastcgi_params; + } + + location ~ /\.(?!well-known).* { + deny all; + } +} +``` + +::tip +Notice how the `fastcgi_pass` directive points to `php:9000`. This is the service name from your Docker Compose file. Docker's networking allows services to communicate using their service names. +:: + +### Kubernetes Example +The FPM variation is particularly well-suited for Kubernetes deployments where you might have separate containers in the same pod. + +```yml [deployment.yaml] +apiVersion: apps/v1 +kind: Deployment +metadata: + name: my-app +spec: + replicas: 3 + selector: + matchLabels: + app: my-app + template: + metadata: + labels: + app: my-app + spec: + containers: + - name: nginx + image: nginx:alpine + ports: + - containerPort: 80 + volumeMounts: + - name: app-code + mountPath: /var/www/html + - name: nginx-config + mountPath: /etc/nginx/conf.d + + - name: php-fpm + image: serversideup/php:8.4-fpm + volumeMounts: + - name: app-code + mountPath: /var/www/html + + volumes: + - name: app-code + emptyDir: {} + - name: nginx-config + configMap: + name: nginx-config +``` + +### Health Check +The FPM variation includes [`php-fpm-healthcheck`](https://github.com/renatomefi/php-fpm-healthcheck){target="_blank"}, a POSIX-compliant script that monitors PHP-FPM's `/status` endpoint to verify the service is healthy. + +```yaml [compose.yml]{7-10} +services: + php: + image: serversideup/php:8.4-fpm + volumes: + - ./:/var/www/html + healthcheck: + test: ["CMD", "php-fpm-healthcheck"] + interval: 10s + timeout: 3s + retries: 3 +``` + +::tip +The `php-fpm-healthcheck` script can also monitor specific metrics like accepted connections or queue length. For example, you could fail the health check if the listen queue exceeds 10 processes: `php-fpm-healthcheck --listen-queue=10` +:: + +## Environment Variables +The FPM variation supports extensive customization through environment variables. Here are some common ones: + +| Variable | Default | Description | +|----------|---------|-------------| +| `PHP_FPM_POOL_NAME` | `www` | Name of the PHP-FPM pool | +| `PHP_FPM_PM_CONTROL` | `dynamic` | Process manager control (`dynamic`, `static`, `ondemand`) | +| `PHP_FPM_PM_MAX_CHILDREN` | `20` | Maximum number of child processes | +| `PHP_FPM_PM_START_SERVERS` | `2` | Number of child processes created on startup | +| `PHP_FPM_PM_MIN_SPARE_SERVERS` | `1` | Minimum number of idle processes | +| `PHP_FPM_PM_MAX_SPARE_SERVERS` | `3` | Maximum number of idle processes | +| `PHP_MEMORY_LIMIT` | `256M` | Maximum memory a script can use | +| `PHP_MAX_EXECUTION_TIME` | `99` | Maximum time a script can run (seconds) | + +::tip +For a complete list of available environment variables, see the [Environment Variable Specification →](/docs/reference/environment-variable-specification). +:: + +## Performance Tuning +The FPM variation gives you fine-grained control over PHP process management. Here are some tuning tips: + +### For High-Traffic Applications +```yaml [compose.yml] +services: + php: + image: serversideup/php:8.4-fpm + environment: + PHP_FPM_PM_CONTROL: "static" + PHP_FPM_PM_MAX_CHILDREN: "50" + PHP_MEMORY_LIMIT: "512M" +``` + +### For Low-Memory Environments +```yaml [compose.yml] +services: + php: + image: serversideup/php:8.4-fpm + environment: + PHP_FPM_PM_CONTROL: "ondemand" + PHP_FPM_PM_MAX_CHILDREN: "10" + PHP_FPM_PM_PROCESS_IDLE_TIMEOUT: "10s" +``` + +## Further Customization +If you need to customize the container further, reference the docs below: + +- [Environment Variable Specification](/docs/reference/environment-variable-specification) - See which environment variables are available to customize PHP and PHP-FPM settings. +- [Command Reference](/docs/reference/command-reference) - See which commands are available to run inside the container. From f5fef7cce0d4a9c98ec1ce1ab88971b7096850c8 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 14:24:21 -0500 Subject: [PATCH 067/170] Add FPM-Apache documentation for the PHP Docker image, detailing its features, use cases, and quick start examples, enhancing user understanding of the FPM-Apache variation and its integration with Apache web server. --- .../docs/2.image-variations/fpm-apache.md | 238 ++++++++++++++++++ 1 file changed, 238 insertions(+) create mode 100644 docs/content/docs/2.image-variations/fpm-apache.md diff --git a/docs/content/docs/2.image-variations/fpm-apache.md b/docs/content/docs/2.image-variations/fpm-apache.md new file mode 100644 index 000000000..b2cfa4519 --- /dev/null +++ b/docs/content/docs/2.image-variations/fpm-apache.md @@ -0,0 +1,238 @@ +--- +title: FPM-Apache +description: 'Learn how to use the FPM-Apache variation of the serversideup/php image.' +--- + +::lead-p +The FPM-Apache variation combines PHP-FPM with Apache as a reverse proxy in a single container. Apache serves static content directly and forwards PHP requests to PHP-FPM for processing. + +Use this variation when you need Apache-specific features, `.htaccess` support, or want an all-in-one solution for running PHP applications. +:: + +## When to Use FPM-Apache +Use the FPM-Apache variation when you need to: + +- Run WordPress sites that rely on `.htaccess` configurations +- Use Apache-specific modules like `mod_rewrite` or `mod_security` +- Deploy applications that require `.htaccess` support +- Want an all-in-one container with both web server and PHP processing +- Need Apache's mature ecosystem and widespread documentation + +#### Perfect for +- WordPress hosting with Docker +- Legacy PHP applications that depend on Apache +- Teams familiar with Apache configuration +- Applications requiring `.htaccess` support + +#### What's Inside + +| Item | Status | +|------|--------| +| Apache web server | ✅ | +| PHP-FPM process manager | ✅ | +| PHP CLI binary | ✅ | +| Common PHP extensions | ✅ | +| `composer` executable | ✅ | +| `install-php-extensions` script | ✅ | +| Essential system utilities | ✅ | +| S6 Overlay (process supervisor) | ✅ | +| Native health checks | ✅ (via HTTP endpoint) | +| `.htaccess` support | ✅ | +| SSL/TLS support | ✅ (self-signed certificates or bring your own) | +| Process management | S6 Overlay supervising both Apache and PHP-FPM | +| Exposed Ports | `8080` (HTTP), `8443` (HTTPS) | +| Stop Signal | `SIGQUIT` | + +## How FPM-Apache Works +This variation runs both Apache and PHP-FPM in a single container, managed by S6 Overlay (for the most accurate process supervision). Here's how requests flow: + +::steps{level="4"} + +#### Client sends HTTP request +The container listens on port 8080 (or 8443 for HTTPS) for incoming HTTP requests. + +#### Apache receives the request +Apache receives the request and determines if it's a static file or PHP script. + +#### Check for static files +Static files (CSS, JavaScript, images) are served directly by Apache. + +#### Forward PHP requests to PHP-FPM +PHP requests are forwarded to PHP-FPM via FastCGI protocol. + +#### Process PHP requests with PHP-FPM +PHP-FPM processes the PHP script and returns the result to Apache. + +#### Send the response back to the client +Apache sends the response back to the client. + +:: + +S6 Overlay ensures both Apache and PHP-FPM are running and automatically restarts them if either process fails. + +::note +If you don't specifically need Apache, consider using the [`fpm-nginx`](/docs/image-variations/fpm-nginx) or [`frankenphp`](/docs/image-variations/frankenphp) variations instead. They offer better performance for modern PHP applications. +:: + +## Quick Start +Here are a few examples to help you get started with the FPM-Apache variation. + +### Docker CLI +```bash [Terminal] +docker run -p 80:8080 -v $(pwd):/var/www/html/public serversideup/php:8.4-fpm-apache +``` + +Your application will be available at `http://localhost`. The default document root is `/var/www/html/public`. + +### Docker Compose +::warning +Notice how we're mapping the current directory to `/var/www/html/`, but the actual default document root is `/var/www/html/public`. We're assuming you're creating the `public` directory and putting your PHP code in there. It's not best practice to expose your `compose.yml` file. See the [Installation guide](/docs/getting-started/installation) for a full example. +:: + +This is the recommended approach for local development and production deployments. + +```yml [compose.yml] +services: + php: + image: serversideup/php:8.4-fpm-apache + ports: + - "80:8080" + volumes: + - ./:/var/www/html + environment: + PHP_OPCACHE_ENABLE: "1" +``` + +::tip +The FPM-Apache variation uses ports 8080 and 8443 (instead of 80 and 443) to allow the container to run as a non-root user for better security. +:: + +### WordPress Example +The FPM-Apache variation is excellent for WordPress hosting: + +```yml [compose.yml] +services: + wordpress: + image: serversideup/php:8.4-fpm-apache + ports: + - "8080:8080" + volumes: + - ./wordpress:/var/www/html/public + environment: + PHP_MEMORY_LIMIT: "512M" + PHP_OPCACHE_ENABLE: "1" + depends_on: + - mariadb + + mariadb: + image: mariadb:11 + environment: + MYSQL_ROOT_PASSWORD: rootpassword + MYSQL_DATABASE: wordpress + MYSQL_USER: wordpress + MYSQL_PASSWORD: wordpress + volumes: + - db_data:/var/lib/mysql + +volumes: + db_data: +``` + +### Health Check +The FPM-Apache variation includes a built-in health check that verifies Apache is responding: + +::note +The health check endpoint is configurable via the `HEALTHCHECK_PATH` environment variable, which defaults to `/healthcheck`. +:: + +## SSL/TLS Support +The FPM-Apache variation includes built-in SSL support with self-signed certificates for development. + +### Enabling SSL +```yml [compose.yml] +services: + php: + image: serversideup/php:8.4-fpm-apache + ports: + - "8080:8080" + - "8443:8443" + volumes: + - ./:/var/www/html + environment: + SSL_MODE: "full" +``` + +Available SSL modes: +- `off` - SSL disabled (default) +- `mixed` - Both HTTP (8080) and HTTPS (8443) enabled +- `full` - HTTPS only on port 8443 + +### Custom SSL Certificates +For production, use your own SSL certificates: + +```yml [compose.yml] +services: + php: + image: serversideup/php:8.4-fpm-apache + ports: + - "443:8443" + volumes: + - ./:/var/www/html + - ./certs/server.crt:/etc/ssl/private/self-signed-web.crt:ro + - ./certs/server.key:/etc/ssl/private/self-signed-web.key:ro + environment: + SSL_MODE: "full" +``` + +::warning +For production deployments, consider using a reverse proxy like Traefik or Caddy to handle SSL termination instead of managing certificates in the container. +:: + +## Environment Variables +The FPM-Apache variation supports extensive customization through environment variables. + +### Apache Configuration + +| Variable | Default | Description | +|----------|---------|-------------| +| `APACHE_DOCUMENT_ROOT` | `/var/www/html/public` | Document root for Apache | +| `APACHE_START_SERVERS` | `2` | Number of Apache server processes to start | +| `APACHE_MIN_SPARE_THREADS` | `10` | Minimum idle threads | +| `APACHE_MAX_SPARE_THREADS` | `75` | Maximum idle threads | +| `APACHE_THREADS_PER_CHILD` | `25` | Number of threads per child process | +| `APACHE_MAX_REQUEST_WORKERS` | `150` | Maximum simultaneous connections | +| `APACHE_MAX_CONNECTIONS_PER_CHILD` | `0` | Requests before child process restarts (0 = unlimited) | +| `SSL_MODE` | `off` | SSL mode: `off`, `mixed`, or `full` | +| `SSL_CERTIFICATE_FILE` | `/etc/ssl/private/self-signed-web.crt` | Path to SSL certificate | +| `SSL_PRIVATE_KEY_FILE` | `/etc/ssl/private/self-signed-web.key` | Path to SSL private key | +| `HEALTHCHECK_PATH` | `/healthcheck` | Path for health check endpoint | + +::tip +For a complete list of available environment variables, see the [Environment Variable Specification →](/docs/reference/environment-variable-specification). +:: + +### PHP-FPM Configuration + +| Variable | Default | Description | +|----------|---------|-------------| +| `PHP_FPM_POOL_NAME` | `www` | Name of the PHP-FPM pool | +| `PHP_FPM_PM_CONTROL` | `dynamic` | Process manager control (`dynamic`, `static`, `ondemand`) | +| `PHP_FPM_PM_MAX_CHILDREN` | `20` | Maximum number of child processes | +| `PHP_FPM_PM_START_SERVERS` | `2` | Number of child processes created on startup | +| `PHP_FPM_PM_MIN_SPARE_SERVERS` | `1` | Minimum number of idle processes | +| `PHP_FPM_PM_MAX_SPARE_SERVERS` | `3` | Maximum number of idle processes | +| `PHP_MEMORY_LIMIT` | `256M` | Maximum memory a script can use | +| `PHP_MAX_EXECUTION_TIME` | `99` | Maximum time a script can run (seconds) | +| `PHP_UPLOAD_MAX_FILE_SIZE` | `100M` | Maximum upload file size | +| `PHP_POST_MAX_SIZE` | `100M` | Maximum POST request size | + +::tip +For a complete list of available environment variables, see the [Environment Variable Specification →](/docs/reference/environment-variable-specification). +:: + +## Further Customization +If you need to customize the container further, reference the docs below: + +- [Environment Variable Specification](/docs/reference/environment-variable-specification) - See which environment variables are available to customize PHP and Apache settings. +- [Command Reference](/docs/reference/command-reference) - See which commands are available to run inside the container. + From 89f82f905df63e3239987aaf6ae237d8b16e7293 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 14:55:56 -0500 Subject: [PATCH 068/170] Add custom NGINX configuration icon to app configuration, enhancing visual representation for users managing NGINX setups in Docker. --- docs/app/app.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/app/app.config.ts b/docs/app/app.config.ts index 488992efc..60977991b 100644 --- a/docs/app/app.config.ts +++ b/docs/app/app.config.ts @@ -21,6 +21,7 @@ export default defineAppConfig({ codeIcon: { 'compose.yml': 'i-services-docker', 'compose.yaml': 'i-services-docker', + 'custom-nginx.conf': 'i-services-nginx', 'deployment.yaml': 'i-services-kubernetes', 'deployment.yml': 'i-services-kubernetes', 'docker-compose.yaml': 'i-services-docker', From a40f28991f29db84117aa7807a27b0ba4e34d60d Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 14:56:01 -0500 Subject: [PATCH 069/170] Enhance installation documentation for PHP Docker images by adding detailed steps for starting, stopping, and upgrading the PHP container, including instructions for modifying the `compose.yml` file and refreshing the browser to view changes. --- .../docs/1.getting-started/3.installation.md | 42 +++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/docs/content/docs/1.getting-started/3.installation.md b/docs/content/docs/1.getting-started/3.installation.md index 0d77596d5..33da2321d 100644 --- a/docs/content/docs/1.getting-started/3.installation.md +++ b/docs/content/docs/1.getting-started/3.installation.md @@ -102,15 +102,17 @@ From your project root directory, run the following command to start your PHP ap Make sure you are running the following commands from your **project root directory** (`my-php-project`). If you do not have `compose.yml` in the same directory as you run this command, the command will not work. Also, make sure you don't have any other containers or services that are currently running on port 80. If you do, you will need to stop them before running the following command. :: +::steps{level="4"} + +#### Start the PHP container ```bash [Terminal] docker compose up ``` - You'll see the logs appear in your terminal. **Keep your terminal open** as we'll need it to control the container. ![Terminal output showing Docker Compose successfully starting a PHP container with nginx logs](images/docs/running-php-container.png) -### Viewing your PHP app +#### Viewing your PHP app To view your PHP app, open your browser and navigate to `http://localhost`. You should see the PHP info page showing PHP `8.3` with the `fpm-nginx` variation: ![PHP Info Page](images/docs/php-info.png) @@ -122,21 +124,33 @@ Look for these values in the PHP info page: - `upload_max_filesize` - This should show `250M` - `opcache.enable` - This should show `Off` -To make changes to these settings, we must bring the containers down first before making the changes. +:: -### Stopping your application -To stop the container, press :kbd{value="ctrl"} + :kbd{value="C"} on the original terminal window or you can run the following command from your project root directory: -```bash [Terminal] -docker compose down -``` +### Making changes +::caution +To have our changes take effect, we must restart the containers. +:: + +With our container running, let's make some upgrades to our PHP app: -### Making changes to your PHP app -Let's do something a bit more interesting: 1. Let's upgrade to PHP 8.4 1. Let's use FrankenPHP instead of FPM-NGINX 2. Turn on OPCache 3. Increase the upload limit to 500M +To do this, we need to need to: + +::steps{level="4"} + +#### Stop the container +**Press :kbd{value="ctrl"} + :kbd{value="C"} on the original terminal window** or you can run the following command *in a new terminal window from your project root directory*: +```bash [Terminal] +docker compose down +``` + +#### Making changes to your PHP app +Make the updates below to your `compose.yml` file: + ```yml [compose.yml]{3-4,10-13} services: php: @@ -153,11 +167,13 @@ services: PHP_OPCACHE_ENABLE: "1" ``` -Now let's bring the containers back up again: - +#### Bring the container up again ```bash [Terminal] docker compose up ``` +You'll see the logs appear in your terminal. **Keep your terminal open** as we'll need it to control the container. + +#### Refresh your browser Check `http://localhost` again and you should see the changes we made: @@ -167,6 +183,8 @@ Holy smokes! We've upgraded to PHP 8.4 and you're using FrankenPHP! You can also ![PHP Info Page with Changes to server options](images/docs/php-info-with-changes-options.png) +:: + ## You've got this 💪 You've successfully created your first PHP app with Docker. Better yet, you've seen the power of serversideup/php where it's easy to change your PHP version and variation by changing a single line in your configuration file. From 893671d2abfd58a2a2f603c86aa3e9b8da2c4a92 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 14:56:45 -0500 Subject: [PATCH 070/170] Refine installation documentation for PHP Docker images by removing unnecessary phrasing and clarifying the steps for upgrading the PHP application, enhancing readability and user experience. --- docs/content/docs/1.getting-started/3.installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/1.getting-started/3.installation.md b/docs/content/docs/1.getting-started/3.installation.md index 33da2321d..9b9c8282b 100644 --- a/docs/content/docs/1.getting-started/3.installation.md +++ b/docs/content/docs/1.getting-started/3.installation.md @@ -131,7 +131,7 @@ Look for these values in the PHP info page: To have our changes take effect, we must restart the containers. :: -With our container running, let's make some upgrades to our PHP app: +Let's make some upgrades to our PHP app: 1. Let's upgrade to PHP 8.4 1. Let's use FrankenPHP instead of FPM-NGINX From e43e6b3087a20d27153618d8289b50746b21dd6c Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 15:08:39 -0500 Subject: [PATCH 071/170] Add navigation configuration files for Laravel, WordPress, Platforms, Advanced Guides, and Customization sections, improving documentation structure and accessibility for users. --- docs/content/docs/3.framework-guides/1.laravel/.navigation.yml | 3 +++ .../docs/3.framework-guides/2.wordpress/.navigation.yml | 3 +++ .../4.deployment-and-production/99.platforms/.navigation.yml | 3 +++ docs/content/docs/5.guides/.navigation.yml | 3 +++ docs/content/docs/6.customizing-the-image/.navigation.yml | 3 +++ 5 files changed, 15 insertions(+) create mode 100644 docs/content/docs/3.framework-guides/1.laravel/.navigation.yml create mode 100644 docs/content/docs/3.framework-guides/2.wordpress/.navigation.yml create mode 100644 docs/content/docs/4.deployment-and-production/99.platforms/.navigation.yml create mode 100644 docs/content/docs/5.guides/.navigation.yml create mode 100644 docs/content/docs/6.customizing-the-image/.navigation.yml diff --git a/docs/content/docs/3.framework-guides/1.laravel/.navigation.yml b/docs/content/docs/3.framework-guides/1.laravel/.navigation.yml new file mode 100644 index 000000000..2cbfff2b5 --- /dev/null +++ b/docs/content/docs/3.framework-guides/1.laravel/.navigation.yml @@ -0,0 +1,3 @@ +title: Laravel +icon: false +defaultOpen: false \ No newline at end of file diff --git a/docs/content/docs/3.framework-guides/2.wordpress/.navigation.yml b/docs/content/docs/3.framework-guides/2.wordpress/.navigation.yml new file mode 100644 index 000000000..4de484196 --- /dev/null +++ b/docs/content/docs/3.framework-guides/2.wordpress/.navigation.yml @@ -0,0 +1,3 @@ +title: WordPress +icon: false +defaultOpen: false \ No newline at end of file diff --git a/docs/content/docs/4.deployment-and-production/99.platforms/.navigation.yml b/docs/content/docs/4.deployment-and-production/99.platforms/.navigation.yml new file mode 100644 index 000000000..85283371c --- /dev/null +++ b/docs/content/docs/4.deployment-and-production/99.platforms/.navigation.yml @@ -0,0 +1,3 @@ +title: Platforms +icon: false +defaultOpen: false \ No newline at end of file diff --git a/docs/content/docs/5.guides/.navigation.yml b/docs/content/docs/5.guides/.navigation.yml new file mode 100644 index 000000000..a5d442aa1 --- /dev/null +++ b/docs/content/docs/5.guides/.navigation.yml @@ -0,0 +1,3 @@ +title: Advanced Guides +icon: false +defaultOpen: false \ No newline at end of file diff --git a/docs/content/docs/6.customizing-the-image/.navigation.yml b/docs/content/docs/6.customizing-the-image/.navigation.yml new file mode 100644 index 000000000..a2603f1c3 --- /dev/null +++ b/docs/content/docs/6.customizing-the-image/.navigation.yml @@ -0,0 +1,3 @@ +title: Customization +icon: false +defaultOpen: false \ No newline at end of file From 281b058bc168b10e4c5b1f53dc49ee0f6317c435 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 15:08:46 -0500 Subject: [PATCH 072/170] Add documentation for NGINX Unit variation, noting its archival status and recommending migration to FrankenPHP, enhancing user awareness of unsupported features. --- docs/content/docs/2.image-variations/unit.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 docs/content/docs/2.image-variations/unit.md diff --git a/docs/content/docs/2.image-variations/unit.md b/docs/content/docs/2.image-variations/unit.md new file mode 100644 index 000000000..20c0917bd --- /dev/null +++ b/docs/content/docs/2.image-variations/unit.md @@ -0,0 +1,14 @@ +--- +title: Unit +description: 'Unit was offered as a variation, but the entire project was archived in October 2025. This variation is no longer supported.' +--- + +## Unit was archived by NGINX and is no longer maintained +::caution +In October 2025, NGINX stopped supporting NGINX Unit and archived the project. NGINX Unit will eventually be removed from our project. [See the official announcement →](https://github.com/nginx/unit?tab=readme-ov-file#nginx-unit){target="_blank"} +:: + +## Consider migrating to FrankenPHP +If you are using the Unit variation, consider migrating to FrankenPHP for a single-process alternative. + +:u-button{to="/docs/image-variations/frankenphp" label="Learn more about the FrankenPHP variation" aria-label="Learn more about the FrankenPHP variation" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file From 2578bfb6829a1f06cd543735063adcd836809e53 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 15:08:58 -0500 Subject: [PATCH 073/170] Add container basics documentation, introducing key concepts of containerization, benefits, and getting started with Docker, enhancing user understanding of deploying PHP applications in containers. --- .../{1.container-concepts.md => 1.container-basics.md} | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) rename docs/content/docs/4.deployment-and-production/{1.container-concepts.md => 1.container-basics.md} (93%) diff --git a/docs/content/docs/4.deployment-and-production/1.container-concepts.md b/docs/content/docs/4.deployment-and-production/1.container-basics.md similarity index 93% rename from docs/content/docs/4.deployment-and-production/1.container-concepts.md rename to docs/content/docs/4.deployment-and-production/1.container-basics.md index 5ca16e2bc..a7c72d0cb 100644 --- a/docs/content/docs/4.deployment-and-production/1.container-concepts.md +++ b/docs/content/docs/4.deployment-and-production/1.container-basics.md @@ -1,5 +1,5 @@ --- -title: Container Concepts +title: Container Basics description: 'Learn the basics of containers with PHP and how to use it to deploy your PHP applications.' --- @@ -45,5 +45,4 @@ These images work with any Docker setup — Docker Compose, Docker Swarm, Kubern Spin is free and open source, and it's a great way to get started with Docker if you're looking for a free method to deploy to any VPS provider. -::u-button{to="https://serversideup.net/open-source/spin/" label="Learn more about Spin" aria-label="Learn more about Spin" target="_blank" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} -:: \ No newline at end of file +:u-button{to="https://serversideup.net/open-source/spin/" label="Learn more about Spin" aria-label="Learn more about Spin" target="_blank" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file From ad01f07ee8fbbab2921d446ee6cc005b424a2f97 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 15:13:10 -0500 Subject: [PATCH 074/170] Add navigation entry for Orchestrators in deployment documentation, improving structure and accessibility for users exploring orchestration options in PHP Docker environments. --- .../98.orchestrators/.navigation.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 docs/content/docs/4.deployment-and-production/98.orchestrators/.navigation.yml diff --git a/docs/content/docs/4.deployment-and-production/98.orchestrators/.navigation.yml b/docs/content/docs/4.deployment-and-production/98.orchestrators/.navigation.yml new file mode 100644 index 000000000..13126c183 --- /dev/null +++ b/docs/content/docs/4.deployment-and-production/98.orchestrators/.navigation.yml @@ -0,0 +1,3 @@ +title: Orchestrators +icon: false +defaultOpen: false \ No newline at end of file From a870c2e535afd97fa2c98e4905b0c684a0ffbcd2 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 15:33:52 -0500 Subject: [PATCH 075/170] Update FPM-Apache documentation to include SSL configuration and additional port mappings, enhancing security and accessibility for users deploying PHP applications with HTTPS support. --- docs/content/docs/2.image-variations/fpm-apache.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/content/docs/2.image-variations/fpm-apache.md b/docs/content/docs/2.image-variations/fpm-apache.md index b2cfa4519..9ed604cf9 100644 --- a/docs/content/docs/2.image-variations/fpm-apache.md +++ b/docs/content/docs/2.image-variations/fpm-apache.md @@ -97,10 +97,12 @@ services: image: serversideup/php:8.4-fpm-apache ports: - "80:8080" + - "443:8443" volumes: - ./:/var/www/html environment: PHP_OPCACHE_ENABLE: "1" + SSL_MODE: "full" ``` ::tip @@ -115,10 +117,12 @@ services: wordpress: image: serversideup/php:8.4-fpm-apache ports: - - "8080:8080" + - "80:8080" + - "443:8443" volumes: - - ./wordpress:/var/www/html/public + - ./wordpress:/var/www/html environment: + SSL_MODE: "full" PHP_MEMORY_LIMIT: "512M" PHP_OPCACHE_ENABLE: "1" depends_on: From f15e0b8a52853eecb7a5f6557bfa13cd820af52b Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 15:34:11 -0500 Subject: [PATCH 076/170] Add new SVG and PNG images for documentation, including container initialization, Docker layers, permissions, reverse proxy, S6 overlay, and supervisor container visuals, enhancing the visual representation and understanding of containerization concepts in PHP Docker environments. --- docs/public/images/docs/container-init.svg | 79 +++++++++++ docs/public/images/docs/docker-layers.png | Bin 0 -> 76743 bytes .../images/docs/permissions-privileged.png | Bin 0 -> 84041 bytes docs/public/images/docs/reverse-proxy.svg | 126 ++++++++++++++++++ .../images/docs/s6-overlay-container.svg | 72 ++++++++++ .../images/docs/supervisor-container.svg | 73 ++++++++++ 6 files changed, 350 insertions(+) create mode 100644 docs/public/images/docs/container-init.svg create mode 100644 docs/public/images/docs/docker-layers.png create mode 100644 docs/public/images/docs/permissions-privileged.png create mode 100644 docs/public/images/docs/reverse-proxy.svg create mode 100644 docs/public/images/docs/s6-overlay-container.svg create mode 100644 docs/public/images/docs/supervisor-container.svg diff --git a/docs/public/images/docs/container-init.svg b/docs/public/images/docs/container-init.svg new file mode 100644 index 000000000..ef5dd7e48 --- /dev/null +++ b/docs/public/images/docs/container-init.svg @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/public/images/docs/docker-layers.png b/docs/public/images/docs/docker-layers.png new file mode 100644 index 0000000000000000000000000000000000000000..76526583fe991934700bb9e870bf9919d73eafe4 GIT binary patch literal 76743 zcmbSyby!qg_vj#qh~yv$C^a0qB$O7A0cL2VB}9;tl5PQ!77DWP{ScB}cHe+$TG2=_uB z(1Sz!Z3Qb`hUMgb?C$Q4#r<%!wwgVCt8o0_pl~f285zGWU19l{TNf^x=TAAf9>wLC zH_o0s6p^c&Jh02JfT<#Q_{18fkE(_@zl?65oE#Q+%7@fy-FQj3cDA6cl9lP`~J<&&OuR0qrSc#+o$vPZNOE% z{f7@9JiYw}HnCw*O>e$o1Kxkh?;j&4CqJ&SA08P_tL~I|0)M6(8&}fuKCMI#y)q#K zSqO`6ZEa2b{GFDT_A?r7XqpTFfQ@~wZY}nuW#*od!P*ISeSIT2vtuf&_~FBczg=8o zlD;Zw>P2pxWf%74HDzjQYC=8370VCS+KnDpFCBJhWQ}1%d$E6@QpIIIYZtI5UYMx5 zYAv0YCPsRJacNFp2Abpl{Fpfy_~v3{gD8T3AUXYXWccKy$UdQS7$o1hpOy_b>p z2DL2_mm57+33-FH9q>x*1?TZalEL$Ws0m8>-j>ZE5VFt7rSj^`L=)A_+vL(Q~URDWJT_~gwCbw zUlE;8o|rdbwNtSiVb?j&1E*$MRo?{M?8nA`?Mc?w>1$5zu+HM|!Ip+D>}kR3yGMVP z)Ke#3TeoiZejgP)zW)C8?em@MB(EP)fwoS@sGgTb_lvNsDO)){I*pOW!uh9@T{(vt*9e_C9o~dhtm}Oh%KLk>k?anisy?LlvVHPkDI1m>%ANwM<;=w}1wpd7O zME>YNme0d=5FV!m94e>dHMKP(7qKWy8@fOgv2A5$la`ZuC#5}rS3fJqkrJlW_?)0} zfb@oKlRQ(7fM74}NYs!?KuCU`clMp8`)W_RG0XN>)jpG*SYyi}vKQU@^w}QEsqy6% z!pCB%=0bF(128&dmtuc4M5xg1Jc@xmep6Th8%5qZvJq8!l=?&IRqvly^!|kn{r0AM z8k+>5z466AijGy@J}mJRPnyj>5qxHE{>26zOO;%DHS{5B^VLSUs<2MsMmiTni0M4a z8T>)@IJ@7xGL;>oz1eEl2Ya#JIPi()HpuLXUd%M=eb<-dZAbRn^Qdv_p|+?&>+W#X z{m-cqkm29LA>lp|iQxP(YkTMq9O#aaHfeI#aq8B!aK&v<@2okUj|LwQH9pU@EpKV; zV}+yl-BRev!CwAOIcHOS^cL5N41%-YspxZ62Ba;3>u|BWunHL!Uhhn7 zfnVXeH!1(|nxrC9tDjqP_IQ%4lDihbzZ zmv|m^m8HsvELQPnuS$!$Zna$$R?LQnb&2^ac0(ZX0V=qzaeo{TiSHU&dUY91;#2`@ z`x27T#Nc5BN@3mA_Vjhj2DO`0!2YVX21;)u1fvixC zKXt9Ee)~vy_VEe!+qLdN)S)|$vAs2^w=l*#Bz-5!Jgkv2Nv})Tlb*Ybo)p9seiM=V z*pLm^C4E->DB}BZfIuptZ8&|*y;{G)kz9ocAtx28;>P}=*g};FY|jM;`!$copAH^S zO73ykD-$zKpQk$h#kF(M-wozIHf3L3I9%07Xdzpr$amJSy>5cEMJ~qXZUlU?z8QL# z)!f^}ckOAZ?MWEBmae5#kv!~?d;c-}5QXmXGbMLzrReU+f(9D#EY=5ZHpRWc!TqjA z4b@JAr+zMC%~nKbYE{_y3yq9JcT2s!+wDQpvrH8rvk0rI3YqbF>-U(ioGeM>M)%&$ z&q~`nuF1CcUCs92TB{NLF^maXzlOmG9;#Knj}v2#G>0CQUWo5;r>9U|DG4v-A@I}K zaN|g&0DF+~B|?FL6{11m9CM4wxS5$P3;K7!7rjy^hZ;k}!>h`k?y0n_`4Rs!-WHZ+ z-IA@T_}0^>zj&Ucc-{D?l-1H|CHjseBkQ7?qvzMzIPeAKUu6+frqSj9wAyyRj9!0# z;N0imLPZ)rX*$YegPX0(TINhR&7uHzbUwes&dAlDWkJV10%6^PE2Hv7QJBpm~wLqbN#O}vQumm-<>9I$b z21c%L3G))&EAhvBVfIy_caFugOS%%gX=ObujUYL1kq^%nby9?&rLBn7e799$@mrcWcwou;CQBZ) z)!Fpx@dYP1$U$PXYB)=wFZ%Q$JpdL~u1>6rsMuX1GmCt(G1-x&ddj^2>+HUHQ@(sD zIQh@9{|uhJmj4%Pc%Q;Fqlp9i4)3{}yQj9$`nua^Y*s#TZ{GBoM~iD+1fOIB5dj4u4U*1W zT-WA^U%n;P2GW2z@LznqeNylTVZ`Q_4}SDNGgk+0gkvhhp}C~R_YmSpB4%*UkVqK} z7641(s2 zh5=J?J{^7kV2d0w7IS2m0yBtO|HEfwCKPIpfI>doLU57=(DxAUcK{zXNe(a`)Lg4j z@h*b*b37;5=^x58NSGhs5tHr;p_Bz^+5zMpNkqV8qeaG#pob*i#bfwV`(4yOOPi>- zjZJG0IyP|LoYix4Gb)^YJf+Q?!xE@~;Yt7$I(JGsWCP8@-`{7V#JBTxZ`+_P2zp?qy-Ie^W zjO6zhh`ZWUa#_$Sf8}QYh1@d$-%p%i`P&Q5B&ex)JZ&tDppqTz8xCdH08ai&UNGq{ z!WAdTCD>&#A0;5sKfrR@;LZeTEU<4EhbUrL206X6osc>@*X;6frK@vU8xF}t2 z`QU*11Mt7q|K)yYqdw3sX6z734sbw>h)#FaC?6``~5sTTX?=`gMiHrGwS^x3#mTFPv&G zbYH4rET=5Qo-ipu;ywydBKU?QG2bI_)})CTgJ!@VD5c`WsSQDQR73Xt6{ITJU8102 zV9CFVK~g}Cm^YxLvV$aHH2xWZ?r~OU^ku#H3(7LYgV{L-h!*56GZ@cwLNYyxE9W7} zAJ+&$SkyTlgpGje?FX<3H%1IH263j8>-)w2RpH^!jv+OJvgdcHs$Ww>(`mlgP!Ui% zoZn)Im8cj?wVKN*wBLzjp7WOKIIN@Pca$ar(E1cgGta)qQiES1BUBg$JRu?HT)JCCsh03`^-jA&j27WPnHn`ifbWLhbvd4=F# z+(JRwX}1LDOKR<#*P zW`yd0$lh~X>;8e_eB%29Mme635Rggbs*%_Q%L_3)<#zO#WI^~7pol;dcFYLg>z!?@ z-0&AI_FLgt~1UjlcFMG6mv-1`vRLp$V7ji-TH4c%?gp zZ%Xf<=&rTCeLM&=8Fz#3%zvOYxO_kEps@Iu0B*kf7vv<(Vw`EF@z1gZfNbB1hoa$> zwP?&Zpmtf2t(M>zrI@pOc|WK)M@=0%c-wAo9H0~!zCIk8kHz)B?XAmIzw@`uO(neG zOcnF<%gr%hTr z#OlR95eT%!su82j_~0gq2S1{}K9=bT#iVbuLY&w2_fjW~-TPR@{*zm8tj<37?yN2- z-w|0JfoEoJ{c^UV;znHBUlHExVChj-z(-9;rtNmHfjbv47cvT zoJZM&Hpx2e#ppS_@o)%AoA&Fya=yInjydZ!^j(fCaWI9o8i6(BzyUXK`T&Z_M;Ux;SWyT%~j-;YAIvnl_=T~ru78GWF z3kCs!WWg8hG$@0Df1q0d@NJUAdeMmJQB;aTBNB6@s4m|V@}q2pP{V!bq7UVTHvm-r zN3s4I&{J@#Eksgbh6;X{p&(ohd2xaI{oe0O?W9aTV7{c>`j0})xneh zwAKMD7(zOQ8k6*>ABRH4G6K5$>LWjX{kRjz%D+;HI8 zdI?bhw~s|_F+yRBGK4rg{5&oT_LRL+UF_onkcsS-+L&V$XM=MNr@~exne*a)EOp+o zehJ0Uit7E}xpMt_eVsoZ#L|uGa2YnEMqLYDeU|vdhMc6kf3iimEz6Z~q(804o_2Wn zAlHa9X1@yfaU3-y;M2CV8bE@Rl37I%P~#+05eVXyZ#D`Dsh(S@lDbN84?l4_c+3-Ip|P?f|lilbd~h6bRDU zYW35`ShDH~3~y|iv4q}@?egZdY&YSK*RfdukBT;K*m18I2e)||CuV!FA!k!npRjFa zx4V=M_{=4E2x$*h6Wyv_n>agr9fLZMl9zlm#WUhqSM2+p@we&20}C_{BKRAh^++@2 zdaA!PVUQk-5QPaK`fpFpHXGCFY$2=)GX`LW(VoiuAB(rPx0ynj_ViFhGCENrz45$M zQrh%}bj8GziQ#H(f>dS5?-q-vCq7yu?o1&TuUUgzSq9k>zLF5K ztock`UQF{bnMIIXN~e8i9qU_1&{Z2&RNDe2A!a zL*0sI`(WSz(7*cs7X1alIcj!=8DnswmPfAIh!0ZrlUiYBceG*%|M0-gN5*7X{3CS< zn2q3&R@JdWw@+)`D=(J%Cv!teM7)g{2c21sY)aml!gRAfdY4)1h`P@D9GhOa%B?)F z+xW~y(k#0R%WcdR9xs1#lHi#A;H$=Obc0%Q_uG59!s(v1WgkF;%u4}eCcDrxoTl33Z!BZT_iDJtzIcz65jdI@A5<2X z*Xr1nJ7;{-$u@W{YN(=Cj@I`uCs-v!r=T1)SemV&=aiGNn9_$85Y%>UYd=IT+3jUZi3 zqk1$x{H~j{_)pzw6L)E$ia0XoM!H@2CEow|gHClSL#{<1xSN$98^=>c3T{_ro#e4< z1wQ^H-DHBsBo4_^Dsmt4mtFRuMD4&_UKfhAOc*Z zyxgTX`1nSJ$O=cnT}Ac=qq$AWGv@Tij|^U}{ctjg=*E78+btWb@V zNcult2pUpY*~l$2%*pg9f1NXIQAxSIVHPs@Fh{@Cbnw+`wUsLBx0#~KqqlX8xEMBk zUv<&*q~B!xIfS@v4$K#YaC-UeG16=ipCVUBasm8dacC=u!b5@6zJ`Ju%x!DGE>^%G z@Y2D~V*5UkD>AjpnrYuf>cVSGKV?a#*F5wxS-{R}Y=-pj+}va<3$~nj$&R$5vZZlu z1uA_(!Ak5hM32|WZdtD;M_k>gO(Ih2C2UYG zov6u0Id(1rXydSNkjnOPTW0P@A1tH1m8Z_X1w02^aPXzxMxmWhDa*%?g`qA1whP<1 zDSL$P{({%~vi`w73g%X^H5y2^PRnkN@gTFo=)qO@eS4+Tm)^V^?(@X|J919+anRd; zxDj_+ug)J?v;xoh2OqN?s%j7P%gr-Rr-d8I9~jHolnv!RfPd>dI#peyuuNWjFk)1= zDKa!0dR;T|d?2JX^U`5fWzichY=b#T0Z_C{^jhmG2Ro0Hhp8Csc!xzKI!qKN2)PhU zqMZy%_ll1#;MEjgx&*7g9~wKMIQx5553>B;VP-fG+w@vmkIX$^eoJO2tX6F8tR zy&186m(z@%U$L6O=(e(+RM-XM)T!n~H!Q!J&qD(9Jy+h`0{kLzJRXQ5>UW)xZZh7rQppN@-b$v+FVVWdOE%L_PNpPqIGkb z8f|s3bmN+JQZ%n!y$V=m+>n*V0>a#v6kP^SER=Ta8D`@cCAy0%V*-a-1M*crheZ1&zw=7^5q zHhIb>Siy#(^%Wyd#JC}$@h2)8s*VPuZT#PT8GD-Y&fhz#EF!F~HNS+fs?vBQLg41E z_aOuMrf>-L=R($xG1I7c=u0a>N1nBBSYden)Fjfh!zEtkaUQBTTJ#OS2kY9V%t|M(oF}C{blz zfjj>siW4Cx_w?tiwsqvG+vOH@i=HNnps`;iZH^@VjPHT-{XC zaqsr~j@KUYskCUMY3#p9zPre#(ObhAE-BDUQ!>z_wqgpttnWXv7dV&>mivn`zv z*q8a$GhoUc-x;oPrg>2L-bt>W3sI~JCeO0{^m~q7^2^i%^AOw77l}{}(YkQGl#_Qq zM;#9Y_XW7WLveYbjdC0?Lr-c%oE{FFtPm4HPAX1`k>Z|Qzp-~S#Jf8$H_QB*!bjB6u-`aq^* z%OhcS1aHH=wGO@=1u&9HN&bsSWCeh<`Pf7dV+>wldy~*T!-LS|+!y?>_l!(VggTXF z%(_c_5oDcP*7(T%$l!uaOKN3WY0z16T6F{HUhegM29|C%dMNSOOUCt4iSL6%Wn~SO z2;212S-(uovZ|FH1HpTRS2L@+MJtKwU^JBGB4Ihbnmm&O34NZZ)f)9w(4iif<1Ng* zIA?^vH=h!c1>^l)PQ0Lg(efF1UW1ZZ_89X{kNSC$AermsU*tQHOy9_9Z;cWV?Gd=p zw)3f>%j*!QWJ2u)2RDnMOG=bUBz8E9X;A9(-?Mmw)AfZd!ZhAJ+;Q8zOKGViUcmDxVf{|@8$PD>uB=43x#sWC^-LEZ zzIoehpvLAvTA;p;o zKV!ffdf+-0w`R>2TS*&>NA;n%Qpjx?*#C9p=K1o#%gQQ51X8DEVTe@rAyr*}D2)iW zpnxwYXNScbgEt4e3i%eRHNZW3&L!Pi;m>PoJSV=^&img)d6E8)w_!swALQ4QZ_cvj zOeYypCf`Q72+QxhQorl>)x}T~%?RoD8E zC8lp$=5W?T@+PRId~Bm~Bu1-}kvGSp=+<)K^DdP|C_$x8;_6^88KWupN9$~Si4e{l zWu+qR_k>bD>OmUNsQoG-IB(C}H-=C?u*C}k?ef`94f!!=lmWjD zU-ZWn`#IYZPdF%}7d99`BsTl;w zbkPN#0_?WlHtTZ=T#T~=r(UsHwp>B9&iz!GrsPGl5h+julA9x)<7lF>SfiTnK!4lS zkW`hz#zA8sS5db43(#=j`QYPoj|Zm=!3U`?-DK#Y0VK}Ve7j*a<_6ss384*Ki=9d=_8{zIU_n zL-puu+}45of-Af!ry%;d0i?1q87wS|c zJb!-)F)Xhu2b)N=q|{g|l$VsV7L&wbBp3OC{qKLg=9;g5HGT_bYQYC-TsxjGXX^KJ zd}AW{Wq7*a+Do2|_duX#W=kd*5b7;qd8NH*a(k-4Iis-nJt1o2Bb&tY%f6QJ^@Y@B$6W@=QQw>18VOn28LhrBx%yZ(YS&Qk zie{%25Z3J^S4i^r(q|FZ9&qA0rHEB z{mkU$@8nO`ys#(1-&~oR@Im8#yqBgvD@_Axt9hP*)(aN{f--LjiJC^TFxhXMBDCGW^2!|ENzEteZFm5zJH!>%{np~1cm3{OdS{v$MFN2@G{UJI&a}4S0 z*j>pQ>2AJYU%Os$Z_{+Tol#oFw!a#*n_UW93==&wN|U=;9tRPHzR}ovu-nIOq*4S- zePm%%g)JtU5NtU*lAQb*ylA!2g3_kwHeiEgWWg*5ERx|5NvPRF$Xr@6B+*x#NRv1=F z;06p52-LhE6h`=p!I$gN+4%?^a32Y}H>rs~ zkCHoVE8G z`vqL)VUmH}!x~VHGi}^P49v z<7u;lo`vtK*pVfQ*8O`RL)2xd0pUyiL=*IOKzY@+AQ8jWpjEH~G0K1tKs#)ia$w%zrN8b&EXwPnrNw1c~ zacQ{c$P9`OKwyig3FqDZS`PAEIqZ`g75}qa7JRcZy(y_eIqh`m&NJwqKKRck zdGI|1&L^Y=Y3Rg~gNxb3IyVw9(8{XkH-9L6fUa7S<|@Kf5hhej3$#VHsSLy)Q=YlL z2pX{Q=p-%C0XL$56Ym!VIU^Hc=A0Y+xXr^jOu^nzR9zJr(IZI+9L$rCh@Eft4Z2IY z{NTIGA^3A^tf~CZDDv|9?s<~v`wXM(h=}d%)}BKQ*P#zx&@;UxOdt{?LUE)vn*5Q; zTb=ueO=l?FvnC%3u0nmyXAC~Q@rTtEY~oJ_>FNq5Le-HlrcjcP$sw(_918^k8WUR2 zwkP>PpJ$rxZtdocQ@|2vAIjw}G9X;z(f}=;JgxR0oqU2+(M=72Rj+*^+V8{2wAbiD z@z3O+;ER}e?vDVOWpL`|jW9B}v9OfLff9om(OrkdlGV|R+*d*aV^Hu)6(diq zoK(a6WawJQWtZm2EHSDR4{p!Y*zxF1`BN~ShiGlY4>*J}QVddSolA{KZU4*&@AVQu zao!Q|Do$-@E>QqemAnE^=9m^l%SIbqH&+CqVNJ@3840^)eVtNS93sNu)EtN%^)J7d zgQMf1gfR0vbZiLR&Jo<6E;=4sAwL>%KFba_2qhkfbLE)&R$*NX0V_@=1JDS|`evHkDg zU^vO0_$U2t@;Un`;V>@!0IrxBeP-I*Tx|LBdDxDLxc7L#AkLk+|4N0%1xNF2=Xs-G zE9MhxPVp@kJcsOQq&QXEPa-W=z9Kb38SYY%+-*e|9&Qxa7)6$=ftRicWthAxsMOiA z(pe=}?ESmrs@?B09!MwEU*wifM6f4Ekb{>nx`bL)UI4U(XStKnw9D03wV8AI-5g^I2{Oz8T7 zEoXS8OmJZ`Rx+L>u~flhJId!_Zjv-rSPScd|hw6|+Ct!xS22qQ{LA9CY? zFA7$6HQ%ygE9$U%FUq$|lEXqnLW5u$51A*m#P-DA zfvkJbrz~rCj7{TBYi?X@ga%p3|^jd`KHUc#GUu$W*5}n=J z-@RgVs{r{Gsey%M?C52)`5bf@o0yRMO3YWE^eNHbumFMWM;(z!1AatI=#Aj`5WGk@ z8)Xh^f+-EI(~`&breTSn4e9qAS!%dGz24dG0arb#A^s(a_6I40GJjRS18C&EIEvhx zTJ#GU711-%Qx>{BumA{alq3=cA?f64vE#go0R%s29(|pMi*H6NL!PpsJ#<| z0}KZB8%)55yS=eY9+U0$5fNHG+at^f11*R^QRPa=HUay^C}U|B#>j!=>%s8b zS^J7fxy(egW#fLaIehtrm2e_Pr(h2!o)0+ja3i|UJ`MLVxO_yxtSpP~RHkx#irYqs z@z1`-SJN7iHDtkQSB-$E!;fO{ryDgL^z9CE>6@N@#+B-O29`p~u_2F*E#2w<3@ap$dxO4knZSKf^SM+l>=dMO_ZUhBRLw-I&L@1lb&XfZ50-2$I zI31yH1OyQ5`dK0dQq=q!Lk%AAM4oUFaRecyE*P5yv^XYV{L8oz zSZ;0viH}E>%Xks+^!h%$`uN?!G>Z0xGB}!{q>bf-4Y6{Q4L#$}?mY0tDceyGez{o$ zn7b`SxXk|r(12IFblvSf1>1qq?4jKUgv8|SEh#{alkr!rDGO@nrEapTz-MF07&L@Y zqksKJVgM)+8mOG>^2aY8gA*B*4*2U^{rXQU`efaw#-1Rc$++18o*R{d1pV-X8 z+UBP`;23DFT%i|)u4dAF%H33aZk8QEQ%9@u&4hQDvDE5}TcRko61fS`xC)aWgLiYi z3r)bJXHi#qf&xiFLeE$Z34!u;Fv-$;>0+!b}Cb+HP41qLpW~J zGy17ZaP_@lLs<)6seq_P-gysRCf!4H*#m9neVij0KcY#4Qg&!kO?=94FQ$MmKWzhG= z%Mft5=avn3-u&`{%s()ZZQq1iLZTE9!kJ$v&irIp5GCO_X(B8GM~3k~KN&FU{K<=u z+IOyG`+g@9%%J&>b(ey?hmCTkbPs*#e!`btP~B0Y4kM9K-xga~__&x9h~_Wc>zYBE zfMZengo)5_oFm71@Rj>M9-KaNKYVjQ{SM#%!Ly(X$Nc4c z$59U#-Q{b;f#Q!0FNPdtz01rHwqH~hcPMUnJu{doh~q$fBJ(~fEH+jwy8|FmUiwLP zDluXv_sHhRN9?97Mv=)+ZiNaPN?aD*I~*MdwEy_)$}uAzYE6`50=CEvLGgcDM6fp}(55(_0%b3|K2eDG zK|6|;$|8fY6Q-K6GKv2tv(SM3p>lmk+Fe@r{=~%vifzNeNLM?sblp!*L^=56Uh^kZ zCvM8P-wNyx8)}X90IzRm+~!8e%59jDx^O5(uz<OK2 z{QK}Iv(*t!M4gW31dTd_^*cBg_{Hq*S-UES@)TK68i+*s3M&> zg+1_9g&>)cUgrF3=>p2eqVxBj9xbZ4a>(@Df&qlOc)!St++w?zSOxcK`NxWHHQ2R# zaPV<}iX?w@-{2)dPftg=*j+`T-LnWOp$G3Ss}tZ*AgfP5ld^!N`kIUt6dw1g-ljON8)+ z+q>=$u`pG-_U_&3v|8(uR3xoSWAFB@x1M4kiCVpvA=^vJx~hp)A}Heh=xPeOtdEFZ#lA32^75)lsd_+z=mpg7*N z*-y<1#;fg_(LTA;w(mOH^ghp%F!~0vvlv?H+3Hyq6Ae8tOjd^MgIdm_nOxCI$=kaJ z{)R+@!PBeXN1x51>OB90{LIoS`{OL_M?ey6dmcp`_cY|$_-wrRuE$se1LBgl^sCv< z@6-B&od{trC*4nk$WGfsgdS)%IaLpdgjHyl0bufl^HS`}=CSe5Mb`b5gYvT`iria& zN*nve0cExw{fpD07_xBa+h83oyEQ?TyP{wV9~{Lp8Q@A+_LzH;IS4M5$23$LlPZbGKlr8j6SacD=@W)Zt{4m zEaDm4GgtsqGB)PMjEhEGX6#$>vuoD2MiOhcfSd-H>OTp z5?T4F0}kr?i0?!|7uUU`Fe^Nh%6FwtXZ*Zy{f7g@EbpO<2=6K7OHP?S4#@0V`#EF2 z=*B<7uFl#D7EhG%L?p|CAE+{qhKOuFCp-h(PFZpvB}1<|q3 z@gC$5N>Dgv-S+Xw<1zhWFMdkV+dNwH^pA&j8u}*CK??_?_KSyK$m3>OzOHM!;AO@9n7)ASXGi?*oG9z z7Ue6O&H!Ga$NBF`sh=f3ef>pcq~M_@a=9sdLye9=elSjhN>?e4FY@d4pL30K$}CEM zB|nb&5CKXgHk^IG40Di_@&p}l0#TA0hMecE%8MW%kTlF@WhG)3L&be{$mSork-&Id zh@zm9%M}QbmV9<{fBi%zKaTiu+%T4AG}LQiA7!r8T;(0DKBcWY3js|}?_4*V|VAYhse+gY*+ zUypn={Wy+g4A6ye2Gex1+<;Cc*xcMcQ!KDa<`lKj*v7hJDO(^}it(I~T=*quk!FcP z95b&V75xv^Qx*)Nwwp^_BMqwRP}9>v)%APY*CbnfAv{~(dvdF4%~wpvyHtxzga61# zCcFr{M3{mmuB|3(yIr9o7;OwGD}WmxA zzu^hCGJs(*`(Gg_yqzqwpvPTX36;Ax*)@HQrvp*~H?bs;|5*~iS9!S5EQ9GTX0BMuy@V|?Y z%{;&*Oc4Ejyk^5?Yy4&4Z<-A*3FOA#oD*Df2i{v=3GnoI*uWaQoc{yt3KY@?zY~M8 z(p6+yru15F0N> zt|kf=ZuX{>Nmn)UiVCBohWB0ho|0y>HRN0ERVm^U@Me%HHu5Y_lBSYwKg{|vmgFBc zzo@nN)b5U87>ppWj&=V7smlK6(U?pSqaOr~-J7;}0+uPM5XHI3skeVR_K+!d@>~P1 zJlmW%PvzTSy$H+)(^3sxe_RgEhm}eh!dOi3WBV0v$?YkaY)EPQG3VeYNehfdup%B) zHen$J=8-Oq0R>8qUuoS?ss4)FL->M$Emq1(f|Vf@)Su3iV|U&w;u7-i?mg1sru zVu;B3#-XyTw2yfQg(yZroiBR!((V5?DC8=H!Dzfq+25*Q{>W%SoIQLL&808zqY*e6 zz|#zXPfLwY(_tBz?ryC*jLcwMPDzRrpy(3v7%3(R&EI+-y9mwmgVnAdkhPJMy(9XT9FIx7%q)T} zCd&i+4HWRZ1acH`UL`;a_xktabkR5m;JgaEhMt6LC6{EL z1U)7Iq3&C8@#?G2$|vRcCF|ePdI{>I!=mmV`&DvFrbYX<`p;zd8BJc8l1FLrAtLzo zO&yR>Ig0m0*?QnixfZ1?(hjA}+i#d@D_Zz|_cGoI_rEd>?hU*3`kwiC+FU9~K(+6K zP>#O^UPnxd4J8*8()TK0+j%?i^+t&Bc6Gbb}C z5&G!s?YxNOvBL9|MJpl4UjVXSbLv)l96b+;(>Q{uH7lEOA=ul`=lXcbltPc_K^-xC z3t!W(0O${_Ue3;=toi6|4T~*Hz}$|*9qir9d%u$jI5RK&G$e}3M6c9vb0PX~Nw#hhGs6Stx)*BKP(#7v7zI zTRQyS%>0Q=>dvmt~hX~o5bw3GN=r94nJhcA&?!*jdzVw7{MD83&~h0%ISh)LM~MgU{FZ+Zkm z|I)m(=lUqZ>(?5NAn9L%HZ01Tk5D!*<$5F+5o|GWmPRay9;P{F1S!=P1K>HCkuE6_5QL#; z=nm0BHef1nF)G$vghO@80MBJI~o`y=$+v*V$**Uhj5h4lc$1L6q=`Ed}hk zV;cT&T@~>F)&>mCvCqqa`Qlxr>7um1lydPS)vYYaL=yTjQ_nW}o%?7Tv5El#ZhmBM zh%wcej2Ple&a6EA=hxi7U9Rg`MYBEzlamn$= zN0!4$n322Md`RQpKW=XTpzbwXON|<0iB1cYqt}tkzch@7CsFt}P=qf=3e$>KllSZ6rUM27h4c(pO(y^FMi1xd&%R*+XYuC zCKsj0p^P)GS;DDk!UKaPH9|r$J+w%Ql;F~$rcK${tRidSflEGH^i-fXN4xK)M_;YT z&kq!h8-ewWUgcX$uuDU5ngs7C2>C_EHkD0IaxVsGIeCV*DkdoVl9wA)<$|(@?_|J6 z=Dc$^K1tj0>3a)+-rwc-gzMyf-qrG_fs6iBxKt9`9jWx1^n9c693)>c#EZ<;H`;}; z`yb{DKOc&wtyru&0%|7nKW9n2pg*CKbMkczKaFz}<3_SKxE@or^8}b)#` z)xH~CFXn)|`uJOQ-3i-QVHpBQeQ&#`%ON`fRtsw5Iq>M7K4JzZ3op3???j0Pm-I!P zy|(7Udj(B*%K9^{;Z_=J6xXXK!!82*sV=hS;d=+~kpt)^WpoqvH7gmpiKZSU<9ug^ zThVD=PyR#5<2Zp0)KHVbi!7qzqti0=<$^<(pGmm-O9a{f@qNIm`AtAGQLHV3_NUZO zf4=wji0gQKRVztOOwfWnH%Oio9LHJSB&KU5P2P23^xm+Y5se{^_8ER^ z4qh}*4`QJI9IbvwBI?kG*UzW*s%~Se7OO_mY0l!Dg(@nF_xFvGaU&Mcl?yQMOX)WJ zM1xIOb>#+zU`5c#JTV2wkViP`ZmUwXnR;J~X;P&danV#sse@xEI8-6&MikPmO-;bX z24@t?un`iQq%vL@_q-(3E&sKHxJ<5F>vSEune=SE?C+}CfduShz1p+ zxrYboaA5m5xtZaDlVqz`0)W16bFyGs_02!+`|yJ`kIh-Yj%>BKPY`TRUc zjq6wx)4lb)J8HlgCt-zZi0z{%KZs2jY=l^l39>A4m&XJj0pa8Gmf@K;6VmGDuW5#i zXG&lmP>@T*^Cak-QDQZcUoqt(a0JU53}U3Ft3FrArlmxT;EO#Z4RTCR1Sk(FJ}|#X zs|f$7Nsi`14u1b8y(kL|JWR(-<(-)t&95H%9a@&F4kkd~*cGDB|)Yn51U?fUvXDrzGQz0YWLZ$+E+ywqd^k_$KA~;F~lAgOg3unSxU(Huj z0cZFSJ;!*PqLvBg14-xfSl5ddCmWUgEFNT> zhe#n+GR8?NeEda^k6@ChUc(nxC>K2X6}mjg3-eu5_})c}0~j5#_v$$cYS-QQ`{hn) z@!a-^Pt%9)$1$6&GV0*MvZ@nTr+Tc1r&Zh@s6srlp-Yn~QA<22Rf18=FIDo%wH$R! zsb)xnGGcPM`o`F_29lt}3hi`o-n`44E{byQ3qPNwN2<NQThkq?00uytLrZ^*Rf;CgtaI z+!?N6Cia2Cw7GuYW^^XmK>@tKyKRTDYv!SuK#gOVDmEd0L!VP!+NpoAo09bYN(J(I+z9FPZa34f}zcRPx zd2+Qo=keYUmlrAd@Wgfd+oZ6e2)BM$`g^YZ`WD~M^l(S6k4csWLKvMNold`Y9t|c# z+=dQoT#YYQ}xKV4Z2 z&kv*N#XGrH!DUxP1dn98L}q==flX z0rckld`aRM$H0BMk65-D8%^Yw?QsamZ4zKaB+jJ~59NKsXA47Ij1S?xFAwWvJzGSg zOY-#pq6uiqd!_CvOT7R~hpy9q=XqMt6anO$(h-SMW4Ae&hjYvDhSd+{4>ImsI5vVY5a>2!a&GZ{)D`(Xdf&F_n5rWW{6?cHMS zj|*3by|flME9~by0Oz$S44go!Bs#(|M00;Fp8c@~M&uwg#+q$p-A|jtH2hHVa#1y+ zmT3(GTYpk6q`Oz2roCi?qu+_k1V;?JR=Y#HXGT4~DyD`xP3%Lf`J=ehFzaANBSahJX$ zVWA)FSs!f{sUUeolh!GftpUB*y|l~e5Py$7b;R;bg(WiJlRYTp z-q&}{6wm2{IQBa5;;|c668a#ry!Xi;|N0B>Iq=kuTrs9ZXVkQvkhrj$Q9+P(B}DVP z_wPU3gBk9nLHpql(I++f`ems}7}7=erC{OHG-ZX>260bh3Z}4!C@y%8cqcUry3uOP zHWFm0F76n$&^Q1r{F1|#CPviNs09ndrA@7)LX2Jeb^_f7kefWC&kW(1o6ZfgU%^7^ z)F|kpl1xP)tJZu7YsCW;v_iws%=BK3f%Zuu#}!uslTs}G4K7`V(vSC2Y)P(<*%5AM zE|9&G^RYK-SO$fJl9q{XIb&vIC46ER2PjyWlOhv!Y=yc9ymr zMjoSc(uIZ8q4}VN^oFWFVC459`6=}ny)wPUdf9PXSeov{hBRxHSdkyY*J6J9N-shS zHV~bM<-@1N%jFq|JC0`H8dc(x}QyHx_=1Oh5d;UvAap81UCEq>XxA^VE5nOjHkP0B5);+G2-xZ{_tt}sJ zV@OZi*Ta6|y^nSJ0>Kx5P%aM$)v3Dgv<^E?8yXmc0=juHxS_)Exe*5o4o^9V(56`cSA|v+TkPP75BjJ^BffT-q#_ln4`xO1n%(36~#L1Pg&B%}ZP%u>^GV?Bc zWkT<2g{-PgEs&H*3_(cez`7ivHbJaKD{Q}L34n~3sRD*5XQ)~Mh(amrQ4Mv#6L@9} zxoB)Nof3Dy`<6VCog^|D+9Zc5H}MpAjpamhI_^xZA#?sk10D(^D;oMD4~TupwoTPG zuLzOFkX41Fzi&@z9cNgcR5(&;^Pr)?ITY+4X0e}_c7TrfDTF%D#fdI_x6gqrvy}n6 zS4${k(gw`u$v($$B3IG7A$`g@VD*aeF_oqDVF+?|-8b<+i@3Y@l~GXF{LGkX2$jcu z>7F7Q+9MuwLnlp6B-xCPsth-&v($xQq=iQqI^vIR9JahmXgUGv2S6h(oQHN4;W7aG zxf#0TqUk&bH1Nh^ATq0Wh}?8XArCO?qOcW#c1Cw_9VfP4Ua%Dk$U?!5Lp|$S4Uj^f zZ|O||vXOwz%9d!IkTJ7#mA1szbQi^%@=N-PKb*)`_L=uO?2e8>h0P{lkaSb1!3P6} z@EdJjB_|7fTLI%<&iMERH6942}h4( z0^aaAravDpa8y*$4}I)*9jJRtv&-(dX8UpF^V=U=D%%|pz z2X?X@LB{K^gN}HXm51{mjWzCY8LBRAd2&j3}{g?XZkwaMdY*wx@X!!r9rg*(*VA(^~x z1IavAaOZKPLhT5d=aO(&RXLHOU-!MOx|6q`J05{AC=R~|uHG5aTspfPVcz)VE|WDh zakBjCWNA61$!aUwZl`$hgfoOKFLY{_z$6^sXkME>HTHGb)d=SPYRl85F8!JuQ7JfIIen%Lq6 zIpp6HGmOTBU#Lxk?_*2mq$o~i@W_^B#;pm>|M!d5miBB6=1uznjx8s)#z6!^-i3f- z;wo`-jNQ$HCqc+(ml4oAs0jJSnQpz)tPzTm|M!%&40kK)d;9Naco2|g1nkOY|IwSV zh`Zvk0wNxll0&Wz%;`kT>UaYO$`$utJU09lS_GuheoXNC)WrXoOufh(me_1m;6l|w1>09lKmSGDQ2xy4|%!B10%c)#x-Xv0I2ImDs5!gpC z!(!FGU(?u0kw378A~Mfa#&AI z-wqc=0H_1qe66+_jn3-&CI3jepi9~Rp2vlNVCk^vS@ECKk()%s%;4YxB&OsIv3CQa zMgAU^p2{8~f;={L_1I3WdarqNwX~ZFwX~ z#BD$RM+-LHsqmwYVvJ%w6NZbXL;z+|4NL;Ukeo^>A=5l8%~!lDFrV4@AdZ8^ZCH;; z7K;o^1qRR|IZ}2%siskH*9{u0j!`&ZYv@R&rN+8bk>k2(qU8e;@NvM-9osEzoyuNm zsoK|na&8=xYReP0UpcC9UjWOx#-)VtrE!}iS;)Ly7rUBP$^;xBj$D7&_%3V>9sYnF+%GUlSH=G2w<(@PR4e154 z2Po@CtzL;4n=moNT(o^mz;fWhAFzR6gAaGk3SEY{2K0#f^)_Xe#{;(LAH7$k)-y~L zOA?>9TJjX;%gWZ!@AY{jy5&`S@NY`>D>?KHKl~b)HC}(x)#uAkMwa@|+kM+x^ry-n zBE_!GINcgzF}>{I;%%7Jb?5wboj54ejXo~qEv-K?|9UOS90 z^ef875DXKHCwC{698uCHu-{D-)yJ)HRBU>^I559smYup%o6@_tGqj&j4y}wmSWUC_ z?ovLIa>2Z+(R$l)#Cj3Pdj}`g4iUz#W|?w5&YamV%b?-5X7YPdO!?sMdZMn`gfBfi zR2c~Y!`X=3SR2}=?4K%9B!qBI5r#{vZVeT_JrrwZ&=-6{G~t0df4^I zq5_@p^z~!Qv@0K*k>SUH@jZF8Y?dxKN7iH;EG6}4-i^_YC0_+XfxAIzeJoC_Zf|JZ zeyt{ELlruzDt~YF)##R;bY8mB)5UKOeyEJ$6u%-<&hJNR2XuMrKEl${ebqElM%1-i zYDbJ?LfRYt&XAaxYHjyXFrQ$g+hxw4Ye-Iml#@)gi)}bGulWt+m1evEz z9iH#742&P_>5;}Mpi=hhR~r!sQ{#?tiY~JWTEf2gCyXvF3O@4GNFF4o44RH;?wPCf zpgai6RH`)g1RVa^tRiF_^UJ8Kxgn&SXG^M@?=-SASWTg@^_4ppDjFPS_G7uVgKG?% zWpJX4UI9awRy0Drs#(S29)bF~uXvhT@|6nbr>YMBGpvwX8r$~?K7LvDsY~7W`?jFsquWD09<2zvk^R44nCfk(+efjB z6$?!W{91r@PsSs;Wx%Sdr2%sF5va(Vw+SuLVbngvZV54hWO)91ws7q1;SkXyt!Qc% ztZ?p((FbVha_sy^0J}bMx?-TU(dV|=yaL7Lw-a+B>&bZb z4%Y@Z6K)v8Qh|p1OBMynOlZxAtSDVX&%WnV>HWmre{eK^z#P9U)I?+5^9COo|7F#< zC}}tBJAOn%Hhs7)Wc`>)P7jfU#1D4X;*eE`%P^O*n zDpA4(+patpqyc7a^Um76^H215n4?Coa6WpnUNk8yWZiabB*d{^l!jgJ3DuJF?mf51 z5wcXJCjyOJxkg_7%s}IS=%}JaxP&l5WvY;jfJmsQ7VFS~VkJ=a7`8 ztSUMJN90%pU#V|NOu*2!`4o?$ZlhQw-bo7WKj2Hm9G-8z{s}#vbEP~thJ#D7@Y)^n z6EN>PG?!A`c5@*J(i){l+9p||U8~`*xzu;kfJm9!S{u{=;UpQWalFqp8xmMB`qRhH zrLeYIAk4AlL9+R+fs$ZY+lULfTw@>eec0VOH6H4*h&v%3=Jq6Mhq_cP+cGGBN$6CPOrS$)nnE-kzhX^wszJ zXlUl^bA`5k(d<$FOu+fQ%|hYw`j$S_D!uggwE{PzC?B$J8u=o9>H(bGjal{JV;@eM ziKacW>$JgFLYrjG={?GXw6coV&9X7{S6d-gJ1%Y9oroBcyw0x~9g9M4R=9#Tvw{t~ z{dhID9F*$Y+zq4$w{j-sLsC-6vnqA!!T@p5ko{EP+>Soqng_F-oq-wolPRP!T z=zsOv42;K_|DIjg(84?%0Ogn7b5VTne%~-@1RwtA5bR@Zq2@kZgXR6RYJ1UW2;THD z?MfHLc1acQb7lrT)*;IR99~uf*;g}I>G&d#n6zERC0*TW3HfF3tG8Y{NbR)(-KYWr z8b0Lcek|~Q>k{l3EI42~7CC_rU&#&PiWTxeK^5SC8ahg5V4vAgup4lA3>zp+M7i@q z@aJETIdCRcLpi|6!?m;v7ioQ(>IUojwDUC_uJ9xM{9w6h7R@Q&j4PANhKd@3Au1ld za=K+gy`-Pf9>s^#cTfnLm9<37WkOlu82+e=iWB>0VDzwM9dpXtjfP#8sQ-@zr9ieb ze`G}KknTZ%@s^$@nb7(iwqW;p#a&w)y!r(zxW?OaJrbSjKyAbXxb>JM%F*EeUUe>n z-hT#vea8mr;U;I;(0Qw)2NN3 zYJe?ORsq8NUNAU3@m&=xKjrIFWH}5nmiB7$9$f9CLi3eE0ql@O3jfdcGd}De5t{jU z=#q%Zk>-~k@Pe?hhEn9e=+VSR&ul6L@ry{?<5y%ed-h%lK*WC%0f$FJ^#M2M!Ov|J z0B8)Rcvbe2WmTt(LK$4hJQ+eAu@OPL{gwe;(VFu8-Uh>S>W({vpOea zqH@mO_?Jqs@@tmVDLJ^>YWqPn?64*m(CWq#WwoLk)HN0SuMM4l z<=%DQSuOZ+>>UnvLSaH8SQc3RO}s&V^f&utk8XnkE)B5cv$p+FWc6U8XvSov$%Sd- z=v_uC{Z8Kr3Aj})w4P(ZjE{!c8p*u*|OC0L<4f9WL}twp=Cb z4bF{{iFR>72zy9eB|FlE;(>Q{8M1p<9KM6|_={>&z-fJRZ-hbP(eL=k>7l_fI9<~f zX7LW zO#&t|gUK(+(;WPU0~sVo>W9zG`mUNQ}wc6W?Oz&z4i z`0Tl~<2j>AJ<{sD+SL&aHx9B`D(8noQWU=xZZA8c(9}Zy0O~JIg%aFKTW1*e*p{GD ziR|rt<2V3Ojw}v_+1N%B!}Bd(O!g*wvdowM*xkaM=k-~nH{MN==aZ=llx^(4JF%L< zmw=Hn!*5=sU~?<%v#N;qMo+zR@K4cD7h#T`l4|7M*5kLr&(@ex5K8sAgxUgbK{}5% zU)D3Dd9m;MQn3d4NeiD3)LL z?j4-rcX{9=h|v+1dqnslU+&(V4J1}-fzR+C+`kQMaFKC%oAZtD{uheja1nZ4IrjM#BZ$2)?Z;WO;7FMi1LASMbqtb+oM5Bm8AsP=Cx0%kbt&B zPbdentvLJj=K1s{6LxyV&3jvt>Js#{2-xSZr-&b@Du=o8f?yI!ZrJlv89=Wo^&r6@pqMj3w@4fD!NA0L$B zIQLML>UjpH(U-B`T6}mratPa6a41VxV&R0-Lw~}y{z&YJu|8T^AiCd|cBKB%YXr`L zRK9cE1zxZ=Ujat6;(+YzFGDxi_a~GbGtaDk_3grEeM~-L_+b#M41B--mGgR_@6B#9 zCRi85_9_JvFB9hm-@N;gjZm8m4&7y?Q@sD;EhrbD%@;tH&C`DK0wt%8UKe|~!(a%N zn1a2M<%4LS5u)kXzpO+N1XVw<`-vNg-7@zv^5b2jOyD$ycD~S~+PppcrUo;3f7@Aq zqO#TA@K+>cHQ;aPHJYHVHJS1>e_O~fc)G15$O@p&?H&UOZhsoJP1Fo?ijnVuVuVeZE zbT4>x1j-79R1@?CI8M4!r^rf#R6yUuzbt5Qr9 zm=CN2d}ELP3UwEP$W(Pf4#mTZdnY4ijazgErL*jQRyxAA_1;hGjcdGaQ&w(=4;ThuiRe=amQ!6@4VP!pA`^{!uOux0eAVP{uR!K*3RTF9+#g-_a)`YX+(UZzb zT_mlN2~$<}WdGK7)}HGt3(ZD|^J)K(#+i-z{2sHtj=&|KgWch3D!4xe+VT|5Sn~`J z7XQY@3r5x-DMQQR177v9kQ>Q!!aJku`Ppu;pWS|D}~o6h;VO_bqFEg|HDq^gs@qIM#Ct zGmKe*(@$mbBx&PW8Mx%;9LlXp6O})9ABC+i+#A?h@uK=sQHIfGJ>-2z3N8)tfx;e2 zAA|{mEtS!(lrSjxCB*)+q9wykFRP-6v8(95T zB*;*E=Jsch`dqHcBfTmE00Kr9A~6VzRnau$aEfCgr?C1uunZGCkv+-&ca(wDiznk- z3k6${cVqP9sA(;e0^hf4NNc71Bb(O8sge{dAQJl@FkQlaCL|}`#6T=FdP z)p5~H(oMOjJ>SmO`H6C4-`uU?mr7pi>SMcHDb)okyh7mT!P^lZH(?l(sir2FV<^5p z-j5}>Dp>SN_%b1%%9g@hZ(bSR^eM-KbeN;cwhI*=L&(+9V!(PBCV^$+Q9a)M5A(rl z-emOkB4WV|@A>|^M%JnlagfAXtCFR5m^>>z3f^B;D8}I;0827-c#HpRc)}0`rF(|p zSK8SZsVQz-KbcXCk!q=LZ9V-xy(=_CnCe5erI(og%Ovo#w~J-#FP2)7Ud5~ezIhyW z2QIh54_PDoJ$dmPk$oxwrPY{!U`Ot6+D1aj-x=!y!d!huzK|OB{aMYX%y>`S za)}f15;%`#fHbM_l^&Nf^{=<^kY;8OTNEX5n*9Ezy!%dqwscT(spPx19|erQup2>( zBzW7_PwMgwj_w3*o%yzP_`K{UIWwMoet`YbSx#D41SL|;m-SHZt?Y~v{nztMXZ~L_ zo8_wGl^Y6&Lv{7PSO%i*Nq(x8a$ic}V_>U#?J06`Z7`yqhe}OzBoAoWGp(`%ep#ava4&AGn# zS^bLqB0J_CE-v6453&n?szUE6`X3~+v zYwuvuZqbQwEd*-bGMC^gLX!z4A!mHHLevs$QnhGPZkJs9g8$-gT=sl`vn(a@Kyh&t z+JS&ZK{KvUO||3C?`i8)VvhumaHeE;{1lw1Ocim9I9`$vbh9;8K)x{r_SV0ns8^$* znXdd;TKoP@<`JuiVnwYYGid^N)q$w26!vI~S!wbvit>frzgI_%BUfd3R#hzKM^1pM zh(?~k@67awYMpJoFeDxbxYbLGRgP0P-Mnr72 zQ;V~r>?{Al`B2|Osky&Ka!7sU<`)`3w)Tx?7}AOh>~_V=&kSxODzb@&UUwmia<(fP zT)Sh=7g5x)=DqS_ZVhJ1^W6gJ_+Y9dD8vJOvm9>$ZuLTUIxev{Qq|gj?JXetL0t_J zS2`Z5X#H$&jLmVSg;)lfe?e3CY)PM5`DeewQyJTc>g)8CFMsdK53D&`A32b$brDPZ zD`+9lZkzAN(vI>^zw8?e8jQ_2L1FTl+gJqfic_;0^--)We=@aFe;Qo zY+!6@r{11VR3z-TyB@twX)_URZo|fpQ8> zloX{EGBVJ}U};X*Tz>?lnnz!7-u$b6E&oGDKkCp}Igkwckg#IZwc^ z_No!)`RLOtq{kW%PR(3{b;M@LiE1$Bhs3g*Z%FTm`NebY`?9jo-=cdS^f>heQMfd`-F-Z8EF~8@rj`0yQMl?0e4DzlF;3fe_a2E>XS z+SXE!Kt|rn=Pz0vf5Glvj!TU@q*SByEtawdQ5YPbge7K1D`#UB2wRPRRQsR{CB6t`XgFo1W}*~in^R--$M`Kun$1sSoyc6pMVCW(tDg8T(#Qu=cjNbhrc zq<7B;`yK||m)7^E?FUzzrcoQw~7*!aIvk z9Q+)1QBC>PSSNTNWxuFGJ8{}1TJ=lKn2i#Njdlsh;Wjg|TJ})2Gv2WvgGy*jwR&Ci z?9|hbW8!hnUlVYPpNlUDFo9Ek-iJsXFvnm3z9=X{WH)_c**h&|HHK-DrZq&%%OgXJ zP;r*&y#-N+QsMk(Jox8)WX57Gog77qQ&x`#=k6XY-|u-*w62z-Rnm+ zlcd{v19h_-IBQ*l$IPo0N7*yiqbwtf+zLqbN2=gr2ujgIAzxn?=#y!QXl(j@-%~IO>VD+8=ve| zI%%X~0{N`h(+|{KWQ~pW3^q%I7Ns^y*siY)aDe;bvb!sZIgXRx->-1Xhp` zAJRSnfdZ)%SZP_cDtMpTmMSL7)u1*kvte&Ib#CDwCzafvrIZ+>8vM>4T?g%2Oz?pFkb^EFlZu zvYaZf8+$E<$65#n_nS0k($uzZPH$Iw1Ck_LrFU@T!0&(yHFdbutiT=RdP{?{#L>KY z206RDP7@c^_L?D~tru}*dFH*QG09*l84b!B0me_9;v|pg4%cs$8!ih%*~(fJnl-?v zQ!pDyowT}}0X`?-b$0}lfcq$j?{|jS<3I}mB3M9ksAhrfGNHy~nz$S$Nsv^pTWz0T*!q!E;Ep6!!b=?c(+ncvmpNG}f zI3}p$KLPQ=Sl+|RRXBp(OAEn&n*dbJT1$o8*`6W%O*p{yg=;dixec(9*B~{ywpAF7 zF~G-2w`Yk^&6q#XF325f09mPJ0^uJ=JD)bxkUFP|w%ZTIjEVJ_baui>~p)3$z{ z=HlV2?=9yKPD1+Qj3qlo^VZ)OB*KL4T~F1)>rVXeW6mWlRF8XdCI}q?wLzyU8wtNb zn$!rWQFghPq768YL_?%6ylkik*-%D`wA{OQSgQDusD{lH4qY!=>xkEd+vtd2TqUlN zZyi*b4VM$zlSr$MuG?mw{Pt*cRDWGj(t1y$qZI-}#AAZ)p?z#JSwl9a&MI3+*F2v7 z-Ej%_=OXH}T8O-u7Gyd(S?eJ+E31W%xkXJ9>{r0waY(F^D4ICTE!3Z zGy|WNh|KN;t$j%QPJ<~>dgxlX-;?nAH(!(VA7SLZq^NGXo4p`1KnRBTiU+?MUC2|4 z7Z)8`kC!pXZCPGTosd3RcUM>tax$S(_6r@7d9OPLs06HK0ktNyXjeM;0NNUkP_o-S z0)!Hdt={hr9?Fi*N>IQlQvBjY2-LAoraE49LlvKoJ*qF}bTtP{5SYtkx0_s!L>JJQ z9ItLN^4|K0Q}e`i=dk4*q!G^{>{?7rHDdU^{VlK8{lSI@qe1HGDHinI!E zz&bbL_drNd`*Y_*Azk-6^u zTgG`gf3ftZF4h(e)~rd!&^`-gE_mjLSrhlLc@EoTv_1H|H4)mK4|O2Til$M8 zfCY5H_MOw;r@#PeBK)y~JTfY84uYiCBq;R%nF5`d_;r-Z6Kc*$KXMPQYlO%Y!ggZ_ z6eWtNfDMbrcmKLzZ^A*0R&q+s<8Z(bn-OeGX8iKtc4-oHQ_IhDeq#LDWbqOwaLgm|{fT}m6x1tB zmx;w^Ti}h&HLk_ZWOT%VMt*Hl1VM(JOux?2unA$A>c&4WY=TNZ5XszuAeAk?}93bA+Z}6*33jpH!H0 z`{vSO`FiH7q)ptlZ;$J+g*Bf>Z)kquj{{tp^kb_Lu~sQPJ|w}gCE?dfT;bGXRD`?D z^CdTzV+U2l{$Il1Ue&Qcpq~LF&ZLE0JoL8o#i!}cJLYL_W;NiJFCC-wrTFjLVG(ZH*%g0r z){dc>h}3=2c^m&PAEJH60?c`0jk)OSsq`Ob-Mfi}OoP<2|d<5tX+3|K&^DX_1g~Yu=iZ;G+ z(t&G&Vt@Tc7ra+L^}O6Jyxexyv~;qgsn{;~kilU!i-%@C!G@uh8p-l*za;haz~6ppMzu|Znh*~AC(AUoolf;a?qv-MaE0s@8vQ`^r z+wsi)k^!hH0=^+I+E@~UZhwb)kqCXUH|bCO z*cQ88>53R`XPAEz0?;nT0@*Z)KevsWAI(k;*f_pvaS5AOyCMH13#G-1};< zJe2e@9`lu8j+y{752Da!@NXoAC=pT$F2=TMmb zcOd0pywggP#vS91wYAp`C%=a6l06rQOsR^^sd`RzEjM=S@v)ni<4b5a?{D#%t0)5n zWlu-K+p zuy0&yM#TXcrW2en0K4G9A4c1Ua*nXhxTkx%cjg#2hC${uzXYktYr z1`8!ZD?LM*kxEUh$aNlUKPO{Wjn=SnvtFGGUf!i1_hgss7VGe`;6wmP<}4QGTiCZU zXdDb+UV0a!Gy~RtN)Py5)EKeB3p`|hjY1Ql8}Z&wLWp=M9oBe(cWBcsW14TQf5+n-5+%&T$X|Da^{Q|Zu}oVF z344O>cK)!g`2nGP^)NJqd^F~PDbPfEx5b0)*Pka%oMFya#Oxw5yQs8;xs38Qkz*N2 zP>;6Ch3ourwl6UpSL;_&mxP5_io09t<7Q(~RYMkJ1;F^4H5oKbt8xaYfIrZU-oFFS zB=P{F(46hK`EB#@tHPj_t%hVgK%JzuOSq?1sQ*k#e^hRcw^tH!G z>If@&G`3cTWkjD&ZTGvcgzOf1ne5Yr zqpa5TT$dftLhMnsVcFo_K00j(L$J3nSpp*$ya956mZeK!@9_F*ry&c~BdoD)jicEX zbz$dJPq2N4IKo}(qh@)$7M0{^@it)8W0FG;*KuvmYgjek-)`qWK^{O2tGp`tZCm5g zNvhmZ(cqb$3HwFtE_3BIg|6w<5=^Y289-0@~GqmmqdbiLRE=qGkTg#n6 z{COo!%|#JH<)WXaFcUViXJtr$8nv8}$bI<8syJsm>WMSom3{bJ(`(}Q1n|Uo=r_sI zW^+|)PRCO*u4IwBWAOXKQ zQMSj=@*u%^;QUxm`1@SKJV+FldG^k(%cA9ueG~P}geUeRVgZ|83q#iS2-6M$q^Ske zyypE+Bi@&N53!=+kbQ>C^~1!qO3J$bL>3F*3RVT>DP%mPM+k}6A}`ak{1m|yT9d@& zN`j`u$4jYdyweiL?*_`;aub*BzAh7p8PPr}R*sZmUgnKemBsrcfc5@ofx&m$Zma`k z%q()bZaqc`R8C_B2hC#P{vH{+il7ABoY|I%l9mm58JtRm?XbwDiCVv~=H~)t*Y4R~ zxu6~J$yPevDhh%L^&pNY{?(EcW9EpIh0M?o!`E#^mfck9BFfy4P&Y_M2Zh41SvNqMm0*OeH`QVQ}OA3 z3+2$tTEP3Ih8iMMK2eSn#G$iiLb(e_Vc>u&7|oK4Se*_R*2{aziW=j!v)(NEG>C7P z^fzl)2k=8eecsF!03kj$ruY%TZ|~r1^DSLnU7?FZ{M|j86zHC4Z%2hnHl|owd8J5( znNLUB9zqg1oFBcO6MNl+Ec8tz5;L(Sqp!HZq|Xc2ye*?0a;~R-2dXl^zw~~tcwE15 z-2?5^@TKiQ`=h#W2z~XiL8D3hK)A{{@%3mmBrLH$HJM`OLMR~^ZnMzc6`S2%Xhx&# zyM|-6R`N;f-i7Y|ybssn$w~vqgudpCQt{V!Pc+h5q0HpiTadU4yy$nQo=~uY;-^Ax zXvgkV=w=`{#*J&&)SIiy0HZEitW|$9-8Js|N{LE;zKZ_3pXzEdI-ovM^b0pK$EZ2q zmEBobc|-ID?YO?~=WJI*znKqL^G0Xe>{z|au6C4Y&H#(^KM{X-JlaZWwSEvi|5`-O z_?;*nt2F;4OBg<(r|lEb@y(DVry%^iNsQ@_+f<)vyx&F`hEGs`xHVVrZWE22+!#p8 z%PZm`?3eX%L{hj_Y9b(#8IW0$Dj{aXoH*OJ7H5yDBR;ZNqd3`45(;|3_~XLR!a(0 z_{Ay0w8}VsA@m1)w-!sKYd9I7;0pX`o?Y=-mP>)=NoGFpq%FC1k-Bv7; zGktVjz|hVe9+Inm_6mV8rBUMp@XU$c!T7&v=0u)mj13j~PrZ-ZC<*I!F)m1hwlGCc zM{dI(_Fa=bqJ%k)kKazG2W46`IsZO{!T2c!E>$q*OVC+iEtad7@ghxvsUiNeV`hD+ z1ozsYt2`=Y;x2TE9(bn{8@AZw?m)X`P+8-`GO3S>4`Uuzly5(0(Tu!+t`+=jt9Q=D ziT&9$=hxSXtC({qTKpe>^v*mnk8Tc5cbN7X04wF3_te|ijzVYkc`O8-kT)Q@Ycx$o z7JYjqNB^Yy8}7WkqwK@=_a5QymqLL>SGK}6O8?lqOIOzjEb9G2V;gEzvB1p90`;n! zVHDuAq-zn5y}a>S(KkM;8tsPP0_*4J30KIeJQ>bu{=#k#mo6jZ(!8AR>Mv-iX{g_> zs$Sasnf$gXaV2+q3fdtk8Iz`Ye=ofaHbsjdhu%WhE8dW}Mf{pVu*-$XKi z+4lcf8PiplObYa6hhoi@Nib*O3i)1+k5*3+u)%O_FL-*$gjz+UPHl!5*oxBk&53HCQ1xBgb$M3RGhd~DuV zw_*H`w37THSMg?EI{mn`syJBhkE=?8_3z$xHXm^0UYM`d3P@t&q-Rgc&GPaaGRS*c zxUtsgZ@c(e>weGkmFaL6ApLVAIb=s==d{xrMf+XLBta^5)dS#P-TOD}Sbk1&-?)1l zWPW9=h=5y!=g$N`DHZbkaVeZ1Kp$V%y4bSoBz{LcSWS&4q>9&Y@czPn?O;HX`19<@ zCTcBXjexT9iem)B+xewG2p=xT!|H_1BvkJ%<`r}W>&cDXL@cT(1ms`Fu0oK%o~~s2 z7T>}PHtDoFGk(u|k&kD$uAkV42ccOlEhlQbkkzCcqiLwO}5FDKU1#gV(MKV@6>7q$2 z>9h0HCsj6xmR&uP2ls~7+w{gWx9(?#eBqIpN*u?y?z$uo?)v}sXfi<_csq|qB5{Ps z2~qeq3K%7^h#uhpdJ0rZ(2qT_a(a~aoa@TY41N2d-5gxgXEaO~d^P7=YEKn%V$kSl zzV-UwXodeq!;T+H>knK{_@fuJM&!&B#!RBYBl9#`gkJT(P!ynD%UB=!@K`$ z|Dm@klVPVBtjh+CX81^ZbXo`!=lL}OMGCN}#wQ&4jgZUxg?FXiTweXVfiVt?8PxiE zY~U6rty-cNiIj}V=xfT^ufv>tTgFs#HqTo^Hi7#AlCKfmCH16R-SrxKI#KCS+b}RF z^IBUHU>1I>Yr4DaI)s}MF<4-w)hC32ieEl~#_ce|Utip*~5K zl-1^=2lE4a;g-_9TO$@S1W1|{zIY9Yx|5e)rhE~u4H zRkc5pbZjnB`waVaT|v)}%4_x<*@OiVuus9)bP5A?owJS-)7QEweQ|!+VG~_P$G(RW zEg$m2fp#G}utYa$&oB3UxZb)tk42qqQ9z{1--Xy@1Th61;e2c`z*U%{nX{GtmNBW4 z>CQ2K-NRIGi;pkN{gcG2St!dg`;?5gD5arDR$xoa<;ZqQH(jL& zJY4wDrF_B{nk7akPCKI^41<8M!4WX1dgJubs10WCT1))-zS5#`B_fmqc2vpPFrXk8 zZJT9zF<~x9?2{z;JZGU$iUfN-lloXYT#Qx*c?~4vKOo!DL>GD2?!goh-(q_d`g_Ml zlBt6*vMW}}^q{}v%S@RtgCZ$VtpvNnX8|hqEGIqOF!1FY3kyRy#l%9FaFGe;Gj>9n z)zCEJ{`IE7@PyWaTb>(Wn^)9xzpvJk#crQ?SD;@@j2L?z;)JqttAxs#m&s5U4ET$S z!Y2hFp^$@Jf6!Y~*Ng-fooD(=UMOnP?ja-3KM4b8OG2;+gkfSwDCjGF?7Zq*x=Ek= z#&!4N%-}BtEAT@>9=aL~)64|FjX~3@963^a{&DpsDr_FC{iEaWW{}Bg%0isbURgDf z5OtTUA94je$J(T8u4Q55;4GXK+PR==XTOy=?_Q67BF833J!wv3K!Q6zD}GvIZ3Wv( zxiz02!yu~Ai0ZDanlIPITr9bUG$l9+EMv|;iMb#kIV3=Gcv6JiI87jsFzc<4q??IV zgj-NX;f3a)_q>uk#tYdjrL%pkdzun^G9vbKmqum?Q23?StgBFidw6ygV%t#R@~4VZ zdL*cnM37IpAL$9-%l-*n2|LyvuKmMkXsZZ+TNxaT431MUElF-#^Y%`nI3-z?F~1?e z=1kKRUxs$^Ns88AQ=24|D!ZRS=i#`hdNSjs{oJeU%Ahe()W$&?hJe+oBEt}OmEr!# zX|-No>0)bo)Hzx8t!(a>7H}gWc}h*wQz=!6tO~%`j>l}YDUnZK)mnyD<`bXWwX_~U z()s{LtrR$L{7vX7Nc+exTq15SEC^W2k*6GeebwaRo8%GwtOXrW@`~7JM#bkj{tK@k>U*u5yGdlU6qMq43A(q*XyeKhE3sS--7D3r6@ zv`5yL(Coe^X6--4Di41<52@uV628Z$%Rxf}UUL3bPon^BziP87xMxI07N27AZlIn(}+{b3r>aFR&0Ws~va!GZjUX&tQ5KqB(N3(&E}>&=9dX zH>ZYK!}Jx+%@Br|?RGpY8hN<9MZv_tJ^Cfbm{;RVFjTf+ygfO1Y-R=}g^BP#UI0^u zeAO6QXJW{(xFG}hbzert(J?@}B-Z(1DMuS>WdO2VXC4p5obw*U1_!S)y2)_h{-wV! z)=O3d%v`(h*>q#!GvY|ZtCB@#aJldmV&XqB2m+u-lXmgyiNdlQtXUe?b?j$_!6q0dTzE&sy&F05shAU zUIHX(z%?7!xt0>z>zG9vz7lqWYSYw zz76{$awrmu!~yOx!*SIpC0NR>A}QFs$)saP(|My1ooItL5R;_~P{4seL>B>w>GjeI zX5la3harjY`@^B)K^f%yM4V}Rw_s4&-B_d-EC0*1yC^zIMc?RksS{aK$9l%=26)2D zAcnkO74Z+12s~V3xj_VhnfJSIhKQwm#(J%jz2hzv3kPfg%nl#~y<4T;IsB0_r_IYJMd*SSD>6G0VYP>5(6|kOmi3GQ-VE zL5Oa2R17$W-7*GTfh5S|&YolGw@s?>-4S=UhY=Ak3)TsipI;80zG?MQrhQT|T26a3OB zU-aMmAY#JG#O@5)dM3tkSDeLrVE?xJ7-?CI4uS#~D0FQ){V{BvMt9A&LB7C0HX;yt z(zUkBcc|@sI2E09R^F_9*7JQvyX`$gtr-mIm>N{EPrm8B4AYzz{Jd}zTuyud*w?J{ z;c*COKMwc+yzy2LGu?7$8%ZWX+il81+6@?V~gc92H=FiwKvD zMT)WY&o?EbPDbh29G-^BK*c~8BVtlPxLo2mH`4v1hu$>uDZJJns#f?iXCLFhLRSZT0}tE}cUKes(=Cbg$<{H$J$9sgr(^LI2mw*T&bNBV2Fiw@%@**`H8Z zSSuqE9{cH8za$G4@*svntH~M{ys`KWUEjA}C``g!e>K`ZSE>GDm&Ez5+bAx&b>$+4 zTn@%g4vkvLhS1PN@tdk_|G)!$v>0bpX~HSne`EqNF)f4qgP9SOO_d*7Ow45=&HMbL zADTxQ|2vN~;KP0lJ$M2m6d@K%pNp6i|JFa&7Z@fPuP`1=dRI-v#o6+vNM>V-KOAbn z5Hh!Jmuy4u@e95->*L;+qel7ZZ5HI%y!gXnK~qd@1^7fh5q}iWYKoNs1p?c)F2Ubh zekna8sx!p}7gQnC7_^|XY>t#-qt_9sbZl+P@S*;A)|#7^nnhb*cUAu*l%$_}`o#o* z4OT75!UEBt#Il_%W`sQjn(|cC!hrp~arq6e6HfF`8k6Iy?Dm{3u)d7u-|5=fa)n zh^zkwh>N$m=Lx^_c`e#(DLn2TDcX&&kE^m%SCx^%`H$%wv$T~psO9=US_U_xowf4Q z;Wf!&7pyspExJrLuG)7vn?XFRUeNjjx*F;iJ{n@k_vC^tK2pDAvXKb5`cIxkHULzEKitstj7bzkm@=b~-Q_Vv zIBz}EwaZoNO8(=MVEIIVy;<64yOT$n}X3VtsNch9zgnhri_hI}L zs8J>Oz}~bH3W%UV1}Z~o&JWhM8*TmHXdkI> zDE-I^KxKCHqWuh5SWq2b^rxn@2gv{N(=N?R9*Zp_q%4E!>&jeD1kpDrFh5ZK@_zzF)|DZ+u zM+N*EE{uZZ8jV-Mez_PemiE%cE*3TbZV2B=FU0!ta61N%4lA#6Z80(tD1@tQ*as=B&ahC3H=EU(+>LVUcA zzTj&zPJxD8&7IqW%h#fq{+K1rn>7V#6p&1){F6C{W->18cx6|)##hBx%!juVN2dcOJ1%w; z;CS$Kw7I}>Wo@z)Ki4#!yWwV%mSe<-r@QnbpNWREPMlq8~Qv>!ftcMBc= zDcjhP@AL7aa6!9UiA7}&&tG*UevB79#Wz<*AB@>_vtf~oTYE=$BKoBdg_V}H=I9h* zMtzrVjXh_7uf<_|SYt7CBI(WC8>JP;7;6W_&kKRAzlK1+itYAX67rn zdmX?D7JM*htX8-Nk$J~=Hr2OO8*~r5bZESp?N1EVp;0MI6;_-{vHhghAyv$N+{oG`}epPyKpzvUjmO;+P!=SN5-T zZ08_uk;PINAt)uglX0^mh|AN6#RtD4SO?$w=@^k!jcA2LJKUM`gsiG%+3ol_W7c4G z;p36V-Gijij0H4J;ia@O>eJw;Mt|s&8{akLcle_Wdl6%I*Z~j=6$Y?5a|jf8JH&I6 z-#EW_A~ z5ODX3t9`8S57$dLFA->Sk;xBx)AI9oTA^CM@cas-F__&%Z>q0du8?gE4nzi#1I!f1n!XY0- z#t?~~=w5nyR;h?%^e{uD+CuR-8Jg`#SCr^ws_tL1V~Rjp9#X%aUja!r5s>Swq5*R| zio3U`Zhw#PShr4CnS-j@WmPeNgL}6_d%jEJ^|BY}gB*}wtFsma_<|77Lt>isMR&4Z zO2{*z+F<;OxZrn#5G`X{#5ogtI0RFW8sxv!f|pJraV*LwhSN-LK|Sc0s%b$(L~?50 zjD$U|MfvD)wK?seCnw}p2lU{I7KIm`)&dVA=DrlZN`s3#K)vpsL;bgMSD`wiP!Y3A zy6Ej{^I)lKGHf3J4XW@`=@~2tIIpeZi$H8>#W>nxsj2o+bN%okz?NTkNe;?>LuRN# zU)spQ$tXGymHVr$M^+@%mFJ2Nel3tlD$t8R(Hm-H)aUF9{s)g2n5Y_4f&CT%V%G17 zicNw4y?1)%v~R~wu|f}4BffH8YqUkdw5tXw8G(3j3{N_GkZpM?3$I|{1E4Z@;u0CQ zJX%%GuIgOZxO%B>ET;zFa=vxmiNhaD%65D;@BUkgJ(E8;yzPP#AGSOF+=sOYrA}T$w)CW+FK$DdG@7RmQk?n6~ z$$sNq-WsNd7{cHCZu>{`ONUprK{r4|*4J;!x4Td!@SB-B!16=;bMBc-Xio-5bzq@h zXNpMF-gI*lX->-hQT zwvILH0{MgFG2#_#qqni0v%Qnrd$Qz`Tb&Be8pYm+xw@cRx|nFn8fIyCzAEV+?VMw2 zUp3f@3yhf$rT&Q;GCp9>+)^pn8@#2?D50}YObQ}=MV3ML#n z*xuEH%D$eUX$Jk90=j#eu1JhXKL1Ut9{w>sWTG1XwjHK0SXh*4c|b;d&>|z1@HrkC zcDJ=k0Xop2v}RaP<}eTkjDa~T{HY$R7>>DGZ$G?$^W$4hs^$HqcP5&?Ie)So_9jGT z&VPG2Yf@FpZXV=(Jv6c3E>u#WQqbk+3A!VA_1dvn>+I9rwu>tn)RjsYyekXwkH6As zISgf7Ao_w^WV_3dn)wl=tupVypy{5ok5zB8je_VJ- zTKZ+)vE&`CSv)6^-&3UH*nKc6*Wz~u70yVN#W>73B$^ zSqO8H?I3cp<$agXnO~glcT$pwJYAfdKDrhhC(&Bzi^D|=;+F$4E#2)`-FISB)V2cA zP66+=GBcZ~H*NzTS{ig59UZfu8~Sxw8ih_ZBMHbN`mLV*&Lx6h%Am)3%9>8zxX3Wy z0u-7OWOJ-6{SFqnKJtBgz54`scJTa&0$ zEHadajJNRcsmz)2*8SHEtz!na$Y_MRVGScXp^C|(Y zQB81D=f^w<54j0SC;~J7JA9=(eeJY}93~aWY%2YIZ=G$lx=Xc5fhsamZ#{z1>xt8@ zv9JBSyiVH>3GQl&DN5EE@jf1G^&tj1mv20JMFs;uiUB%Il(t0F_f zhX>V3&(urpPIkswKIG(go7v=k_Exq-PU0gQMg6y;)$3U_%eSoUmRg zp_%7mBrSzan=|{EqG|%L=z^zQ;Jt;`9YEjvkWFOm8#SOqj`Z!=u(&)ud5au+L;w%> z80J#vlTOJR?b~ZA4_#b}JJ@4l(G>GSqF4K9!)S`I*QyZl{_2w_l~M3ZlacgnW@Ase z9Kx;cx8+g(UR{y#N-jib^bZWN$erGxg zomkz5G;~$0R4%NB?g1ffR+Vgq0=TE+Prj`7l!-R60EbU*f;rN%Fl)!`MXeuBWU(DZ zaxl`e%{iCqt0zsKH;e?w?)Pa}ee87A^^nV9Qs2KDj=TEeuYN*450?d3b4tN#>^Q9g zjlw%Iah1V32lU%nWn70LIy`#cJFsd}_-)g}Ye({s*t=T=t_^YL!1 z)wE$6lXKr3Tp%;Vt(P~q`E{K@PnkK*vxuLK)dQTR#3dI$hQ>!K1@i(aiG9x}jIPX_ z2^b-l_0Mh2uu!yC-D~jD$X@huLZX?~0=qsIo`1Lj>d;p0MPkdE-i|}Cs+0sfOV7uS z4^_8%by5`GHTv|BjPj|dK+6}VuDPNwU*JzkO>MauR;hIn;x7<%1V);oM9N@8-T+1B zqjCl5(fb(qhv+dkYUOA9lM|tblkAf}6`$Q-@I?>mD*9QuNjnw`|E(U}7>qF+Yg8(njVlR35RjrRX5O%y}w#Fw_{~f`r}ou4Fl(wW~VYZcL(i`DT3Dm zY5q4zMK@VtU!$0Iz7U79Mji&}4AX1=w{jff19j>cwzr7IDpHUzba@hkFliwo0=s3R z%Y+o@`FizPDRfz#%TuB_f{kZv7rV>Ul&sZX=-gZSu9-@~x8UVrlVYy^E6{euQTZ`c z6h~Dl7lv#50Itm@-nS>2Hj8T}FJHe1>oGH9E(tQn#LmN=bPW{D`G_Po&?#}3`00CgZwAn zpvCMJif?j@cy1~;eu!BATy68%Do_BQN@FfggASOV`|0KUp1S&bLAwqH$)~TW z-sze!5fCkNA<=EUc3UeF8c&QY<+n|WO1gh`vP9y&<4<}XJ)vP8cBmm(bJX%6%Jyi= zI1$eDF+MUaKkiS3kn^HD2(7x%EUWj%0}VKxWm>Baog6`~bQGfLV}uOXA=BB5LN0Ny zK6y;yz2et?zGI}I3K>v&+B5m`$a&Q?!X(aQvktAW$l@Hwd76_G{c1K0?fjDd27-Hp zTKO4Nmlp(Y=7FXM20iE#cYeb^gY6i|7MJ}XZ;caC#fx)4BfquUqiw0iY+JKbU zipzCis*O2erd38a;y+hS3pL4ClfV$nTPslJ<$ikl(yIP6Hs7QX(~=ST20`}z%r6IR zIkZ_S(2y!VH3i(8mfru1v#uv(vN%z51BjVb7%;%j5pcE0e#nH^CH3?m!9tT%UJ`f& z<2S7eXS12_i^Iiz6{7UE`=`@`A+F>fnFPKcNK$FjHZ8vxd+M6vVv;o3V@C~dExgI>I`x;DP_nZ$@q9usrsguLbsV9pl`@S}DfC94?_uYzuE5L{e;iNUamhI@Oma z9C(Asx`kDpG*$eTidEsD>S%(6KMQX~=oXhy1pHy6o>>cBv3ZNBK-F{9ExySH!L}Wi zu;8CV%jmFdpKJzks6*$WAGbt}{LdP$sak4Gc5~r6o`>QrWeGh%nZ=jRCnWyfv5Q=( zU*7+t%PsI%ShKKKA&cqhGYO;`m*gUxnDfEXh0M)M-M^=4ezkT_c4rcu;2+SNK0r49 zKWl-NP0QsFz!{Lf+>jUNr3Yd(Sk4BiIvs-0szs5me(o+G%EVdtl_W{bF|0YimvCOt z^w9%>G}R~$;ykMNeD@P8TPGMkTUFyS=#B4Sb5i;4)f|{2gDtYQ=>Yd=iHDEW-MHY2 z9`F~q`^$Fmjt6>Dw0VrxZ@+z+j3k}j;wB}sm3grf`M!mjbY#hYCEWU3*>ef_B)QVG zR6~PM!i&0FJN5on_r~y_v|x*<2(8HmU|qe~T2%1A&E^){5m~!CyP_C_=GB@W^N-*( zO>$B!QHQa3Hw$a9__EeygkCE*(nxz-sWb1d#=L?cL7k2Lw|Ox#XB|T=Bkx$YLo#w77J;~ ziF@i<<+QGnK*KL9;`R!OizFN}kV$^*)uj*t+(QZYkG1{~Xv%+8hw+HW#33=Abu*Pq zEW0s_d#C(y+M=&t8-*e^St#V%gM^X62QZPsQs-yCRPs5+-E$s=ph<3GQCe`EKf_Zd z4i3Yn2X23koge3!U@0H{7!z`_8N0$azd*YIvy+A47mo&`zuW-xn&cj3OcfK18!ghA zq*GBz=K6<{=!>tsK|h$<`BpeX8OmB`P6YQSXO|9AN?bRJ>~=>oPGf`j9Hzf)FL%DC z|3|qYK?d!A)T6YZLqpB6#^*J=NOH3a1+uA?R7LLjrMD&0CAbVW!WXmJ>k7 z!|y@VQ4=f_)SBOkYE4;r_t<9agAjRwGY=V7g^_B)EafHvJ0h&*IaSnCH^I4?5JcXv zOzmEgqN=;CSupojYeA!E&&;Bh?OF)holm<^*-@Q#elN%YN!$Xz{gO44nGI}GKlDJJ zFYw7>p0Mol@rV%p=Ty_q@IVbU=yGPmX*mMe{v6+ttxGVx4qubG+e;^ke3p+im4M3= zb|>Y^C9vpV6E)=y5J_9f=4cqEwtlBowba$sl7f%c=0UB4VETz=_H|zMb(51{pp71z zq?T)S9rOnYNGvA}fC0KxvTm|@MLl#MY(A%mlIc}T#f5#$@cks@VdNoi8i#0ksJ}nx z)Dtlk+wr}b8le5aE#er2IQ{SFH2&m@1qB0R?lqkHBdhpZvQ1ul{Zf)u!pP%+XKQOO zRpFX-IAIT!@+c$J0X z7>X7HGR5p~DFC-)JAAgj%44)-$;qxZ3udZ{0+iofR38~OpZ@iHj!maYY$<|7$UdmB z9?@sz&uJ^aVYgk8MhmS51>PbXs+caBb4>V#G8GhKQs6oy1+rt0DkqDPq=53@cL?9W z?a>e*z{szGzVY>YI)FdNM!@3a`Wk35P;a=?Z`p{Gs{W*E_NJW@1}gGB=~1ty05# zy%a@+kQuq7kG~g@n)p?7I^!V`bR&6vc7X`Ve2bMf(qDncrXuj4R|33&gM^^srwll| z(^q)ue=ak}9irSAf$1_jhOf=ufKHpi8Gp{tQ^r>~&IoH?1R?%F8+wLOjRCL7?={H1 zr+B#Jhfiu`VYrqiyK=;Wv+8%7qwdZ%-U1RYofZgZ-)UEkd^4-;`1=kw|p z`uywkt~wpi-yNCJ+RUM`lcb?Pcb<_WXwl7hq|dtRmXGa<{bYUI^3?y+V#(y%bCs^g zcbJ@8r3OfrtA2rSV-k7E(S|w$hUlOofVu;yBALPJ>ogE=nsASY5q81iV!?$ zkS7cMCKPD3o`ukLpt)8`K!sWq5XTDNqMePBit85#dL^H0b<$~7*Dq`ow` zktb0e%}i;(db)6;6g;hB`Dm$Vz4VOH>SS}%;_XV#M*UPsn#mP$^4sZZJHh6pAe#9rN0TDC`yrpwVUV|dj%kGQ^EK9Tzj28cv_k7+$l@J< z+wY9W&0=dKJJtSLGaXy-XAQj329&Awtc~Z_Yx+H@@l-=1XdRL5zApK`K)IK3g}T#S z;?-&YwVL^uN2XQLop_c7*8cO7=`WNgk8)Q?{VWa}{2iw5a=1*ZeD?$>0HuVxu~1ME z9&UjL9+zlf0&alG!~p**dOjKBH0lJcr9Mkq0&giab>78I zGn9K(H8r`$v;Iv^uw;TT#9zEnaqX8*6q(q2yytm-hn?}>8RhBg!uy_FI4=g@mGD{# zl{Sce`c_WDA#R`Zd;);ejFQ|oXU@%iywZ02WXO*wbKN)G(7nll0MODIQzv=9*<^w~ z4(b*0oCLXy8}Jo3UQZF{GQ#}R&%5^wcVkD_u(J`bBx15PrGD)0W(p_kOT_t4TX7J_ z&vVy_^%*}WWG(+Arr3{-57w6p#IBI^KKPu?;+!m{tTr0|l#c%;d%uN9ce(HNHyf)m zG5MV8?_z}`$4SjA)Q z5%+gw73732k4=aA`)qR5o@X-9V1MGcEk#gt-+uW=h{6IoHz!0TRXHaV4d{QO!dky? z$bf7NgAF1)evi}`Pe0}U;OOc8ho{Ztv1hd?oh@an^l^XS;<4{*toG33s}p9TQOoX2 zlb4#W!Ppn64`jlN{q=UyV;cz%OtIkMsZb(b>|F+1f2g{mPOrKPhA{GA!hHug>1S`+ zTjscp_maOj^7)VPWA<}7eCs$w^X?&ALwo zD*&sqctgX62%j)Atu%Xv68>~`6png?apUXY+*O*V9M+#@-`VE$^-hw6s|(MuYU1-B zyl7T(VApJp|7UsLJ!F7m9iYJl90xrrm)bP4pZycd1|) zZzV=gV3%q=9%RJyaP+grewx2c2-+7vV&SJ)PB%VMPS~*ccYYt4WZC_tq77Jn&M$pr zkZEt^`X)ltFj<5W=()?A6RWua(|iDzj-}K=KpWA1q-zjjPdOnGI{Q;)K5RHey_o$U zhk*xPjP;ONCQosnB{pt+|CF9qdwb_c>*VF-U>T2Rx4v)@hNw>U7R423{jtx$BKkqA#9Fh4+~ z?6bsmc!7=w5TLZJj>rF)G_&_E6Z(YgOF{=$Lm`Q$-OM_}3?5L#Vo&HLTv2F>STGtr zsa%|&4n5)5gNJZBy&2wXPy90rg-}YNI6@G!&YPjL_C)-4C|I!i%6P!2v|dfbhm*oe zqITe~I+XsT{s2lWu4$2A^kWcJQN9C-w#KyoKEy)<3ZXAL+pj4ALHA@rzae60SA$7592IorDOp*?*osH zd9wvT*}csr@?z-oym_o495;wdHsL%A9kpozg+eMK(5$;%iSm>vf?Q z;RVQzkaS7~)8x?5BP9;`)gv;Q?S`6k1qd7Nn1X4ennb_b{^04Ui`X|NZP_u5hbvUr zd=~29z|oGh*wu6VpH99dx(+r2^Y$}kS)R^pffmc-m{=0Qt z9S{9v>ma1Lbob)K;n@)h>UD;{24?42X6v9)h8Fq9;S;LyJ`swss^ zx#I7(CT<=iqIZ|ljqTy}cz7x_HR+ZC&UshT;fM-2kh)PHT^cbK{EQ3Cwd4Yy)CvPJ z4Ry(YOmmE9EGw$RoNs;Q6@Pl{EMZ0&8+Q-k-O(C@!2Mmn#vtNrEHm5|fWu(Vgkcdf zvZ04|u;)n?KVVtaTzCEN%fHBtk5dk%X-Y)klX}sq$(i_Cy6ZTTIW=hA2iNZD93`YG zGgOw`63*^}cJ$=n0u{(w3U|;_z+5(!_AyWp)&zv1YOk{z=oe_gOnXKH<)N@`Qn>so zCKYXO_b=jNt4V#^xs2k2n{$JgtrOJeDxi}WXi&_!g5y?@)Y62(%qgLMh5&-#4r?;S|?{S@r3-%+&aFcM5Mg!m(>clWo+|x z`47i4trd*ADoLq5@3*n1=9IR38WkFl83F9tj3OFQCobZQ>Ub}gx44|z)UM~7?m+}P ztb<$B;qtFXU87;y$ki3c*V*q`Qj*H5-isgj9>Z^ ze(5nuOr?}lbM1bHc!1Da{@R;EWThW}P(xu%hd)K8lL8WyOzDE8pH)jx+((wcO(4OxNKf_Ky-WmLnu4E*gXPGw% z_ROzbYrYsF;8e*JV&M~$LFbq2;HJg}%sGq-{BC$r>5Ho)3*Y~3AM5&N|6+MLPH(-i)ve$u3ls5{>0SOaF;%YQ8OH3m)YMa(dK4|$ zpi7Pb-r2fvf|F`KI)pknavg4Uy4OG9n#gzw<;n8yo~N}ieEF|`diFLf|9>FXB5G9dVI#j zA+ySLvb?e3nMm!}*Beg%nDJo0aybomy{RamU~bM@b)~ULK#IK>Hquj-j66SudN?is zClva2cTW{M8^sYmAEe~P~XUKKb&N@^>-&=B-QaQMYdqVFDrHA zVsP^^zQ0ONYTHBNy@d*Fg~jS#3KuB!Qzhq1_)Cu6)&nROiMUqH9vqYiGj#N?f_p?C znK4B0`H(8L^KS+wQhq@R`!&gYx#8}=VU=x0e6YB?o7XhXFu!Z1zxbB9VQNO8M@2qK zx6>-x01+gWs;1vBNNN%rC%@%INM(fA5p6f@I&L}M_%&4bEXC`# zCA(u5)`I_sXWDy?XEU>K{-v{Va&}F*HA9?*HY5z>QX5dyPfEW9*}Kz%Cg53Noj(;J zSP=6dwf2JvYKUPGzs4*`;t5)zIB<42K^L&^nBMV+B_cU@&%~rmW!c=2?Tqz0Lbz`R zh`*z)7@x(nK4J9!-X@c0X@DXot7)|~XOE}Ea!_9-Z?zM>lh&&uuB?{7`kSN+UjNC5 zYlWObnd)vlWP^|pxT{;*qSh)hhVD#iD1wv56%-zzthT%cL^AT-#TN58ud4 zu{z|#!?hXT_pc43C7EK_j)Qh?g&sPcZyg*QOx5NBCkBGj3T=cAohrgl+1cNx%l)q9 zFKZ^b75@P@gle(_BKn!hodR9Qa`L0@p7#za)o=Q-7`BHOi)v`)%C?@T>%lee`uFry z4JKW)Lcsjb;t~2a72QxS2G+CMm3;J%U6K}TDVV)md%F%p20Wi8xs$JE8wvmF8<4AL zsC)kv^EWRk#>zGCsyBp@GM~+LLfvN)BJU-tCE5{QB}6d`-wVUuYR&teWnB2ozGDbh z8z8p#TK-giNWOH8H}dL>~(C1(uZ?ow6jNfB-)Hjey> zqjkRf%-pN3!20oaBC&I=`XC>LzwwQ%5_(ne>Iex)QI6UgDI8rWuv04=xNo@ZCriM< zw-171zNU~7z1{i9&L6R8flL0UkQ>TQIe29nK-$aHX3#(Gq6gsFtFY`*+*)P_o_8mx z|6;QFrK(l(mwm9RNJo6(_HX|e8B`x<UgX$b8gVh&+s|{uyFvLp7dTSWp?K4j6CI2b8I66?q^5V-wrk8B5AhCrj)xuYWqO zs`>_y7;(nc?mZ!5bjas{lvT6aNwcpYN1pWsUi#|vg>*@TiB~`X3b!jmm{CnN$Mr*? z(D$J%L_wm{197H1zaGPjX!O){*Y6V=e1uw1#E7RnjY!N#J=<8LI{*B~_JZ_|l28&< z+mDeG9ZRZ~5l!qzRT!?FrYN#vbb^^ z8yLl3y*8LILhv=+GnzRp_+AH=kpU2jG1A52t_pCqKslBK7`0=#l zQT)+g2A)6Loi6)bY(Bs(6KQ5g{%mTTIRaJFNe=#aHPc+<9|KD+8b9Py(MJgw!!Pi9 zT6Mra3eBw3Ue)o7`1gZl4&Zr2#Dkk=dW7Cbx9YO)4VKv^8$3!+lt_ou)P2hRJ|ME7 z#SQ)+#JzP~luz_Ox+n^wBD*TmvAc9PNGU9^w3MWDN_V4(0*lnrjZy*%NOuT}bW3-4 zNiKOG_4B>I`?~l3asTGItzrSG# zX+pZ+s1%OyMQ(;`LWkr;nDjk!bk!7Zk&9)o?M%aq+o{^g+E1#f^LW!j^?sr$oZMbQ z9+7@leN27CS<*SCX7m0tcAI?YhSUr``cgwU4I5r)cWT->+ z(L^#v^7rYYtA39$6mGF&Q7r$a)F|c31m(N$zB6vx`;AXcUHB#Tl;tTy%^{7Q&}b4n z3Jv5#gRfiMs7zgM6rmfUlC0+ghch>d6=lg=OgHZISYOJPw8f02bv3$fII^s1y*w$X z++INrk_w)QL^yTKP%1*+EKRCqvqGB~MBx$3KB9_|otn-TS%9F#sihzvM1GGG zA2>cIB3|yvS?-w_oNN0n>Mb3WaI2=YxGxz}IuY&B1TIvSg`?A_MNTEb?6K`pSRz^V zd>IwZTCV6^?V~WR25}}-F^^PQ{U~Yd5Uff$8lhQ}fs@PJs;vPwAhMFZw`xJRjfpA5 zhDpYZwYPK>gEIu;lFgM%1xh+&dyKk@+|;LgQcI)c;3^(2^ynn3UDiqmI;;;XzQom7 z2sVob|Ksn`oaLf&a*^TY$Io(=jjI!6U3na$ZGIk0xOhYCt$2J}QJ5fEsJ!CFbLYr+ z1-T2PYNA^LUT6U})LPP)6csZo z`AlHHG#UqfugAF7=WzMH5?F3OkUajW{!;ZHS#inn)~J8hTpPn6y^4oOGMBaddmdC7 z0~h(T6QJMTN7%^idBiQA0gd7ldB_W{agAK-zA~< zBH|A%?HM(Rm2mcmo&>-KC1kQA{!NQ=balR+h;WcAH+-04lpNddFClo1Vo{4aom0pt zPkJpgdb(UN7BU@oLt<97YLGX(o;-@gUM*#%BJ53}i%w3Y2hKdE#(3a zvS+M({Br%r`3}e4iv8XL!CgLIKJ#cx^7!|44{WC5$F)lDUV7Ni$UlVdFX6K7uQ`=I zEtkmPk>$gY75P3>w=Rn~9N|?=P8+IIDRGj;s4om&-jOPV>pX~2epi}ZlgxFSKo;iU zga0_9sl)CfbL6qSFB3#J$+1a+KUymx76TS23}=mbAd?Hr1hXIN1y`qW^ph87FRRQ3 z<;1R&9|Emkf`Blfh~=5?(hX35LdzXvM$j$-nXnx`G#%Qg!o^b_I)pEaVJKAZpZ?Yy zFMa13>1efaEA1h_67E3IFR#*dw19+R?4g(@8!DH3SGwkt?T5}B)z%gq*#);aem$ad zvHskQY^PO+LYD@Yj1XTe5A_=EzzYL8&>V;%!w?h(-T{5onpF*`|JWd3Sf5+fJj_f zk@1n_2o3=}&NFjjTz`KfRAjONgaB0VzWCdK~xKuej1h^K5fVGl*#@a;D0v;b1(dj$fuO~Wjx zcTp@Tdtg7$fCVM^qBiSCGs5nJq%s3c@y~e%-04Jcc~c5jM-utqW7(R#T&pF4(reX< zOMJsEZ)wOuX_Vpn036}~6Ax=1GzqN-jKoNl>seWfkou z0H_DvT;wi@uj45;vyqwGOG5;9qp1G?$^Ob8KT zQ#U74H;6MP+FR{#l^J63xmd1QV29jCgY&Kl9XxwFP!9Jy=k@Ed{i4H57VFR-wX%*{ zDrvFmgiqsw-cHp=tslLaitHcjW^2{FvHOCA@kd$cnHi+k9lMy2cehgbV$M7V0JB>+w#-qA*ME@+Me6$OXdV8s0Feag=4T zvM~9Jzf{AoqK|3R*%FJeUy1s`l4q(v?F=a+mlFk2;)w)9-L749ywN+tO*Kx9zBeY#lzlh07hgJ{i z)0MoS2;J+Mq0FkdkH8@r>HReIOjtNU?yfbR4dbgd<9eyj{i#K&?e)y#NrsXo$%&!) zyTX!0Z_F=d;A7E(R?$UG1HmzN!2JvQO~AueGj0#@A47Yj+u1!#qe~+uLziq5)=QgK zG$1K-hI*b6**lme+9|D-^#?yHSm%Sf1DOE0#zVK#XavoQ?1Im93LS(GddqsFL7=pG zngF)%Hq8q0Zx3J@hpNC-^QS-WP}jc(F4ui`to#uxpR;KmhD1!upZ~we8u7 zaXd^$(0IYkwf!@}OnrrSKCE#>xm$-~=6xz|;060ki?9c=%PSBZFSu8hE8FFv_1u2a&NCxXD$N9B(#p=fkeaV+wCZGy)#BGkSRE!g+fF5xBg) z(gmPtVD$Z?D}emP1Qc*pC<@8^>f~Ve$UUAJ(jvPsE(;~{OmzFbxw7Z`?H!fe!2}W! zwN7lyY~)~e=*C0jeoJX%bHz^OR*`5-mYB!;2s{>mwUJ;bI9RxfdnVpW+}wBrId$?P z)Wl@8 zQasc6%+K##`kzKu#C@{pC92;t{w)?Ru;hVF)L zjMc4PEEM8jHPnMuf@na$ON}4H!vX1TrrW(lHHiZkYWTu|3pIN#OilsY#`xophVGN$ z>t+#FNA1qvWj&=3(*7B(VQ4e89$h|oKp|1LwmQUFakRV7bzB9ww_9QR?jIIc>co_o z!6XAGn?oYvm#Ar31^M3&x2kFzlkGPbvmpN9SF6)U6sxndJ#G;HlA`3%%iWcx0?dE8 z4(hzcfO{4~s7M5Dc&O~)OfU~&h&bpGlJ=Y0sv>2iLNN(KR+DAvZomja zG2N9uP4sh03njl$h*Jp~EdkGSugmvVSk7WER9g7LC!CO3)WR3|tyQe*_i0 z5RrVq3Aoe!OV9~o7fK6X=sAgXuepX9rsr9g>4A}ZZe3C5J7a;e)`6vuyz~K&2yW7^2939W{?9FS0 z@$W@~7h(|I>gdx2Qy6$n>0;A-_BW39fG}#CLcm^3+{gEn7smz84JoCwMXv!wia^wO z(D?nSWN3grMru@i`R7IRw^zR=Wc7MvaYOoKZC0yDKMC)nt8D7*Zg=j&8$732Avimn zf3`;nWQ@sy;$8B8;#0KsG#MQ4kN`KV2>#r#y48OC42Ks7jbM2CaYa8%TG^;ca;1rs zd;FQjYylckEuGpy?_YA(D2XqAdf47Q!eIh`trD7yW2kNb56NnM+$9TrdvOiFy4m*| zr|Au<^)cwN96DDDz#IYv5WrN#fE%qP5y@dANk9scITV9UN65o(w0lLhFA#t(R9?a5 zLJ)wp^7b3rGIS&fiTgII2AQ(bgMhxBLazzR;=W}$lFC4aAS#k^mZ$|-fdBr~tduxL z7!Mq^2XI%n9h8l`fU@+|$xt2rRo^5*!VpZYs zyY+@IA2_mhwBoT;gaAF5r1GT*?5Wv$o{{vgh#b$^-PzZ`SZMOb6Jfi3A1utUp5~O1<-=-YH&mB4OY&-VFZ}L zO*d;^QNQCcC@cWLEnld?JF_9W)&b%>xd@Q^=1jO4!n(oF?gP*yA<+E|vxfOX#B4g2 z1KgB4vN{vArl+Hey$iH*tW*Xgn(1LsDdy_?GAFo+vSvH)!H=gF6E8nDB=SE*f%cM9 zdB$wX1AjPBGYBscYk^=iPW{ob@;ly-czYwo^?((agjXUg3cu78_>AKb~ zL53J3a5?cOJ7OQB%H_6d-g=|3^HrvaNPMjP%dYgk%K3KoTp8Ans*&81b68NN!!%_XNEqpl(@4xX&0+lyT5USG9gzxG?B1QFn0!FAC{d|Hs6BRW?D zdUc1PHMjC1OZ7;|(@&Fm_R?#CHO*X_w_xq`=C*#AlnVMEEANEC`aN%5PvQ9ZH$E-j z$hfM&ne+L^^=75-LcEjulSHTr964HlED5gR)Smh z+>ohce6Ge-J~z?50wcdect@$is&Vo#hhCu;!>RMV64afJ<+;9t{Yonf(CQNJK@FZe zYlotVoRYVwS3k5}ZcVYuNhXpUM#?cOqP4<*1%D|`x*#$Md8aMKCptIJrF)nkd^^wh zF)Mw_Yff}7kAs?u-lK0IyJoHlB?SKh<<`x_KP*tM7Me;}zE(=D>ABUy>plbLDqpVVr{j7c4*SzQyvqS-JMS`n-_NYb`F| z=357QAE~>2!E-`e8X1f}ttj^7gA0C?+uqk8p8U+4u? zKTxO&_Wr_nR__IQpg)ZlC8c4P@l*4KaAwe8*IQ9;?4$*l16>J7yn!tJqG_cF>mjICgwZM*K|k(0=pDm7XzP zAOiHZln@17!EE0ndivmzL*PLL$6{pac*}Z3HJ4LuZ=a*JIMakr+i+)6z-;7^JUIW{D>bIin@4 zYNy-CrmtD*_Gw)R+h)R3FK91g28bWHZt$BlApxL-d&S@@o}VN!$yytODs*pFUhd`= z=10~tpT%`mF_bdQ-{TBFr`Vol_Y65SsNulKSxt6m9%q6gaU8%pgi z9#7*Wgo@dLSk6+~X0a3h^GC7n3FG|$98jQh3P-=q50fgl&it=WI9+Xj6c9N&559^l zTwt&AxB-@nr}%LNmrJTb_51ZX2geH(>`=WtV7?D>Df3kT8OQ7Zyos)d%i=DWLU8`F z_m|VAKTL!EGTM;%=b_)^Px7+}SzI7plpYLxaQOF&|CMkmZ^dUII;BAmHdG#xiN?pQ z|EAZi&AS1jw55LdmPFKC_W<-vX0i>JM!Ir*#1`}^bKB$wQRX+WAg(9X+v_Mk$Xk*` zOiN_CuhK@1-q)hto1ED!NthVyBK> zKrCmd#8F2C&oKB8iEXALHTW&R`@Fn^i^$Cuvpw!M5&g*>@za=}JnUzw)S9s81p5LI zJ6@+EWPuK3ur)3IambLOX}|K|-n8l?x`2@A5IV+UtDc2V3%{OMQM?~2#Di-4;AGRZ z(z+56%r_0LJ2PXRv$;Jp}WR=1Ta@?>tVs7 zgQ<^j0F&hzT%WcQ&j@z*oTx6|1mhfl*&UUllI(I7Ox$G()wAt-=$&bYfq?$hu@F1J z*WJHKbI5Lmh^5pH`Hjxq=n2dK@Ly>lIAxS*Er!u3$)4v+CueIZv6P+~bP&3($8LJDI-H`QCFsX2fw*p%=si}b2Rsn-pFZODsg_BHCCwwL!mn$>*G7M8G3Ctit;{!EJgd@Lw#9PsZ zk(uxuTaMB=(&bBKyk;i=49$O)CvjGUole9wR9NLzv(&=$U6APMX8k&b-JJN z4b_y0+d0>Dv%BKw+X=1~Nw%&*Dfa)7l!p*;s*+5-5tk~*XJ2uw zR;hFU?5QX}EMjCmpr^|Yi*)%VULBY76bxWPy+z{oJ0TXbU%*s`k9zuZz?a_%A5e*V z9WtLKsxO3zPX_dSRa2pbWZTd`{U5Tz0kV|SSl>$sQ9JsG2ZyG9zyBp2R?7MCK{v+9 zmmm2k7OKKcual(tJ#zQG&#RbBawWv|EIOCmiQH_xVUtka22*1gyJmI3UuKQnC^D$a zP}w$nPW-o{nZUzN4V}dno?nlD=_8Lg_nlP`@wIAuN&QtigO`O%&PAy%tzzIHCy;SP znIW$>UGSO+b%v2o%o{Mt8Y!pW3AephS721)TJ4+(#K+Y==y}-3hMle2a9d6DIqdG> z5OgON)o15&4|#3REHIT^m7H8x(9s*z&AL4O8~~sNx;iXtCHTS5oQHkj>?anP7!GQ& z?gplGojfws+59aFx{ZUhILEaRpTaL@T56d#aOQxXw4#`eYFE)p#U-=#Qk-!gH8Yv1%M1Ukz6$}qJeq1FO%t%OJ*MK{jRg6tOPcP3I zo|v^DT95we@gRo7z2_GC)IczYUTGv^;e1O_c@@&OKdk;n%Zob142mvEel-~FQ^A>s z@GLyu^C?Dl7vx0Reojgzg$=kBh(};TYwHLn=_xul$KJm3jnDTCf3FQ_TVw;8kZy}48FimEKtCq}LC>{n=~awP69i=T>_7I&U zK~;36=+?xkU=YR=&*5irFKP95jK_Yi9E|vU?~*dMA*~*JVDWgPuT2z)ys-B3^77${ zJ-*f#8G}ZjGdB<3&oNKar&VLS9e;bmXWZPnIN&eCL&BjdI`@q>3s$oA2c68(To72H zxZ36u0^7somw0FruKG=FigZfxtL7fOFNe?`4Q!E(+SP2nIQ0n#WRqDhkS6M}cluKw z$J%jjAa>PV+}Hd3_*b50zBuz}GPzsoS4R`*J`YyH7=V|{X(c$z*Z#p8&kd1;4^~>h zm+%EbZqRqH70b&k46a4?H&Gz0^fB!2DtYBZ@da`M!5RKib5yI3bN{Ed$A|?oin`y~ z-7THu8q&rFd}iU!JgIyOh0dN=A21DT%n+;3S=|a6^YXM=PuK+Q`58qfk0rf4l!11> z){E|DcF|95W>9%tzz@N5oLb``^Fw!;r6`Br%ieh&jJ+^?9Z7GLAQOmm>6ouBAdRCU zPN}V|dS?Hm|sz+Q6kdcwg4T>6!I;^FZJKSUkB)x}gK4h^0l6yVYgG;zV0ceNZ0k!M1h z%IddGPZK8nH%Q8=7xZu-v-P?Md}6kdytaOl57=<$%S~8JZ`fmzq18|A0u8dT z^q(lD*gf;;`EHU|@RYu^gbgq(N|`P_A$$l-`oJ`OJCDrK$7m;mIcy^j(R^}wknd#`ApUEa$UKjb#*9T$~yHLKjiWyoGkri zR9W9T+HavRZ4FvHM?S#cb2qTyPGh9d&>)(`Sw=T%vq8_{6iER@>Gnn6lq5LsX?gyi zjGRRn!nA4xeGL!r%$bY18?BZjwLIZ9fuur0mf7T`@djTl2^8Tgfo+lR4;f-?*rI|I zzOqxIXa(ZH=iNycCvRYhlRx}XGBgkYnekwg!C({DE3?Na-$F<| zbr|CZts|#W+eB{o>tR(xo#mru>WQwN=f+;Aj?aZ7i)d>pQEqtXHD?pjk2x;;$itiF zRB@EsRlaCcUaC~T2b}*#g^q7O8Q)Byw7R*J5EcI%L?m{5w+9b{JBH3P(U^lTGNa%XL1>i{so zL6hqi9a1)qJ&+j_5;?qA=oc>hBi>6q$ttzHz-6Q81JS@ zR9i6Sjm{;u3J+vRK0Rwt!(n(UEq#z~;kki^zQ)%9>S3if>IAV9v|&{t$a~+a-`2){ z5MSpODBR1qrh~w2X@8}RI$^0-vB?V+9DR@ zh1kMyX2)yaJo)lNFnsY!X!iLRimSJRj7rRbpQuFCi}9a^MCT+tcW_3t5{7d*;C@EE zn=@o|8cSOW2f zoPAU=4wYQVA6(~lF2^-2qCdP)WQ~n+KD)s3*HSs|qe)2k_m@9EAKEIp)D#%nVRUTP z9zH{syhgYC(K8fmF`k|$TLryD8Q%V@0gIXV*==`}c{kB&YXgh)?m&(<3) z96Q^lpe!tf(Cv4nWUaLcnh$dq0?;X(bDA#-8I;h0u^u++@Za;=$-F`k-SVGt6`Dt1 zaX7UEAO7v*VPa&ZOCGayr zBt5?ssfla!QhnjzM`V0t*xknaS2Cl_(QH^j;jyg1!pFO{VW)x9&%IMn<4iiL@H4Zt zJwo}_9^y(dQOfoQm)3XK;8NTyw%vJ$@w&E($9GO=T+W7gGOUbDbbGGtF8DQ}NED`y8!~EQ{uCYT(+2Eo_ zEx{kQQ+rJ0gAtSRH?2cB3OswY4ijghLhi;$#>E(Sxw0;zy~?MP&aFPkKq4O6o452? z$=|H8YfITr(-?><@>IYF?p6R+rA`uoD^q#+s?Q{LB z6^#RYHeaW^!U$QyP7iRCt-@y`417zMkV{Nz=J;RU2@+C#RPp&8uO_Fhr{G<#XPD-& zqoqJnUKf|Xe^Z5}(xG+rW&lEp$2qNk4ALqCmw*0Lj7`lf;)n(IulP)xrN!VnutC}6 zK$lZ}=P*hhGu2Svj*JO_mYO?d=f;Rj*a?ktgn5|CU~whRWwLrxs~1#eMvi zUv*r<_^Mua?uB7biwVl+5k$Nln<)Y(0oFr*d=N`snnTtvZ+`=~6{gm_iS-tsL_K&y zh5BskRg^Srt|v0P;?%YO{dJFS`aHo50~%5t8-_-rV86WCAj=*x9OA*Ar+dfmU<0VG2=#3-(-f@;^DOslqOEHl@4O)f}l zfKt5|ywhS*7TC{{8wfu5kFG^&&7tU?Vd-CLed#W+v>bOc=*I3w5qa0Es)a26J6j%a zj1qfeW1PCA>aNB%qipB^_0ZZpFNa3jT~adB3PJL+j}%`!R*=c(8R5e6ph2`_}DBmzq=7^=ZhYTsO3In6IufQ2;rbHeHOy%Il&~6|# zyiZPO-ss;{ZWCGVL*uA5BkBDs_~xZ?`kG8)Ft)Ohodcq=(lhmZi)3cCFIP?ou^bo8 zkb?EYhHD;<_pF$>>8O81^oG4No}?*3VUSDO9YRcj;IDvB0u+q-StU$`r0^NH#q5d} z6d6zsPK-i{J|cZ2-~7-pPvs2PIrgdDyO~B)EaPoe{H@z0$U09IsgRX#JR(^f6(Kpp z#b8g}|32R#+c{B1BS#Lb@m+1SW0FmUF5;e^va{?%DB7_!oX@oZ9Zd0`g4K=o$7Fyj zy(T_=eMN16_ApxL@(7SW>>JmQ`S6_Rz2gc4ukN7S;engDi>aRWh+nrjZChyMQ=Ev-*VWg<5z*fK8xhprJE>&!}Jd1g73S4?$(wB zO#r?aM97O+7@TILYImQ{Kep~C$4(9J3<3cl5@vDm2)QF(S>8GS<8}iSl#JNqxBKEN zT}dCMr zL5~;z8Oe|9Ud0RE9md6X7G|*y7Rlm&G~X$32xYMh3>-pP5iI?{QiNP&#sgKmpy{L3 zmTurMAsp|D;iZVIZR$Q3Y>ip$xikX^%H+3;lqCT667QjXy)KMe!t3@&gg9ho!aQ%v^ zBZb6T&&cerh^ORm>Ccr|Q@S+QXYC^U`IjdMy;A7bu;8Pbh^9)u942nO5 zr@4sUziVgVj5#=Z#(OqN=6EX@LGv2w*fGP`W#4;KrK3ifd@OPdK%@og)T`JXl2*9s zxE@gxG1=|q{}KQg{iXCYHo7V5n}Kcy<<~3A?^?m$Il?oZEUWDT`vUcK@??w9-Jbr~gMlfL4kcQaTe3N9=x z3%De&xJ9Xf(>GtT;1C>QI2~|CMh*}o0`Ln0t`@)}iNpoQA`}cvyWM}^eg~caXWgy8 zuUP-4%?SX|^Y1u`q*Qp9Lq8g1yuyE1YbAv=kVwIgu5=YxedJjE&qjo}vf4ZTpYB!r=2Jz+f#r_gy7&Ns`VmKjh&itiNYrMl!zL)Dhs z-=Tk9_y13S{@y<~KIh-vjKBVSqJMiDe?9uRe{;S2>*N1FsQ|qG|8Jkqwe(VE@)H8% z;AImnxz-@=AgLb7B9lJsSgz3L_Ot{IS1N(OSM*){M?OImw5hanPAxiPgtvF=9J3hH zu4|iS;Yn@e9R}V&U+I=`68GW-=t{ZQOraODPC_oOTOv065 z(EGK@?{c_r)vT>9LqIeL_mh&+r2+(KOqVs=^$E_i$h53-(|CMP!I5f}?QNne@^RgU z5=Gp%SmR5mw*VM~yCK_K{1xM)s{UJC(MYUAl?7U(Fs+;n7ne>YJTo(E;-Do}28^8xclac!@Ifj|H?x z6Nf$zCqjkdzbE~E2Oc`}3WK@$9F%TChH^E_39yY3JvX`z?P zEvYjE5$grlv|L!Mq_Nw4q~O$g50_f1sSC^GMLu^}3cBwnAX6I=)MCLRHbMLHM{MVh zzCZLA2hpe^>Dkinw`ZLxtRz$)N`dcW-Pw+ z*J%nX=se(|hmZ8qe(2N!;``Gjy7(+qJzIwUJWgRAt*z~wL#mLo!?3uw^u6a;$W9Rk z!v7^GHdaRt!k;;(7c-2-r%@kj3AO}*u5FB8qChv?wcsUExNqxEPH)=N-M}A<5ru*h z)X0IPX8thU+aQPcwBToB=D_ivxhZBxVw`8e^mTyMx;i75f&dXg?UHfkE_|JFLA1ue z#L~DmLW=_efm%LY73|u*#8Cxe`$pma-~Ms<`v!<&8--8wzx&aok`Nc52ZW2&eehjE z1&#v2{?yC)x8DCB9*KlcoF+JlJ{Xlz`Jc;DTR|glvrG8LpkKXqkX2dGoD-Ol?e^%^ z?#c9z5at9-IzW^DRkP3jDpH!i8kXp<)&=YWK-1#>Rl~rX4y6Bo{oGrP4`&*TYU)QU z5Uvadywl_Gzl}l|T0$L#Nl_ZECnKN0IzXJI&nS#&3itOF@oW0vFV4{jO8{6pkREcv zlRj+w<-unoD3~M(Io0Q*5+4?CZkhOBqCtT*S}?b0)C}v9yavz(ra!QaOz=*_-A#Uo1Yya)v zsikxRh6T?u?yX`_H>w7D&D|F%`Kd47Y7%k#^cfNI5bj5Iu{^v9+XrP@cg{3ET3Faw z5$noA-gDD=Veit3`n0$@w$Vr+wc3V+XULntsdnt4#*)xk3n%zXuipAxg%|cJYaHcI zsgw{e^8y4fTN$52k~W5+qNNl+QamsEG87j{CatRAIO!O+3% zVQ7!sR$G>;(9=0JnB&mj)Yk=`_1H{K2x@JR1QqnomnB2&T(Sf0(V$=oOlGomO#f5- zKFL+JWmPt~Yb(Of1fEf+(M5u)y^GaWy2k~Cc_2YC>?0-WvX9?wAWaa)@hA9b~t<7u?PgBE5jq{7QT|Amadt#P;_S2L0E^X6cuM z=lXRM6dGsmW80A_50h5E{E)uD4@E$0c%>J}yE))u1mM#wB!Zps4s4$!hb1J3FhmUJ zKMpBE5p|3AH#BtM84@S}ECR>|m0s{}M~_*kU7R7iH**W@-0$nqogSmxA#gx+VA%c= z4dlbeo_ZZ>lv3EOp|vLg5I`V6UPLHHpb3d+c(aY+2K+>m-x}w-k#J)mXb2Z%wo4Me zaJeZdA{e#f_`||>`0xo_aD$ImqHj13*y(ny8;`BCDxaqs82QM~YQSk}v zUyae8RW}I(jVG4Pd6&B6Q9oRyDB_-^s@zrZcFvqPl7vr~ch_~h`b>2)s`DA7IeYeA z#1Wwe=O<4aUrJr2s8~OKXH@BBT(}>bdQtn7s-U)Q=*8r4I-+ZGLj)ilXb$T8P?fRG zEdePgx4b+`GJf+-wKQY&3!%#lE^F98&3N+f_Z1$g($?8)Y7bf{e+w`{96k0G`dfnx z7dbWC0)AMz|K26rSBw|Gqv<%`Tyto6q(Gu7n<2O&s6 za(%tKu;-LqIOgeSt+X+n5@X4&l<+-j^jL@TOk7{Wq5uc!UvVn0yt%kqUw*zi^oAbNAAc+IjZwohodx4}hvhs%4gyXu*@=PD-9WGX(m{%SKab^Zr3z=GhxiPR}z}&92L#N=YjM?d+VeyFzZh}ho%`B-+$6L{mw}?D`d!25*~Ur0Y<7YX@! zgL%CH;|+q(pv#Z#zAnP^4{6{T(T;YyWik+* zxy74L6wT+u#?|_$R;0gA-9oCT?oQ7rW@ymu**$}guyr-h7CGkax=S%aVh=iLZ9T6f zs;->F4F8qJbySm|Bip#LIk)F54v(`;99((ukvf^!i-_i_Z5U|ji`uHab#jRVMP4zB z9TFb5qseU3Kf<|;gM2S=izq*who0mgmkOdq`5RtI6xG;$bb{A6TE}>2Q$D(@ZW;(> z{Op`q;W3f2_G1Acs7UWAdA5ay8XisYP%?i5X;;;3-NXNi@GZ)}|IkDx<2U7p0)IAr zHDd2RX?XA4Z}P7T<_+hRDc14LLPSS`2v1;b_=J)G3`4V>mR|0pCm8{ zY(ux)7RyWzm!qMYD%!5>Xtt1xp8bIQMm`o(KJ*p5{b=pZBLNCX^7(`7P=9yf$F#_A zyP|P+h9uzvY`0+lx96`t*ojv`F=|{U_gXQ@*@>6fS4Q6Gu+l0OgP&}TyXzE-!wX$1qOgfw?oFf8 z8zTg@<|EV0piAURqk(m1P~B z`Gzh14fvZ~y(3|KQzr466v873hoHXvX;$xkFsg0$b*xR2Qjx$51dD#7?*VqX&C~DkO@C6OF@J!aLCv1}F;Jj-9tFui& z1mX9cstn#ZL@|QQFbS?AH*b3L6--#0i zt!{yl0=9yj65WbV@PS>jzm4U(S&qpRQo#lEBZRywAkiJn+Lk&D_&5Vz1c77N@nNByg4$Bv_-!0t?9Kc5r~64Y z;%2#QP#c@2=gV3AlXHTvIlpN*ntxX8Mza3g$;LP_!dDuYIPa!e(f@0F@q?py2z3wt z%ZtU<;q)D@#hwj`k5owYagUP*S75<*8y*vpVF^H(V-NmBsZpW1w|MG$A*W|V9-rJ9CgktUn=$Q`RsD=0 zQt+pOl+i%xEl8?0wFwrv(9{+B5U(!u@*)I58%Q*D!PjDlSO`h|dfI<`VaKq0{`<$p zowh!|qvJ0>ug0oy7p{I?Tqy|1WFVUjk+NOBK}L#CjGeX|9lka5?zwRs^I`)8p-=J2{MslA!W^A%ePs$(^Awcy=!~r79ma1iE z{A)fp$mRO?kCpZjexK&*v~Z2*_AXSvxdta;18lWi5bVCG)Su5%hld=ynQXJw|v<;AD!D zI=4m{FAL^6w`^M&QtnoaD-FoO1{{Brmp+5nT(jJR^Z%sS&M(4AMh_BISZsL1Sh^w;=~B6okl#V&y+-+ia@o}$)=LmvFIzyIsyhD-GHnZ_)6^hNS$Qysp zBg`(oHvvPN@;|kB-X)!J9y0F-+$aQk;DBU}O(v(`NeQK*V5!7~HauUV|8X8cRq(Fc z9jH=vc!gt%9lr?slWfE$aC0T`%@&#YJIev2ivgDig8c6;+o9Sx!~DKhoQ6rA+j8s* z3iBe76`a%{VfwnNsFrp4boraSo~_9@c@xvuH~gsl5XN7Lt&#|2!&+g*3=iE}BmV@* z1|c$vYLInHpX}79b7ljhLKkf^WXm>Tf< zr;$M&twbOvnaC{`uq5hgFiN?mYwqCIO zVd5H+|MfvZhzW7Pr51E0*>_PZfi>vsmmkUi7ap&JG3RpvbXP{ni$nXtXhgc{NS_dx zxv3@=5Af%{{St_*t7Q)VB7M(Qo3FQuZU6>7W&OIY`0D>??kc0AYTNaY3P{aJiPX#p z(xG&T3^3FH(%qm)w=}5003(cmGzch2cZ(v7fTVrQEl z?^P%`0FGac?BMJ^u_OWwN-!e_IJ6Xvc+-z7c+&B(X-Euv*;5_fN)rC7HevF18R-`3 z#oP7_5m~)@i$WK7|B7v&125%gyae^X1BBVM{r`qbHF-O>-nl}krGvSClPX-b?zE6F zNs_AFzFo{cZ@=)M#~GMI{!QPm(fneSaAv9SwP*;Fv_lF9NVMvO62aJjs|)dgmlHF& zg;Fknm_CR?Shy(ho1;O8*aP?5A-tH%8~C_q_mPC&KEo5$?D*-U#X@lW82p)dHtLs5 z&7gxqMsO&m00F{WehJ3A4Q+`Jl&trnBF?#~0!v;q?A`b%Jrj1XsE&o`BdL1=@lrZh zX=X?KxRDODWkCx8jr(c@Jz@cgHa}G%yvOb4AVfWr8A;7W-RT&ux;j~OtL4Xle{^>( z2wu~^S=>PpH>G8KB@e+`#5=V@(V~hGxPjkLvSp`0NdHW%L4^=Ju@(t3*U^T?O&ru# z5^T-_u@r}+*r;bl6AWlWVxpoEAufPP=_^{dalCqTJr4*tvi>iW3IP9Ipn5&nHgV{B6)*wPJ3 zjZ}yCc}3;xg}esxo(p5ezBGiZJaJ(I+8Z(V$8sn5{cfAsLp(k9^B;70q0c5hTZ_?H z0Qf2JCQ28U<09JOHbGV{0CWd-Ao<4G)H4_Dg8_Wri&1d=0yIuEz@)+PnCh`Qy8QO} zLnSTB^Bc>vb?4+;R&|H=PMojp#xpmjr=g%LES(-?5BWk&KNE4mpNu^xa7|p_d(OD+ zJxg*ad4Y%%ds-Gl|6pN-j%}fLc-wpy=s3V8$$I0kF5ru3#>8jcXbs;*6kS@j9{*g; z^>&M_)s8t44x=P>b7_xEp;g`_b5Y&IGWCf~l89))i351o=hx~!FZF3Xi?(64vpie$ zU~@xZiS6r{jBKiodwSKr^$`CQroQm@{Io&zI56MaV2}aLWy{oPT#aUzsZxVJjoDAm z$G4PY3%!5O9jhOEY1;rxNSrX#?Jhi%TOHxg?v3&43(D-RN^@9^15BOnj6~u{um`D1 zH!uZBgWp966PaWrs-k;5~i5 zMAxLO%o2Gb15;k5OPb}*$1tFS`{V04r(uGR+T*#S5d4?AvW&mccoDxgz{RWYi%1px zTC*dAoZP1iG^pE&QbmtO0{EmpfNqbp`v*Jt2xGs8qwgbPzdYuPekVk>wX0*9B7Mj; zZVwUd<(AVAy?9t`B0j%Jw$9)E1~&OMi^2Rg2JTzj{+>eLS8VqdxMxRviorE6i&_8_ zzNj4-Q$HL?nwny8Go;ogRPlt%F>cN&NY6H6LNi6Ha;&t1yEhl!99}Xyk~N;;zD;bj zX;~W@<yF;&bhPuie>K>Ir(2 z&kL{3*Qm%9EFAK$u$j9mYB^pZww1rKn*^3m`>~4{HS9nW#B)A+`Ha$T49C7I*cMwN z>&_b&N|&~>+}VRTN0!~#n!X6Nnj)+=RhYF?Ak^$h@<-p-Oxh2W$^vZ+yn0lecPii+(a+`|E7ykJvGaliknFOt8PmZwGX1eGw+8 zT%WYe5^YGzB%vEO$GoCmqQo5dJ+6x)%W zMnV@bCxWe17>s#7uft8aXA>i`tYnq4Qo41pYn@bvV;Ri12ajx92A8d6@Jq@WVH>AuiWvy7qL~P7so| z>O$#ta#ce@Y|#oiiGgjDY^pt)G7oKH5U{_c&rKyN<|JtuuqCQ#JA1?De$zsHYzx@d zC=yJU#-H^rkQ3HO=2By05mtP^!y|O9lt)_mgW7emNJsh$_2)i#DOz!BY{jvX90H(H z{unN$Lb97E=);Difx%^CagU*+TP4gG1b1vphXo=F!&8%2lUug`9NT%0SM&WmUU#Z6 zY9F20-{7Z3qdr~kq!FPmi7n3*6OqX8n@`YZ~aZ0irCN@dT<(f#v%Tgm*pb>Q-82>#QT*uT8J+tPdlL zO%RWmOd9AR620Uq(Lo~4v?lFOEy14jhBl9>*k=wDu@xhiK`F{4S z0Ag;+NeFD;)v;6Pd8|}pQTqk!LP1OVqHW2kTffCr|A|)7B^cYJ0Y}TY|Mmx(+_$Zo zxNBvt2l&>JidJTZ)+@DLf`#%nXzgBx@jLL=&VQOb)C(YS@>iXFwPk{*hF8}oXvUhq zHMY$vc{c}M!uq;4xx%eX7b{#Q3$VqVR+7^xx1a+SWvo1D%I`@yn;|o6(ubQ-TGm9a z12y-^E&+f*yul|&7>lup{Q?&l{hIoMO5g+Xhr?x>4d0JDzDh__XK_s8`lwZ^-%+nFznnvUGf$9gbJVbJ zz6wen(!l5fBwWXQBKWVN4;B`8_X&;1wHt%E!B4wwqr8LbIan%>((|n)sk44uN5!g{N;eLU zSxD3tV9AhL{!&60RAUkb=fjfeWYfQsHd>T9DIe^4aMJuM17VfnQ1$Yqe2modFSF(V z;-u!W#A_em5xQh=B_cv&yMlLz>m=U(kEd&a+X744Ng4rt`*ybI`OE^Xw}1z|-AC>@ zF}vtXv#`8)+{Vv$9X$rMt=zg68OPF9EKG)g4zJ+MMF~bmK}q&i7NY9+guB!8%GP}%UIThJjgv4t>PRidVO3q%4ayapAdyJ#OX zF)+(CBM(hf+I%8{Jc6GQZQ!Q6-B)_;+X7)>#q1xXr~66)dBSSC=I;5#eAR8MGC9TJ z;Eu|x@+B1$qATuP-N--fQJXhQbQ#tumTh15j1Z;ySh$kd2 z8B1SJLR=c2@cz}YRY$299(qHL%Qao(LEm=QA;8)KMCia|R=hz*mgm9BVsi>5WnaX8 zN0I{8;ACwnec#KSI4E3au@r-g3v_uW?~SW()GtTN!F@aXh1w@N@$BQX9LBL@t)uQ_ z@zJQIYkwz7XyZ;%noDX`chYpwpWEbfuCf#^OlYqodVwdy&@4JMa=Dg7%2ljjRW%RH z8{jT@Nx$+*Qxt+g>HBKugQ!PRf0r$UPf!+aa=tAn>JE)_W*@Oe8>M~Xo7VaKQwMky zs+(}VG#bZD;Y9E)Pp;TQudAn@g2C80=)=zDGK@M_v@S_tb1D{DBMzggECT zcSU9GNqa}l+wQ8jwTZob1gA*B-ZZH(LN8*+x)`+UO;VFQeo{)smwjiS*z1E1m}h1b z(0co{A!7g@9H_3kCs?sb!jA9F3BQL}PJQ>APGwH7dCNxZ|K1a$IL%##pY$MjbJujS z_k}c6hF#%wui7g4g4oT)^ZAzf(qtLY_5IiXoN{#hBTp2Ncjy@~_>LZ;`D^K5X?b9w ze}5zRQ2Ngs=>Qhz_E`*cfZf<84uToI|HgMILCLDK>Fq1y&H)Q{=U-KUeZqo?NQWMH zG0LnlTF3wXJ$yy0zOq2EQ=*BF{J{d8&;BkxVUjVpPfe3%_Tz>mDt7}uN;7j6KpJ-PsJ-HO> zGxt-G*WH;h_qxR+6zueKOS?Yh#<5g;O*MZIR_kIv94tz0FXY;bP`D;SrkV$7(X);+>|niT!WZZzB=j z?}i>C{l>;xkm(m>dP8k2u3wh+_x31MFpzT9sPFdSI6R^UiQ`iVj&=>9?Uh(84<({~ zV8Ct{!lSW7oj;1(-#z*o zw~h4NjsfDIHP>f%mB5WTps9bNZn@`~A99gSS#1%R-UQ;8tUH{zj3p1J{<9ll7XS}I z(7F7<{NRWKojF!Eo$x8J6jD$qzpJB~AsruiBbGDr zq4z+#Zo2XXRsCTP8(ABRNPnu$9*9BKQOPFL4)WF{xLc`n@c(-3mfJV6Fn^jLWxdK8 zL~15yteBwYm)dRRl$ULm=|M&k;9Al4UDps!d;^Q($(?^__jfn({S<@9cfEIIqAPuo zSkKBw?@oO?#FTM#SdrC0hFrd{t$e+C-|4kwi>;?QOi!+wYr=1Xn`}Uj*ZEZ`3=+$C z3+yJpNpAa4M<5}vm-_CZ86ZbSU@B@ye&*gX5g_TzykzGHZq^OUlu{YH|Wt(!VzSu+0y?qDf z4t?7rU}JiF9zl`cZO=zpWL_)<-l`id&VyIJ)wmda^c7lgnW|qMsMyRv$KB3=;`ULx zj$E1Xz<>eSX(_NmiA`94mRws6i{4%Grz?%aJ2yPi--N9?pWL~@Y%;KGePaYhtw6C) zr#r_c@YkRr(g|8ITGyr?DCy^KjSBV>Jw7NjZ*G)+w0p3(_p#g%J{MSsUBNYc?k0S1 zbg$V!d)21@wv}PN?Q>^DSa@#Ds!_^FcurmQTp`jiJ3AWIxCqg|7(tO3=vKI7+fX_#l{pq(TRSLZMjtDWtt<7{ zM&r;GU_M|$i< zZvlJjcNIRT63(q4P&-R!ooA2ZA<;puQK3#3FZ*RTST}irly@H_?nkAqRDt|Q$O4J; zivRGtc+^c=mHP06s14C49|;jJG}!5(ZY{mgt%&zENzOmhe-9t2ryO-1@ZgMPU!Uyk zuLI{96sfA>mMezH?P?4&QgqyA4*KiCCMU$a-q_b6Q7o5%TJgi{I61Z#TgjCPjipZx zT;Zur?`*zdOC*J`!0`=)^@T-bBYR#aq}3*%hS&!y)|)+}?)vF+XM8|j)$Rrl-G8k! zMekp`Xtheb>|Fg!&E3vZFNr-$jUh&|PXARid!?7xquS=o6g{rs$*r{dkSnKyq9=&N z!4o4wt&Z3zf>H z;h4A+$O?|dhg_cebO}I5?!ZwC0#s;o&rFV0xR1zckIRbJf~ZrP|HrR^2m;DdPke1o zf3i-{xyX2NPfNI;Ipcd&j(69xn&f!ZK%aL}^KSfzMo|k^F+KTb$!CHKq2FJxHkub{ z8q(FcIbs<&_=??vNauAwwwK;j+BfCLk1sgt54;cxnJ6i><`+oZ%m@H*Pk;mDgu101 zZ7dJ~=m{$raF`TYY!)WLI|rCr)L_^zYk9gqd@4W}f8W9&?7*Q7Kn5M2YiG3$U}ho6 zbal9U6GO5jl)5E{8g0FH)|fi-Aa71v9h$XgLIA_Y6r`ejhRSK1C(K21=bQ zeev|Xu70x8E9%h03y}wSl)opZXR~Q$&fN12Zl9@frWa5O5XR(RZl(bA^$e(C@m{@i z2EX2kd;bf>eO2K1?d^VO z0Kq#F?7I!euO^&H0!V^kB=NFyC8J#_aVASErxNDB;|igY(9o9+}4X;eCg?rw(ehB<@3 z_kI6g&ULPH{m+;GhqFJ;wV(Ce>t1W!>v^8N_k_HG$Unh-h6@6Lo+v8FXn;VtFc1iv z4I2Y>=c`|e0|%<1^R=711>JEzEX|z^YfH1qU)^&el|Q7IxH(I zD<>x>Oq@JmF!<=`$jQm+`1m+7GP0UVRCWM^jw03anLrNS8*?k1?G!cddlceIJLjCCCw8|%$R8faLAjF;+qm;JXAXHeYQ`-np{}5J z(Zo2uha5RtYHe%l?C3}j67ShW<}bB;^bUs_I3aI#ic@}zYRe&4f-ZAoC7L{pI-~Bo zUl&^;ql%gjHD4l64*hH57xSpq?DP=BlF5{8Z8@;wBr{`MA)IbanUWC{UZ6oVuMGABZJGwm%;1NUKazc=QN|9fdTI z#x2}5T%~ndrMln#xg<{h@A*jMH-+1<2MNQ-oGIk`08*kHnfDRD&XdsibMsV%XUF95 z{_kBTXNwa5W_BT~3Eyh{Z(jkTf&~9?j(lw~|F==Jv`q2wFz<2vZj31<|3BbN z`eUHoG^+3-v4pw**CJI49WzBIv&0oj0H))@dK4&*P>e%qW^Tn zFQYA0c`&jvnO7nos{VXnB5k%xNg|AfH7tzQZs&<(5Y@XfU1Gt?$^U~IiwBv9VgtyMh4 z;a`X-;PDN;nZ9)@ce_R@lX{%H`%I%}Q^mzdFNz32f%zK7hfUp>a;5nA!a9~+Q-%y> ztCDl?;HmrF5`P6*oOUi8=XcwJnz5AL7%-q_YZ(pibi6?TAQ>QxC85ei_ zc!R94+c=^l`Rui?u8{~FvbxHxcWik6BYCxF>-7ZLnNJ-PB75XX(u`tb*=^*R2&1BF z!yt1~cZ1}D;r!1#kDnur9C>-LiLCx?%^IFO;UD3GzTIw(&djynG1KEpM@i`w7eKZAJTG-lAa5+>X|_RQE=yg40S|N{dD|;Q zcvH$9sv0Y6(y!cYRZKxV(sw%4rk@Q{Yt@y5>h9}szd+90i(QxLzSs9{ci_v~Zt@0$ zuTS%6#wjfHW%Ie%C24MULoPhjuHP|l!3vBXPMAQ zN>KKQ(sEI@<;r;X1kwgp)|4xy=NsY4&B-S_c3}du%S-OrJaJ~WV(Qq^y&lJ4@pa{o zfUwtn-ogYeuFYnRD02z2@;<|I7_kAybu53l&o%--nZCrYXFWZA7AFs7VW!C)L}gKi4IuLyX-M85OBb)^JPw`9;fDc}@a z8^#At7Ggn{Q!kN|&OM+F z$D|ug*C9vF>mJ1ypLS0BX^-^h zcTyj|C#@tQp8bW^mb z4@+E?Q)~p_ZscYIf!S#{{sjwUzerj8!ThBVwR(USEd=Wv!QEr3HBV#593GwToIO2L zuX$>#XUn;aklN$S83~5nqX)f~k4oAjc# zAcJ$4GTP1~v}9f1Nz&NJzw^=6-zo&0Prk$A;h(u>U(zWnUMX`p_N)mq7{fI4|`Ydx-sQ3`M z5aGSesmkTWNGdXqIdVtD3n;&v=s4>XPu}K7SPctdc4x$L22q8Xl4*ReWD9V@@s4hs z?4d4nri|;-xY4>l&-m#tO)e=>hGL;*tjH|C(N!FXWmJ7xAi6d?GYA>fkDuh3oX;Vn ze#`pQYE|o(%({dYcw6~s{K>8E+bZg|@Es3XaMd@a)S~a%lXs4M0-V5*0=*~||CT93 zLs}xl&}~4J0=yX5P00yJ$`ktz6d2Q>oPuU?jkxWUp=_h{qc6Vd3s5ZmZQ*Bn(c2q8 ztA|*9#Eg0J1!mzqyt>@k)5)&dQazvyT@F8ivGp2pN(-O#l5MzXgFB~x*dj&)f|7R#3jc*W7b?-m7j%4`J>N=w`NT z45tWZfAZQO+T|e2iQ7*wVzyUg-f)owkNv13|HTQ^AM6Fd>V0_Sm+8LUJyG0BdLa!) zX~Iwcs2NuIL^mrXH{{7$JnSJ~`+C6NuOq|VBi|p9#g;4Oiy1a?0!zlqQ2XSl+!4bh z_+UI-ku5(FE-7QJ3}yNkeu(C9it9{r5AyPM0YDh&NkJ5ujUzlY(!>(r+?qemxO1zn zJBO#jX6x~Dd5n|bWiNo&0r2!x#4IdP5C^sGf@;b3m6^-SgT##%t(}s*cL50XUu#)X z>1p=i?$;tTGLuwp%HTCi$yfa{$VC8hRul*;nq?cd1lpQ?@|~J*AR8JDBa!{JYEwtj z*0RcAWsdUu=hvE5Z-jZu^X^I>)`)ohu%EEAEm)82%}raSiw0OPj6v0w&r+GWH*uiS zeP%k_Bo_E1q!UbbGgYq|c85f%#94vy;gUXdTe z3W~9k*^z&!Uy(MQHd;2)0$x+MclATg2$J-d`*>2TZmUC%AJV-b(9!gf%XeU*r0wDE z*2-25X|VH>zgrGEp@#;3sWT<9d}4^rfAs4B0b6?i6!UQ3O+FS?rnX4Kj?h`~RzJNtDBakhcymC|qbKD;H7;q#VPzl^0we@nQ zS8oZCK@t8VD#QRZeDrp&`!?NuDIrkFT7YdsVGJQJI&2SSFpP&Zh`kRh`Zg@|GglM0 zlD)d$A?pcZCruG5!U5s_KxB)U6fXL`4H63Pf(tq>DV&5!12 z!b9t`Vbj&Hmy|L`T8Ot%dqH(f08{Nzru%gsY^%kyh;BgZTT?WIDngh!;RWRHeTw$F z6%jdOJ2oCi!!WuZG6mRKH7#W2$lTuHlqYco0UPk8l;SDFV2-K25MfK16|=n>E+Ed- zh7PD4;-(81k&y;laysevp&G}_AxAyuJV%pkk7`W!4%1bJD^f(8{auj-4$6(6r-L>) zdnzTArC7ZLB3E#Bc6dHPpMLoTX2t0;nnechEgL5?KQ9@&E`otu&FO$@NqWBADuLM3 zP?%lNvz?jYy29{c#^d-4`sufKix>H%#P_GqKZZi=z-8TV|1>x*^bG=t^#~alaYpQX zFWx3aRu33(Qc7<2Oan=zuBfcZZpFt#^gEUk17U3L_&Pbq2dfqy`e3t{FO;q2QV!LX zp$2bnIRG)`hK`{7V0Mj6bC4 zxpICbT!9Y}Z&b&EV5B^GZlVun?VjaQ%xC%350e51uyZG}eH5h`rfw$UjE;w-ynry= zgYR`(BEm^?otjL?KPJp71b*=DbJyd4l=yw=3vBDuS=s*OP8pA=YjxY}QK8sjMXsF} zYHt%DQzMTMtLn*IBl^RNdaEv~VAf0e4hls4*zXS8wFL$xurn_!K(E~Abnil-tph8O z`f*gR3ci6?2IrXI8mZ+J^^7UgxM*a?5BQY7-e8H@#zlXbVUSx0vDin4jB|zF^(N!1 z6o28VCH-jcE|FAD^9KF?dfDEHDg{sIp78$dQ=*0S&&kh!8Ml@g_O+=z*NER2ycDhZ z{JmCRAKab0Pjpoh*bl}>TngDNe`c5QURb-`5_Y2!WcN~7lCLd+tnayCAjGT4gK=|+K?iY7!g99cfi0jC zNu9xuFPYH&nf=w?M1lSCXET|*re-E>vAZ>FIJp*FLH*+5`=V&6vu1M)0Zm7>vosV& zNh%%k5#X;>Uhyob>LOd*x}7Km<_?)EziJ&*2&~0?ZGrT^-gtHQW0?ar4vk-qTX&lc zxfM~ZyLJQrZZy!7SQ_-e+>c7x*y(Gm9`s89*`s~%*@^|aPx9#r? z$-roSn$|1jub#)%Uu1D=6;F=8lFuXt3FZ%Xj8)ULm`c;6p9qacmphCZX-J@+av*F^ zgf?QONL7ul&Spx#D;MNG7E;R-Lej7Gr!{`ldC^#W`z}r=@Wp-p{$E_plXYg4L8j!m z8CF8YK?msbs?Q{oAPuL7qrSb_6Ns& zG#4ZR*T$eNd^foR#X2Zlo0!IPxYn#F`FY5206_Vpp}Jy zE`Gk4@32#UsG=K1ZNK#pRG3k<`@m#)UIqX$+BjH6zWMyMx?TCWh}h3lK6N!!qK7&^ z8}w(#rHRZh-t;%#pPzI^pgS_>NOX|vyGFMm9Fd#rEK*P{aXxy659re{uU~qm4=BSD zq_c$u8sUAi2rZxieSG#O;R@{!ud2Ve%kJdE_XNRN85r+s2Zy^IC8!2{)sm0gRps?Nj$qk^BV$LT%k!M4}pdU@j>AaUyk5|TEZVj2l{|a zc>Pj*Km-=NXQy@BH3zZU*X{=yG$2fh2t%Oypt85(SP}*E`q}rb(u4YOd^r?M^w8vp zq3*I6Im)M`oSAadkKhJ)3<|`Y*9GRGZ=82IA%t@CCA=fDtmXCTVw4Z)z-$9<`}|=B zIWC*YBTBBtj#*zyxXpA7(E}2T(8X)N$T*pmz`NFfJ3O%+ED&=@#}oJL<0ShK?MZx) zj9IWa%;(t4JLnc9!5b*j8bFOjbB5t}KcyuXZyq%Pikc9xzWMyUIEWyEE>j2`^lzTR z$4EHc83t&GoakG&Q}Dm(U;j@qTWp6@9oORcn?CntXj1<0ltgc9IZpPl?Q1+Y0gpvc zdCa~zsoAH;^-4{}&vAWxN{cYR?AHtWPSJtfMg$20$+M0nUizXsVV)Q7D_!8GNOaQ% zz9bf7vzxa0DH6+%=lb*JES2=*A$QvSWO1%fR+ykm3D{oLy(xhVGc6cx@wdkaNM?hK z7L1QMgoDIw*acBY{x6FgcCRjCT83cw?V<2w5q}=_&bkR1)y$7uSirjd_VxVH9rl;( zej4;4cMtR-oM?QRjXOb6TSj-efgcR@OJ)L`y#&{%Cxq;8A!dfijji0BGty7sMln8Wz%wN&cr^M)k+9*3>*O2o-yc z12+34mp4f!jl_Rf5=@$4bv?*(@=evH>0HQ&uN1M(U{9-7H4}VYA}~86B)MHr-IBaQ z+#hKh@#^$-GZ4AGH@>L_I|E+jd0#DcPUyPaWQgW}-82v$y`d{$Aq1Fpo}vryfa?Ac z*cP9mu@45{`BM^F`l!qF7}IC>k_uOc@2eeUPQ_jegu*3bTt^xs7ylydaOl7Sc)Y&Y zbUn)+pEcPZeGY*58PI~yI~6YpY~0N7#OKZvYktk_R!0pkk%lF%C-IWJ?H#bPBnJ2% z^t{%;#5G!3=3|xF=*e8ir^79QrOlr*R}#}wqAKiQ6;TXl?o5+0uk#ozC`_)|C{n|d zsn8{iq5R>Lgny;SN?$l7pPwVIGp0rZ9KRZ~y5(KP+H8p}+@HxI04U{?#rKq*LMz*p zHo6UaiTZJ(AKlBLIzK07D@(TjuPju$>KlWpEYFX-7wR1I!PL(eB61SSh@Z%PrtIIa z9=+{{C_{R)B})@2#ls+L46oYWpN4jRhB`iz;m&pphAW60>kxN;SWFy|g4t2MzpHK7 z;*b;fHC!Am6AyFur8@tCkxGpc#Ld%zUoorX)YX|n-nh^3?iz}jyhWnPKcbX_MWd&H^8Bdzea>tNoIjylA2PM}`^b)ZH%;yfAVNwLm z#l*B&_nk^dHfCDa=g^(b{3OKkK%J$&Kq#e(;}Ty}cTv9}*RhmO7%qMVbrVNqAMWqbl1LU1P; z@@-DwSMI%a`$m%Gw2R_GAO`j|MYW+%l`B#t_KV5$&UDo@2&J^bN8YWEJlah9Mm%
+
+
+ + + + + + + + + + +
+ + +
+
+ + + \ No newline at end of file diff --git a/docs/app/pages/[...slug].vue b/docs/app/pages/[...slug].vue index bf4e7efa2..d4937684f 100644 --- a/docs/app/pages/[...slug].vue +++ b/docs/app/pages/[...slug].vue @@ -77,6 +77,10 @@ if (!page.value) { throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true }) } +if (page.value?.redirect) { + navigateTo(page.value?.redirect) +} + const { data: surround } = await useAsyncData(`${route.path}-surround`, () => { return queryCollectionItemSurroundings('docs', route.path, { fields: ['description'] diff --git a/docs/content.config.ts b/docs/content.config.ts index 84bf3ef1f..e81cfdf98 100644 --- a/docs/content.config.ts +++ b/docs/content.config.ts @@ -13,6 +13,7 @@ export default defineContentConfig({ exclude: ['index.md'] }, schema: z.object({ + redirect: z.string().optional(), links: z.array(z.object({ label: z.string(), icon: z.string(), diff --git a/docs/content/docs/index.md b/docs/content/docs/index.md new file mode 100644 index 000000000..0c3517392 --- /dev/null +++ b/docs/content/docs/index.md @@ -0,0 +1,3 @@ +--- +redirect: /docs/getting-started +--- \ No newline at end of file diff --git a/docs/nuxt.config.ts b/docs/nuxt.config.ts index d24c20172..55cf77941 100644 --- a/docs/nuxt.config.ts +++ b/docs/nuxt.config.ts @@ -7,6 +7,7 @@ export default defineNuxtConfig({ '@nuxt/content', '@nuxtjs/plausible', '@nuxtjs/sitemap', + '@vueuse/nuxt', 'nuxt-og-image', 'nuxt-llms', 'nuxt-schema-org' diff --git a/docs/package.json b/docs/package.json index c9f93d2b2..fbfe41629 100644 --- a/docs/package.json +++ b/docs/package.json @@ -20,6 +20,8 @@ "@nuxt/ui": "^4.0.1", "@nuxtjs/plausible": "^2.0.1", "@nuxtjs/sitemap": "^7.4.7", + "@vueuse/core": "^14.0.0", + "@vueuse/nuxt": "^14.0.0", "better-sqlite3": "^12.4.1", "nuxt": "^4.1.3", "nuxt-llms": "0.1.3", diff --git a/docs/public/images/logos/server-side-up-logo-horizontal.svg b/docs/public/images/logos/server-side-up-logo-horizontal.svg new file mode 100644 index 000000000..93198355b --- /dev/null +++ b/docs/public/images/logos/server-side-up-logo-horizontal.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/docs/yarn.lock b/docs/yarn.lock index a735c398c..add35eede 100644 --- a/docs/yarn.lock +++ b/docs/yarn.lock @@ -335,17 +335,17 @@ mime "^3.0.0" "@emnapi/core@^1.4.3", "@emnapi/core@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.5.0.tgz#85cd84537ec989cebb2343606a1ee663ce4edaf0" - integrity sha512-sbP8GzB1WDzacS8fgNPpHlp6C9VZe+SJP3F90W9rLemaQj2PzIuTEl1qDOYQf58YIpyjViI24y9aPWCjEzY2cg== + version "1.6.0" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.6.0.tgz#517f65d1c8270d5d5aa1aad660d5acb897430dca" + integrity sha512-zq/ay+9fNIJJtJiZxdTnXS20PllcYMX3OE23ESc4HK/bdYu3cOWYVhsOhVnXALfU/uqJIxn5NBPd9z4v+SfoSg== dependencies: "@emnapi/wasi-threads" "1.1.0" tslib "^2.4.0" "@emnapi/runtime@^1.4.3", "@emnapi/runtime@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.5.0.tgz#9aebfcb9b17195dce3ab53c86787a6b7d058db73" - integrity sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ== + version "1.6.0" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.6.0.tgz#8fe297e0090f6e89a57a1f31f1c440bdbc3c01d8" + integrity sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA== dependencies: tslib "^2.4.0" @@ -505,9 +505,9 @@ eslint-visitor-keys "^3.4.3" "@eslint-community/regexpp@^4.10.0", "@eslint-community/regexpp@^4.11.0", "@eslint-community/regexpp@^4.12.1", "@eslint-community/regexpp@^4.8.0": - version "4.12.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" - integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== + version "4.12.2" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.2.tgz#bccdf615bcf7b6e8db830ec0b8d21c9a25de597b" + integrity sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew== "@eslint/compat@^1.2.5": version "1.4.0" @@ -516,19 +516,19 @@ dependencies: "@eslint/core" "^0.16.0" -"@eslint/config-array@^0.21.0": - version "0.21.0" - resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.0.tgz#abdbcbd16b124c638081766392a4d6b509f72636" - integrity sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ== +"@eslint/config-array@^0.21.1": + version "0.21.1" + resolved "https://registry.yarnpkg.com/@eslint/config-array/-/config-array-0.21.1.tgz#7d1b0060fea407f8301e932492ba8c18aff29713" + integrity sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA== dependencies: - "@eslint/object-schema" "^2.1.6" + "@eslint/object-schema" "^2.1.7" debug "^4.3.1" minimatch "^3.1.2" -"@eslint/config-helpers@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.4.0.tgz#e9f94ba3b5b875e32205cb83fece18e64486e9e6" - integrity sha512-WUFvV4WoIwW8Bv0KeKCIIEgdSiFOsulyN0xrMu+7z43q/hkOLXjvb5u7UC9jDxvRzcrbEmuZBX5yJZz1741jog== +"@eslint/config-helpers@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@eslint/config-helpers/-/config-helpers-0.4.1.tgz#7d173a1a35fe256f0989a0fdd8d911ebbbf50037" + integrity sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw== dependencies: "@eslint/core" "^0.16.0" @@ -582,15 +582,15 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@9.37.0", "@eslint/js@^9.33.0": - version "9.37.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.37.0.tgz#0cfd5aa763fe5d1ee60bedf84cd14f54bcf9e21b" - integrity sha512-jaS+NJ+hximswBG6pjNX0uEJZkrT0zwpVi3BA3vX22aFGjJjmgSTSmPpZCRKmoBL5VY/M6p0xsSJx7rk7sy5gg== +"@eslint/js@9.38.0", "@eslint/js@^9.33.0": + version "9.38.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.38.0.tgz#f7aa9c7577577f53302c1d795643589d7709ebd1" + integrity sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A== -"@eslint/object-schema@^2.1.6": - version "2.1.6" - resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.6.tgz#58369ab5b5b3ca117880c0f6c0b0f32f6950f24f" - integrity sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA== +"@eslint/object-schema@^2.1.7": + version "2.1.7" + resolved "https://registry.yarnpkg.com/@eslint/object-schema/-/object-schema-2.1.7.tgz#6e2126a1347e86a4dedf8706ec67ff8e107ebbad" + integrity sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA== "@eslint/plugin-kit@^0.3.3": version "0.3.5" @@ -666,16 +666,16 @@ integrity sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ== "@iconify-json/lucide@^1.2.69": - version "1.2.69" - resolved "https://registry.yarnpkg.com/@iconify-json/lucide/-/lucide-1.2.69.tgz#c7994a5de2c2baa9166bc1c81e2d295db75df129" - integrity sha512-xOhNf74m+C+nSCObfEqYi34dXk1GMfMUcOB+gfqKY/bn0RcsPLinGfgouOvrUFEreDEFbCti7sdheTf5HESLTA== + version "1.2.70" + resolved "https://registry.yarnpkg.com/@iconify-json/lucide/-/lucide-1.2.70.tgz#4d89e1dc37f8aec808b9dcc37fd8ff3d4f1cb9ec" + integrity sha512-56s9NdBKgshywVY1e4gOcxzAbU1J649e/jLHBJU1tyNqRs7mFLVEGwj2mmzHJ5YAZB5Tsngi4f/ocTBPlG06ZA== dependencies: "@iconify/types" "*" "@iconify-json/simple-icons@^1.2.54": - version "1.2.54" - resolved "https://registry.yarnpkg.com/@iconify-json/simple-icons/-/simple-icons-1.2.54.tgz#b72bb1c36c03634bd31a8f33666b2237d40b36ad" - integrity sha512-OQQYl8yC5j3QklZOYnK31QYe5h47IhyCoxSLd53f0e0nA4dgi8VOZS30SgSAbsecQ+S0xlGJMjXIHTIqZ+ML3w== + version "1.2.55" + resolved "https://registry.yarnpkg.com/@iconify-json/simple-icons/-/simple-icons-1.2.55.tgz#eb55f409e76f62f4502504a3e182d04fd8f0c507" + integrity sha512-9vc04pmup/zcef8hDypWU8nMwMaFVkWuUzWkxyL++DVp5AA8baoJHK6RyKN1v+cvfR2agxkUb053XVggzFFkTA== dependencies: "@iconify/types" "*" @@ -686,10 +686,10 @@ dependencies: "@iconify/types" "*" -"@iconify/collections@^1.0.579": - version "1.0.606" - resolved "https://registry.yarnpkg.com/@iconify/collections/-/collections-1.0.606.tgz#f6f4c5d9a521d04337285cb324d1b122a07d789f" - integrity sha512-PQiFoOJpOpd3ulwmhKdtxCaeRVWp2d5jeHR2TUMuyyEizCqCmIWppWL/dGbDcbWPPLx7sovXzhLIrGihWNzBdQ== +"@iconify/collections@^1.0.608": + version "1.0.608" + resolved "https://registry.yarnpkg.com/@iconify/collections/-/collections-1.0.608.tgz#ed35264ae81b1834374e29bd5eb3181dde9b4896" + integrity sha512-uMbaErE6TzDb04peWVFYjc9cweBD+j1nFBHi5EEcA1u1mXJAyePF01VzH6dimurrhivvU+nRmuYfiC8GPDyG6g== dependencies: "@iconify/types" "*" @@ -698,7 +698,7 @@ resolved "https://registry.yarnpkg.com/@iconify/types/-/types-2.0.0.tgz#ab0e9ea681d6c8a1214f30cd741fe3a20cc57f57" integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg== -"@iconify/utils@^3.0.0": +"@iconify/utils@^3.0.2": version "3.0.2" resolved "https://registry.yarnpkg.com/@iconify/utils/-/utils-3.0.2.tgz#9599607f20690cd3e7a5d2d459af0eb81a89dc2b" integrity sha512-EfJS0rLfVuRuJRn4psJHtK2A9TqVnkxPpHY6lYHiB9+8eSuudsxbwMiavocG45ujOo6FJ+CIRlRnlOGinzkaGQ== @@ -850,7 +850,7 @@ "@emnapi/runtime" "^1.4.3" "@tybys/wasm-util" "^0.10.0" -"@napi-rs/wasm-runtime@^1.0.5", "@napi-rs/wasm-runtime@^1.0.6": +"@napi-rs/wasm-runtime@^1.0.6", "@napi-rs/wasm-runtime@^1.0.7": version "1.0.7" resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz#dcfea99a75f06209a235f3d941e3460a51e9b14c" integrity sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw== @@ -1133,24 +1133,24 @@ unstorage "^1.16.0" "@nuxt/icon@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@nuxt/icon/-/icon-2.0.0.tgz#b31a9a474ea41867bb56bd3d91ccc217fb58e7be" - integrity sha512-sy8+zkKMYp+H09S0cuTteL3zPTmktqzYPpPXV9ZkLNjrQsaPH08n7s/9wjr+C/K/w2R3u18E3+P1VIQi3xaq1A== + version "2.1.0" + resolved "https://registry.yarnpkg.com/@nuxt/icon/-/icon-2.1.0.tgz#067ad1fc7847189c4983f987a4637dbdab45816d" + integrity sha512-m+XQrgzeK5gQ1HkB7G7u1os6egoD07fiHKijG7NPxqT5yZUGOjKJ7X/Le10l3QWRKyCB+IiU0t+eUqSvh+SULg== dependencies: - "@iconify/collections" "^1.0.579" + "@iconify/collections" "^1.0.608" "@iconify/types" "^2.0.0" - "@iconify/utils" "^3.0.0" + "@iconify/utils" "^3.0.2" "@iconify/vue" "^5.0.0" - "@nuxt/devtools-kit" "^2.6.2" - "@nuxt/kit" "^4.0.3" + "@nuxt/devtools-kit" "^2.6.5" + "@nuxt/kit" "^4.1.3" consola "^3.4.2" - local-pkg "^1.1.1" - mlly "^1.7.4" + local-pkg "^1.1.2" + mlly "^1.8.0" ohash "^2.0.11" pathe "^2.0.3" picomatch "^4.0.3" - std-env "^3.9.0" - tinyglobby "^0.2.14" + std-env "^3.10.0" + tinyglobby "^0.2.15" "@nuxt/image@^1.11.0": version "1.11.0" @@ -1894,9 +1894,9 @@ integrity sha512-NIJgOsMjbxAXvoGq/X0gD7VPMQ8j9g0BiDaNjVNVjvl+iKXxL3Jre0v31RmBYeLEmkbj2s02v8vFTbUXi5XS2Q== "@rolldown/pluginutils@^1.0.0-beta.34": - version "1.0.0-beta.43" - resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.43.tgz#fa8249860113711ad3c8053bc79cb07c79b77f62" - integrity sha512-5Uxg7fQUCmfhax7FJke2+8B6cqgeUJUD9o2uXIKXhD+mG0mL6NObmVoi9wXEU1tY89mZKgAYA6fTbftx3q2ZPQ== + version "1.0.0-beta.44" + resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.44.tgz#ac8dcf86c50b177f7849a0a21df7e78b08eda2dc" + integrity sha512-g6eW7Zwnr2c5RADIoqziHoVs6b3W5QTQ4+qbpfjbkMJ9x+8Og211VW/oot2dj9dVwaK/UyC6Yo+02gV+wWQVNg== "@rollup/plugin-alias@^5.1.1": version "5.1.1" @@ -1969,115 +1969,115 @@ estree-walker "^2.0.2" picomatch "^4.0.2" -"@rollup/rollup-android-arm-eabi@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.4.tgz#59e7478d310f7e6a7c72453978f562483828112f" - integrity sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA== - -"@rollup/rollup-android-arm64@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.4.tgz#a825192a0b1b2f27a5c950c439e7e37a33c5d056" - integrity sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w== - -"@rollup/rollup-darwin-arm64@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.4.tgz#4ee37078bccd725ae3c5f30ef92efc8e1bf886f3" - integrity sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg== - -"@rollup/rollup-darwin-x64@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.4.tgz#43cc08bd05bf9f388f125e7210a544e62d368d90" - integrity sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw== - -"@rollup/rollup-freebsd-arm64@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.4.tgz#bc8e640e28abe52450baf3fc80d9b26d9bb6587d" - integrity sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ== - -"@rollup/rollup-freebsd-x64@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.4.tgz#e981a22e057cc8c65bb523019d344d3a66b15bbc" - integrity sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw== - -"@rollup/rollup-linux-arm-gnueabihf@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.4.tgz#4036b68904f392a20f3499d63b33e055b67eb274" - integrity sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ== - -"@rollup/rollup-linux-arm-musleabihf@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.4.tgz#d3b1b9589606e0ff916801c855b1ace9e733427a" - integrity sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q== - -"@rollup/rollup-linux-arm64-gnu@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.4.tgz#cbf0943c477e3b96340136dd3448eaf144378cf2" - integrity sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg== - -"@rollup/rollup-linux-arm64-musl@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.4.tgz#837f5a428020d5dce1c3b4cc049876075402cf78" - integrity sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g== - -"@rollup/rollup-linux-loong64-gnu@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.4.tgz#532c214ababb32ab4bc21b4054278b9a8979e516" - integrity sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ== - -"@rollup/rollup-linux-ppc64-gnu@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.4.tgz#93900163b61b49cee666d10ee38257a8b1dd161a" - integrity sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g== - -"@rollup/rollup-linux-riscv64-gnu@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.4.tgz#f0ffdcc7066ca04bc972370c74289f35c7a7dc42" - integrity sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg== - -"@rollup/rollup-linux-riscv64-musl@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.4.tgz#361695c39dbe96773509745d77a870a32a9f8e48" - integrity sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA== - -"@rollup/rollup-linux-s390x-gnu@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.4.tgz#09fc6cc2e266a2324e366486ae5d1bca48c43a6a" - integrity sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA== - -"@rollup/rollup-linux-x64-gnu@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.4.tgz#aa9d5b307c08f05d3454225bb0a2b4cc87eeb2e1" - integrity sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg== - -"@rollup/rollup-linux-x64-musl@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.4.tgz#26949e5b4645502a61daba2f7a8416bd17cb5382" - integrity sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw== - -"@rollup/rollup-openharmony-arm64@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.4.tgz#ef493c072f9dac7e0edb6c72d63366846b6ffcd9" - integrity sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA== - -"@rollup/rollup-win32-arm64-msvc@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.4.tgz#56e1aaa6a630d2202ee7ec0adddd05cf384ffd44" - integrity sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ== - -"@rollup/rollup-win32-ia32-msvc@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.4.tgz#0a44bbf933a9651c7da2b8569fa448dec0de7480" - integrity sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw== - -"@rollup/rollup-win32-x64-gnu@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.4.tgz#730e12f0b60b234a7c02d5d3179ca3ec7972033d" - integrity sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ== - -"@rollup/rollup-win32-x64-msvc@4.52.4": - version "4.52.4" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.4.tgz#5b2dd648a960b8fa00d76f2cc4eea2f03daa80f4" - integrity sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w== +"@rollup/rollup-android-arm-eabi@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.5.tgz#0f44a2f8668ed87b040b6fe659358ac9239da4db" + integrity sha512-8c1vW4ocv3UOMp9K+gToY5zL2XiiVw3k7f1ksf4yO1FlDFQ1C2u72iACFnSOceJFsWskc2WZNqeRhFRPzv+wtQ== + +"@rollup/rollup-android-arm64@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.5.tgz#25b9a01deef6518a948431564c987bcb205274f5" + integrity sha512-mQGfsIEFcu21mvqkEKKu2dYmtuSZOBMmAl5CFlPGLY94Vlcm+zWApK7F/eocsNzp8tKmbeBP8yXyAbx0XHsFNA== + +"@rollup/rollup-darwin-arm64@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.5.tgz#8a102869c88f3780c7d5e6776afd3f19084ecd7f" + integrity sha512-takF3CR71mCAGA+v794QUZ0b6ZSrgJkArC+gUiG6LB6TQty9T0Mqh3m2ImRBOxS2IeYBo4lKWIieSvnEk2OQWA== + +"@rollup/rollup-darwin-x64@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.5.tgz#8e526417cd6f54daf1d0c04cf361160216581956" + integrity sha512-W901Pla8Ya95WpxDn//VF9K9u2JbocwV/v75TE0YIHNTbhqUTv9w4VuQ9MaWlNOkkEfFwkdNhXgcLqPSmHy0fA== + +"@rollup/rollup-freebsd-arm64@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.5.tgz#0e7027054493f3409b1f219a3eac5efd128ef899" + integrity sha512-QofO7i7JycsYOWxe0GFqhLmF6l1TqBswJMvICnRUjqCx8b47MTo46W8AoeQwiokAx3zVryVnxtBMcGcnX12LvA== + +"@rollup/rollup-freebsd-x64@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.5.tgz#72b204a920139e9ec3d331bd9cfd9a0c248ccb10" + integrity sha512-jr21b/99ew8ujZubPo9skbrItHEIE50WdV86cdSoRkKtmWa+DDr6fu2c/xyRT0F/WazZpam6kk7IHBerSL7LDQ== + +"@rollup/rollup-linux-arm-gnueabihf@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.5.tgz#ab1b522ebe5b7e06c99504cc38f6cd8b808ba41c" + integrity sha512-PsNAbcyv9CcecAUagQefwX8fQn9LQ4nZkpDboBOttmyffnInRy8R8dSg6hxxl2Re5QhHBf6FYIDhIj5v982ATQ== + +"@rollup/rollup-linux-arm-musleabihf@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.5.tgz#f8cc30b638f1ee7e3d18eac24af47ea29d9beb00" + integrity sha512-Fw4tysRutyQc/wwkmcyoqFtJhh0u31K+Q6jYjeicsGJJ7bbEq8LwPWV/w0cnzOqR2m694/Af6hpFayLJZkG2VQ== + +"@rollup/rollup-linux-arm64-gnu@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.5.tgz#7af37a9e85f25db59dc8214172907b7e146c12cc" + integrity sha512-a+3wVnAYdQClOTlyapKmyI6BLPAFYs0JM8HRpgYZQO02rMR09ZcV9LbQB+NL6sljzG38869YqThrRnfPMCDtZg== + +"@rollup/rollup-linux-arm64-musl@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.5.tgz#a623eb0d3617c03b7a73716eb85c6e37b776f7e0" + integrity sha512-AvttBOMwO9Pcuuf7m9PkC1PUIKsfaAJ4AYhy944qeTJgQOqJYJ9oVl2nYgY7Rk0mkbsuOpCAYSs6wLYB2Xiw0Q== + +"@rollup/rollup-linux-loong64-gnu@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.5.tgz#76ea038b549c5c6c5f0d062942627c4066642ee2" + integrity sha512-DkDk8pmXQV2wVrF6oq5tONK6UHLz/XcEVow4JTTerdeV1uqPeHxwcg7aFsfnSm9L+OO8WJsWotKM2JJPMWrQtA== + +"@rollup/rollup-linux-ppc64-gnu@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.5.tgz#d9a4c3f0a3492bc78f6fdfe8131ac61c7359ccd5" + integrity sha512-W/b9ZN/U9+hPQVvlGwjzi+Wy4xdoH2I8EjaCkMvzpI7wJUs8sWJ03Rq96jRnHkSrcHTpQe8h5Tg3ZzUPGauvAw== + +"@rollup/rollup-linux-riscv64-gnu@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.5.tgz#87ab033eebd1a9a1dd7b60509f6333ec1f82d994" + integrity sha512-sjQLr9BW7R/ZiXnQiWPkErNfLMkkWIoCz7YMn27HldKsADEKa5WYdobaa1hmN6slu9oWQbB6/jFpJ+P2IkVrmw== + +"@rollup/rollup-linux-riscv64-musl@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.5.tgz#bda3eb67e1c993c1ba12bc9c2f694e7703958d9f" + integrity sha512-hq3jU/kGyjXWTvAh2awn8oHroCbrPm8JqM7RUpKjalIRWWXE01CQOf/tUNWNHjmbMHg/hmNCwc/Pz3k1T/j/Lg== + +"@rollup/rollup-linux-s390x-gnu@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.5.tgz#f7bc10fbe096ab44694233dc42a2291ed5453d4b" + integrity sha512-gn8kHOrku8D4NGHMK1Y7NA7INQTRdVOntt1OCYypZPRt6skGbddska44K8iocdpxHTMMNui5oH4elPH4QOLrFQ== + +"@rollup/rollup-linux-x64-gnu@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.5.tgz#a151cb1234cc9b2cf5e8cfc02aa91436b8f9e278" + integrity sha512-hXGLYpdhiNElzN770+H2nlx+jRog8TyynpTVzdlc6bndktjKWyZyiCsuDAlpd+j+W+WNqfcyAWz9HxxIGfZm1Q== + +"@rollup/rollup-linux-x64-musl@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.5.tgz#7859e196501cc3b3062d45d2776cfb4d2f3a9350" + integrity sha512-arCGIcuNKjBoKAXD+y7XomR9gY6Mw7HnFBv5Rw7wQRvwYLR7gBAgV7Mb2QTyjXfTveBNFAtPt46/36vV9STLNg== + +"@rollup/rollup-openharmony-arm64@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.5.tgz#85d0df7233734df31e547c1e647d2a5300b3bf30" + integrity sha512-QoFqB6+/9Rly/RiPjaomPLmR/13cgkIGfA40LHly9zcH1S0bN2HVFYk3a1eAyHQyjs3ZJYlXvIGtcCs5tko9Cw== + +"@rollup/rollup-win32-arm64-msvc@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.5.tgz#e62357d00458db17277b88adbf690bb855cac937" + integrity sha512-w0cDWVR6MlTstla1cIfOGyl8+qb93FlAVutcor14Gf5Md5ap5ySfQ7R9S/NjNaMLSFdUnKGEasmVnu3lCMqB7w== + +"@rollup/rollup-win32-ia32-msvc@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.5.tgz#fc7cd40f44834a703c1f1c3fe8bcc27ce476cd50" + integrity sha512-Aufdpzp7DpOTULJCuvzqcItSGDH73pF3ko/f+ckJhxQyHtp67rHw3HMNxoIdDMUITJESNE6a8uh4Lo4SLouOUg== + +"@rollup/rollup-win32-x64-gnu@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.5.tgz#1a22acfc93c64a64a48c42672e857ee51774d0d3" + integrity sha512-UGBUGPFp1vkj6p8wCRraqNhqwX/4kNQPS57BCFc8wYh0g94iVIW33wJtQAx3G7vrjjNtRaxiMUylM0ktp/TRSQ== + +"@rollup/rollup-win32-x64-msvc@4.52.5": + version "4.52.5" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.5.tgz#1657f56326bbe0ac80eedc9f9c18fc1ddd24e107" + integrity sha512-TAcgQh2sSkykPRWLrdyy2AiceMckNf5loITqXxFI5VuQjS5tSuw3WlwdN8qv8vzjLAUTvYaH/mVjSFpbkFbpTg== "@sec-ant/readable-stream@^0.4.1": version "0.4.1" @@ -2190,12 +2190,12 @@ integrity sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA== "@stylistic/eslint-plugin@^5.2.3": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@stylistic/eslint-plugin/-/eslint-plugin-5.4.0.tgz#4cd51beb5602a8978a9a956c3568180efffcabe5" - integrity sha512-UG8hdElzuBDzIbjG1QDwnYH0MQ73YLXDFHgZzB4Zh/YJfnw8XNsloVtytqzx0I2Qky9THSdpTmi8Vjn/pf/Lew== + version "5.5.0" + resolved "https://registry.yarnpkg.com/@stylistic/eslint-plugin/-/eslint-plugin-5.5.0.tgz#44c2e5454ff827f962b1908f0b5939130a6b18b3" + integrity sha512-IeZF+8H0ns6prg4VrkhgL+yrvDXWDH2cKchrbh80ejG9dQgZWp10epHMbgRuQvgchLII/lfh6Xn3lu6+6L86Hw== dependencies: "@eslint-community/eslint-utils" "^4.9.0" - "@typescript-eslint/types" "^8.44.0" + "@typescript-eslint/types" "^8.46.1" eslint-visitor-keys "^4.2.1" espree "^10.4.0" estraverse "^5.3.0" @@ -2208,126 +2208,123 @@ dependencies: tslib "^2.8.0" -"@tailwindcss/node@4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/node/-/node-4.1.14.tgz#cf3864490c746db6b06b46aa235df9021a289bad" - integrity sha512-hpz+8vFk3Ic2xssIA3e01R6jkmsAhvkQdXlEbRTk6S10xDAtiQiM3FyvZVGsucefq764euO/b8WUW9ysLdThHw== +"@tailwindcss/node@4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/node/-/node-4.1.15.tgz#7008f30cd35d67352690ead8f59389455f8003c5" + integrity sha512-HF4+7QxATZWY3Jr8OlZrBSXmwT3Watj0OogeDvdUY/ByXJHQ+LBtqA2brDb3sBxYslIFx6UP94BJ4X6a4L9Bmw== dependencies: "@jridgewell/remapping" "^2.3.4" enhanced-resolve "^5.18.3" jiti "^2.6.0" - lightningcss "1.30.1" + lightningcss "1.30.2" magic-string "^0.30.19" source-map-js "^1.2.1" - tailwindcss "4.1.14" - -"@tailwindcss/oxide-android-arm64@4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.14.tgz#8903678d75715d913b8f7c5f6fa0517af83b5111" - integrity sha512-a94ifZrGwMvbdeAxWoSuGcIl6/DOP5cdxagid7xJv6bwFp3oebp7y2ImYsnZBMTwjn5Ev5xESvS3FFYUGgPODQ== - -"@tailwindcss/oxide-darwin-arm64@4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.14.tgz#72d56afadce829047a83d8512f29ee16cf6fbea5" - integrity sha512-HkFP/CqfSh09xCnrPJA7jud7hij5ahKyWomrC3oiO2U9i0UjP17o9pJbxUN0IJ471GTQQmzwhp0DEcpbp4MZTA== - -"@tailwindcss/oxide-darwin-x64@4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.14.tgz#ac1af82da01299143129fdf615f6fcc046b4094e" - integrity sha512-eVNaWmCgdLf5iv6Qd3s7JI5SEFBFRtfm6W0mphJYXgvnDEAZ5sZzqmI06bK6xo0IErDHdTA5/t7d4eTfWbWOFw== - -"@tailwindcss/oxide-freebsd-x64@4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.14.tgz#a955cedf9b020147d222f92490e9d331db9b5c36" - integrity sha512-QWLoRXNikEuqtNb0dhQN6wsSVVjX6dmUFzuuiL09ZeXju25dsei2uIPl71y2Ic6QbNBsB4scwBoFnlBfabHkEw== - -"@tailwindcss/oxide-linux-arm-gnueabihf@4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.14.tgz#5474bee4d377144107f3f0198a3c0225a46c02e6" - integrity sha512-VB4gjQni9+F0VCASU+L8zSIyjrLLsy03sjcR3bM0V2g4SNamo0FakZFKyUQ96ZVwGK4CaJsc9zd/obQy74o0Fw== - -"@tailwindcss/oxide-linux-arm64-gnu@4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.14.tgz#b06ca140083b353735414e32f7a8786f55ce2dd6" - integrity sha512-qaEy0dIZ6d9vyLnmeg24yzA8XuEAD9WjpM5nIM1sUgQ/Zv7cVkharPDQcmm/t/TvXoKo/0knI3me3AGfdx6w1w== - -"@tailwindcss/oxide-linux-arm64-musl@4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.14.tgz#85f4cabea2a07609274d1f747bd098c5da2a7cd2" - integrity sha512-ISZjT44s59O8xKsPEIesiIydMG/sCXoMBCqsphDm/WcbnuWLxxb+GcvSIIA5NjUw6F8Tex7s5/LM2yDy8RqYBQ== - -"@tailwindcss/oxide-linux-x64-gnu@4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.14.tgz#0d7fbf91763a2f6886044a050298489107d120bd" - integrity sha512-02c6JhLPJj10L2caH4U0zF8Hji4dOeahmuMl23stk0MU1wfd1OraE7rOloidSF8W5JTHkFdVo/O7uRUJJnUAJg== - -"@tailwindcss/oxide-linux-x64-musl@4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.14.tgz#93578713064ba4c16df517df01b3c546ecc9878d" - integrity sha512-TNGeLiN1XS66kQhxHG/7wMeQDOoL0S33x9BgmydbrWAb9Qw0KYdd8o1ifx4HOGDWhVmJ+Ul+JQ7lyknQFilO3Q== - -"@tailwindcss/oxide-wasm32-wasi@4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.14.tgz#9e55999129a952a3dcc2196cc9cc55248cc1b1fe" - integrity sha512-uZYAsaW/jS/IYkd6EWPJKW/NlPNSkWkBlaeVBi/WsFQNP05/bzkebUL8FH1pdsqx4f2fH/bWFcUABOM9nfiJkQ== + tailwindcss "4.1.15" + +"@tailwindcss/oxide-android-arm64@4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.15.tgz#ea5a49655203214bacf3af5b21373457c34d1462" + integrity sha512-TkUkUgAw8At4cBjCeVCRMc/guVLKOU1D+sBPrHt5uVcGhlbVKxrCaCW9OKUIBv1oWkjh4GbunD/u/Mf0ql6kEA== + +"@tailwindcss/oxide-darwin-arm64@4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.15.tgz#6eed73058cef8cb3f0a3f984700d93049dd1549f" + integrity sha512-xt5XEJpn2piMSfvd1UFN6jrWXyaKCwikP4Pidcf+yfHTSzSpYhG3dcMktjNkQO3JiLCp+0bG0HoWGvz97K162w== + +"@tailwindcss/oxide-darwin-x64@4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.15.tgz#1eba5369a071d3b06488be8c12dbb94029e69389" + integrity sha512-TnWaxP6Bx2CojZEXAV2M01Yl13nYPpp0EtGpUrY+LMciKfIXiLL2r/SiSRpagE5Fp2gX+rflp/Os1VJDAyqymg== + +"@tailwindcss/oxide-freebsd-x64@4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.15.tgz#d7395ae1a6d0adcaf313ef6f94e771dd64e11b77" + integrity sha512-quISQDWqiB6Cqhjc3iWptXVZHNVENsWoI77L1qgGEHNIdLDLFnw3/AfY7DidAiiCIkGX/MjIdB3bbBZR/G2aJg== + +"@tailwindcss/oxide-linux-arm-gnueabihf@4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.15.tgz#7b296f228fb9bda92ec70d6607927a3eda8b9550" + integrity sha512-ObG76+vPlab65xzVUQbExmDU9FIeYLQ5k2LrQdR2Ud6hboR+ZobXpDoKEYXf/uOezOfIYmy2Ta3w0ejkTg9yxg== + +"@tailwindcss/oxide-linux-arm64-gnu@4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.15.tgz#959afeee72c55a39e80f32a100e9a3ddbf73295c" + integrity sha512-4WbBacRmk43pkb8/xts3wnOZMDKsPFyEH/oisCm2q3aLZND25ufvJKcDUpAu0cS+CBOL05dYa8D4U5OWECuH/Q== + +"@tailwindcss/oxide-linux-arm64-musl@4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.15.tgz#8a58e33595233628bb96e02fbb03b544680a36a2" + integrity sha512-AbvmEiteEj1nf42nE8skdHv73NoR+EwXVSgPY6l39X12Ex8pzOwwfi3Kc8GAmjsnsaDEbk+aj9NyL3UeyHcTLg== + +"@tailwindcss/oxide-linux-x64-gnu@4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.15.tgz#546666cde500f80d3ff2e819de9276a9580685b1" + integrity sha512-+rzMVlvVgrXtFiS+ES78yWgKqpThgV19ISKD58Ck+YO5pO5KjyxLt7AWKsWMbY0R9yBDC82w6QVGz837AKQcHg== + +"@tailwindcss/oxide-linux-x64-musl@4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.15.tgz#07e9ae8ca70bb9a4990ceee612c88781bd45a6fc" + integrity sha512-fPdEy7a8eQN9qOIK3Em9D3TO1z41JScJn8yxl/76mp4sAXFDfV4YXxsiptJcOwy6bGR+70ZSwFIZhTXzQeqwQg== + +"@tailwindcss/oxide-wasm32-wasi@4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.15.tgz#82a6c5159bc562e4619cf938450a9c017837b194" + integrity sha512-sJ4yd6iXXdlgIMfIBXuVGp/NvmviEoMVWMOAGxtxhzLPp9LOj5k0pMEMZdjeMCl4C6Up+RM8T3Zgk+BMQ0bGcQ== dependencies: "@emnapi/core" "^1.5.0" "@emnapi/runtime" "^1.5.0" "@emnapi/wasi-threads" "^1.1.0" - "@napi-rs/wasm-runtime" "^1.0.5" + "@napi-rs/wasm-runtime" "^1.0.7" "@tybys/wasm-util" "^0.10.1" tslib "^2.4.0" -"@tailwindcss/oxide-win32-arm64-msvc@4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.14.tgz#097c00bfc60cd84943a9cb5e853b25fa25525c77" - integrity sha512-Az0RnnkcvRqsuoLH2Z4n3JfAef0wElgzHD5Aky/e+0tBUxUhIeIqFBTMNQvmMRSP15fWwmvjBxZ3Q8RhsDnxAA== +"@tailwindcss/oxide-win32-arm64-msvc@4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.15.tgz#7e7f3f187c7a60209466b7064e78d5b70ad1945d" + integrity sha512-sJGE5faXnNQ1iXeqmRin7Ds/ru2fgCiaQZQQz3ZGIDtvbkeV85rAZ0QJFMDg0FrqsffZG96H1U9AQlNBRLsHVg== -"@tailwindcss/oxide-win32-x64-msvc@4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.14.tgz#eaa49fa930ce16b23478d3b58c079a40ac0b6622" - integrity sha512-ttblVGHgf68kEE4om1n/n44I0yGPkCPbLsqzjvybhpwa6mKKtgFfAzy6btc3HRmuW7nHe0OOrSeNP9sQmmH9XA== +"@tailwindcss/oxide-win32-x64-msvc@4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.15.tgz#fd4e41ed0014a8da456576be1381c12c345d1a0a" + integrity sha512-NLeHE7jUV6HcFKS504bpOohyi01zPXi2PXmjFfkzTph8xRxDdxkRsXm/xDO5uV5K3brrE1cCwbUYmFUSHR3u1w== -"@tailwindcss/oxide@4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/oxide/-/oxide-4.1.14.tgz#acfc7869142665693b3b08e4e51d0f419ca13662" - integrity sha512-23yx+VUbBwCg2x5XWdB8+1lkPajzLmALEfMb51zZUBYaYVPDQvBSD/WYDqiVyBIo2BZFa3yw1Rpy3G2Jp+K0dw== - dependencies: - detect-libc "^2.0.4" - tar "^7.5.1" +"@tailwindcss/oxide@4.1.15": + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide/-/oxide-4.1.15.tgz#80a261e646f67bbaaa84ce2cf6c97e984fc0eae1" + integrity sha512-krhX+UOOgnsUuks2SR7hFafXmLQrKxB4YyRTERuCE59JlYL+FawgaAlSkOYmDRJdf1Q+IFNDMl9iRnBW7QBDfQ== optionalDependencies: - "@tailwindcss/oxide-android-arm64" "4.1.14" - "@tailwindcss/oxide-darwin-arm64" "4.1.14" - "@tailwindcss/oxide-darwin-x64" "4.1.14" - "@tailwindcss/oxide-freebsd-x64" "4.1.14" - "@tailwindcss/oxide-linux-arm-gnueabihf" "4.1.14" - "@tailwindcss/oxide-linux-arm64-gnu" "4.1.14" - "@tailwindcss/oxide-linux-arm64-musl" "4.1.14" - "@tailwindcss/oxide-linux-x64-gnu" "4.1.14" - "@tailwindcss/oxide-linux-x64-musl" "4.1.14" - "@tailwindcss/oxide-wasm32-wasi" "4.1.14" - "@tailwindcss/oxide-win32-arm64-msvc" "4.1.14" - "@tailwindcss/oxide-win32-x64-msvc" "4.1.14" + "@tailwindcss/oxide-android-arm64" "4.1.15" + "@tailwindcss/oxide-darwin-arm64" "4.1.15" + "@tailwindcss/oxide-darwin-x64" "4.1.15" + "@tailwindcss/oxide-freebsd-x64" "4.1.15" + "@tailwindcss/oxide-linux-arm-gnueabihf" "4.1.15" + "@tailwindcss/oxide-linux-arm64-gnu" "4.1.15" + "@tailwindcss/oxide-linux-arm64-musl" "4.1.15" + "@tailwindcss/oxide-linux-x64-gnu" "4.1.15" + "@tailwindcss/oxide-linux-x64-musl" "4.1.15" + "@tailwindcss/oxide-wasm32-wasi" "4.1.15" + "@tailwindcss/oxide-win32-arm64-msvc" "4.1.15" + "@tailwindcss/oxide-win32-x64-msvc" "4.1.15" "@tailwindcss/postcss@^4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/postcss/-/postcss-4.1.14.tgz#29fd4e082b29460e4062a7bc4bf70b38a97f8fc5" - integrity sha512-BdMjIxy7HUNThK87C7BC8I1rE8BVUsfNQSI5siQ4JK3iIa3w0XyVvVL9SXLWO//CtYTcp1v7zci0fYwJOjB+Zg== + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/postcss/-/postcss-4.1.15.tgz#c39c6de085cfc26c2dc82868734bd63ed5875ec9" + integrity sha512-IZh8IT76KujRz6d15wZw4eoeViT4TqmzVWNNfpuNCTKiaZUwgr5vtPqO4HjuYDyx3MgGR5qgPt1HMzTeLJyA3g== dependencies: "@alloc/quick-lru" "^5.2.0" - "@tailwindcss/node" "4.1.14" - "@tailwindcss/oxide" "4.1.14" + "@tailwindcss/node" "4.1.15" + "@tailwindcss/oxide" "4.1.15" postcss "^8.4.41" - tailwindcss "4.1.14" + tailwindcss "4.1.15" "@tailwindcss/vite@^4.1.14": - version "4.1.14" - resolved "https://registry.yarnpkg.com/@tailwindcss/vite/-/vite-4.1.14.tgz#94d0fb87b11030138a45cef8ae9c3a7b080d4007" - integrity sha512-BoFUoU0XqgCUS1UXWhmDJroKKhNXeDzD7/XwabjkDIAbMnc4ULn5e2FuEuBbhZ6ENZoSYzKlzvZ44Yr6EUDUSA== + version "4.1.15" + resolved "https://registry.yarnpkg.com/@tailwindcss/vite/-/vite-4.1.15.tgz#da8d5432a89f8ff091a3c34681c33bf155cf58f5" + integrity sha512-B6s60MZRTUil+xKoZoGe6i0Iar5VuW+pmcGlda2FX+guDuQ1G1sjiIy1W0frneVpeL/ZjZ4KEgWZHNrIm++2qA== dependencies: - "@tailwindcss/node" "4.1.14" - "@tailwindcss/oxide" "4.1.14" - tailwindcss "4.1.14" + "@tailwindcss/node" "4.1.15" + "@tailwindcss/oxide" "4.1.15" + tailwindcss "4.1.15" "@tanstack/table-core@8.21.3": version "8.21.3" @@ -2407,11 +2404,11 @@ integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== "@types/node@*": - version "24.8.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-24.8.1.tgz#74c8ae00b045a0a351f2837ec00f25dfed0053be" - integrity sha512-alv65KGRadQVfVcG69MuB4IzdYVpRwMG/mq8KWOaoOdyY617P5ivaDiMCGOFDWD2sAn5Q0mR3mRtUOgm99hL9Q== + version "24.9.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.9.1.tgz#b7360b3c789089e57e192695a855aa4f6981a53c" + integrity sha512-QoiaXANRkSXK6p0Duvt56W208du4P9Uye9hWLWgGMDTEoKPhuenzNcC4vGUmrNkiOKTlIrBoyNQYNpSwfEZXSg== dependencies: - undici-types "~7.14.0" + undici-types "~7.16.0" "@types/parse-path@^7.0.0": version "7.1.0" @@ -2446,78 +2443,78 @@ integrity sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA== "@typescript-eslint/eslint-plugin@^8.39.1": - version "8.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.1.tgz#20876354024140aabc8b400bc95735fdcade17d5" - integrity sha512-rUsLh8PXmBjdiPY+Emjz9NX2yHvhS11v0SR6xNJkm5GM1MO9ea/1GoDKlHHZGrOJclL/cZ2i/vRUYVtjRhrHVQ== + version "8.46.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.2.tgz#dc4ab93ee3d7e6c8e38820a0d6c7c93c7183e2dc" + integrity sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "8.46.1" - "@typescript-eslint/type-utils" "8.46.1" - "@typescript-eslint/utils" "8.46.1" - "@typescript-eslint/visitor-keys" "8.46.1" + "@typescript-eslint/scope-manager" "8.46.2" + "@typescript-eslint/type-utils" "8.46.2" + "@typescript-eslint/utils" "8.46.2" + "@typescript-eslint/visitor-keys" "8.46.2" graphemer "^1.4.0" ignore "^7.0.0" natural-compare "^1.4.0" ts-api-utils "^2.1.0" "@typescript-eslint/parser@^8.39.1": - version "8.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.46.1.tgz#81751f46800fc6b01ce1a72760cd17f06e7f395b" - integrity sha512-6JSSaBZmsKvEkbRUkf7Zj7dru/8ZCrJxAqArcLaVMee5907JdtEbKGsZ7zNiIm/UAkpGUkaSMZEXShnN2D1HZA== - dependencies: - "@typescript-eslint/scope-manager" "8.46.1" - "@typescript-eslint/types" "8.46.1" - "@typescript-eslint/typescript-estree" "8.46.1" - "@typescript-eslint/visitor-keys" "8.46.1" + version "8.46.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.46.2.tgz#dd938d45d581ac8ffa9d8a418a50282b306f7ebf" + integrity sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g== + dependencies: + "@typescript-eslint/scope-manager" "8.46.2" + "@typescript-eslint/types" "8.46.2" + "@typescript-eslint/typescript-estree" "8.46.2" + "@typescript-eslint/visitor-keys" "8.46.2" debug "^4.3.4" -"@typescript-eslint/project-service@8.46.1": - version "8.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.46.1.tgz#07be0e6f27fa90a17d8e5f6996ee02329c9a8c2e" - integrity sha512-FOIaFVMHzRskXr5J4Jp8lFVV0gz5ngv3RHmn+E4HYxSJ3DgDzU7fVI1/M7Ijh1zf6S7HIoaIOtln1H5y8V+9Zg== +"@typescript-eslint/project-service@8.46.2": + version "8.46.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/project-service/-/project-service-8.46.2.tgz#ab2f02a0de4da6a7eeb885af5e059be57819d608" + integrity sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg== dependencies: - "@typescript-eslint/tsconfig-utils" "^8.46.1" - "@typescript-eslint/types" "^8.46.1" + "@typescript-eslint/tsconfig-utils" "^8.46.2" + "@typescript-eslint/types" "^8.46.2" debug "^4.3.4" -"@typescript-eslint/scope-manager@8.46.1": - version "8.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.46.1.tgz#590dd2e65e95af646bdaf50adeae9af39e25e8c1" - integrity sha512-weL9Gg3/5F0pVQKiF8eOXFZp8emqWzZsOJuWRUNtHT+UNV2xSJegmpCNQHy37aEQIbToTq7RHKhWvOsmbM680A== +"@typescript-eslint/scope-manager@8.46.2": + version "8.46.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.46.2.tgz#7d37df2493c404450589acb3b5d0c69cc0670a88" + integrity sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA== dependencies: - "@typescript-eslint/types" "8.46.1" - "@typescript-eslint/visitor-keys" "8.46.1" + "@typescript-eslint/types" "8.46.2" + "@typescript-eslint/visitor-keys" "8.46.2" -"@typescript-eslint/tsconfig-utils@8.46.1", "@typescript-eslint/tsconfig-utils@^8.46.1": - version "8.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.1.tgz#24405888560175c6c209c39df11ac06a2efef9d7" - integrity sha512-X88+J/CwFvlJB+mK09VFqx5FE4H5cXD+H/Bdza2aEWkSb8hnWIQorNcscRl4IEo1Cz9VI/+/r/jnGWkbWPx54g== +"@typescript-eslint/tsconfig-utils@8.46.2", "@typescript-eslint/tsconfig-utils@^8.46.2": + version "8.46.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.2.tgz#d110451cb93bbd189865206ea37ef677c196828c" + integrity sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag== -"@typescript-eslint/type-utils@8.46.1": - version "8.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.46.1.tgz#14d4307dd6045f6b48a888cde1513d6ec305537f" - integrity sha512-+BlmiHIiqufBxkVnOtFwjah/vrkF4MtKKvpXrKSPLCkCtAp8H01/VV43sfqA98Od7nJpDcFnkwgyfQbOG0AMvw== +"@typescript-eslint/type-utils@8.46.2": + version "8.46.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.46.2.tgz#802d027864e6fb752e65425ed09f3e089fb4d384" + integrity sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA== dependencies: - "@typescript-eslint/types" "8.46.1" - "@typescript-eslint/typescript-estree" "8.46.1" - "@typescript-eslint/utils" "8.46.1" + "@typescript-eslint/types" "8.46.2" + "@typescript-eslint/typescript-estree" "8.46.2" + "@typescript-eslint/utils" "8.46.2" debug "^4.3.4" ts-api-utils "^2.1.0" -"@typescript-eslint/types@8.46.1", "@typescript-eslint/types@^8.34.0", "@typescript-eslint/types@^8.35.0", "@typescript-eslint/types@^8.39.1", "@typescript-eslint/types@^8.42.0", "@typescript-eslint/types@^8.44.0", "@typescript-eslint/types@^8.46.1": - version "8.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.46.1.tgz#4c5479538ec10b5508b8e982e172911c987446d8" - integrity sha512-C+soprGBHwWBdkDpbaRC4paGBrkIXxVlNohadL5o0kfhsXqOC6GYH2S/Obmig+I0HTDl8wMaRySwrfrXVP8/pQ== +"@typescript-eslint/types@8.46.2", "@typescript-eslint/types@^8.34.0", "@typescript-eslint/types@^8.35.0", "@typescript-eslint/types@^8.39.1", "@typescript-eslint/types@^8.42.0", "@typescript-eslint/types@^8.46.1", "@typescript-eslint/types@^8.46.2": + version "8.46.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.46.2.tgz#2bad7348511b31e6e42579820e62b73145635763" + integrity sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ== -"@typescript-eslint/typescript-estree@8.46.1": - version "8.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.1.tgz#1c146573b942ebe609c156c217ceafdc7a88e6ed" - integrity sha512-uIifjT4s8cQKFQ8ZBXXyoUODtRoAd7F7+G8MKmtzj17+1UbdzFl52AzRyZRyKqPHhgzvXunnSckVu36flGy8cg== +"@typescript-eslint/typescript-estree@8.46.2": + version "8.46.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.2.tgz#ab547a27e4222bb6a3281cb7e98705272e2c7d08" + integrity sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ== dependencies: - "@typescript-eslint/project-service" "8.46.1" - "@typescript-eslint/tsconfig-utils" "8.46.1" - "@typescript-eslint/types" "8.46.1" - "@typescript-eslint/visitor-keys" "8.46.1" + "@typescript-eslint/project-service" "8.46.2" + "@typescript-eslint/tsconfig-utils" "8.46.2" + "@typescript-eslint/types" "8.46.2" + "@typescript-eslint/visitor-keys" "8.46.2" debug "^4.3.4" fast-glob "^3.3.2" is-glob "^4.0.3" @@ -2525,22 +2522,22 @@ semver "^7.6.0" ts-api-utils "^2.1.0" -"@typescript-eslint/utils@8.46.1", "@typescript-eslint/utils@^8.39.1": - version "8.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.46.1.tgz#c572184d9227d66b10a954b90249a20c48b22452" - integrity sha512-vkYUy6LdZS7q1v/Gxb2Zs7zziuXN0wxqsetJdeZdRe/f5dwJFglmuvZBfTUivCtjH725C1jWCDfpadadD95EDQ== +"@typescript-eslint/utils@8.46.2", "@typescript-eslint/utils@^8.39.1": + version "8.46.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.46.2.tgz#b313d33d67f9918583af205bd7bcebf20f231732" + integrity sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg== dependencies: "@eslint-community/eslint-utils" "^4.7.0" - "@typescript-eslint/scope-manager" "8.46.1" - "@typescript-eslint/types" "8.46.1" - "@typescript-eslint/typescript-estree" "8.46.1" + "@typescript-eslint/scope-manager" "8.46.2" + "@typescript-eslint/types" "8.46.2" + "@typescript-eslint/typescript-estree" "8.46.2" -"@typescript-eslint/visitor-keys@8.46.1": - version "8.46.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.1.tgz#da35f1d58ec407419d68847cfd358b32746ac315" - integrity sha512-ptkmIf2iDkNUjdeu2bQqhFPV1m6qTnFFjg7PPDjxKWaMaP0Z6I9l30Jr3g5QqbZGdw8YdYvLp+XnqnWWZOg/NA== +"@typescript-eslint/visitor-keys@8.46.2": + version "8.46.2" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.2.tgz#803fa298948c39acf810af21bdce6f8babfa9738" + integrity sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w== dependencies: - "@typescript-eslint/types" "8.46.1" + "@typescript-eslint/types" "8.46.2" eslint-visitor-keys "^4.2.1" "@ungap/structured-clone@^1.0.0": @@ -2944,6 +2941,15 @@ "@vueuse/metadata" "13.9.0" "@vueuse/shared" "13.9.0" +"@vueuse/core@14.0.0", "@vueuse/core@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-14.0.0.tgz#a3d9520935a191b167cb91e08f698545e46bf0a6" + integrity sha512-d6tKRWkZE8IQElX2aHBxXOMD478fHIYV+Dzm2y9Ag122ICBpNKtGICiXKOhWU3L1kKdttDD9dCMS4bGP3jhCTQ== + dependencies: + "@types/web-bluetooth" "^0.0.21" + "@vueuse/metadata" "14.0.0" + "@vueuse/shared" "14.0.0" + "@vueuse/core@^10.8.0": version "10.11.1" resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-10.11.1.tgz#15d2c0b6448d2212235b23a7ba29c27173e0c2c6" @@ -2987,6 +2993,21 @@ resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-13.9.0.tgz#57c738d99661c33347080c0bc4cd11160e0d0881" integrity sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg== +"@vueuse/metadata@14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-14.0.0.tgz#139231dc8503f172a7a45ce1ceaa7a415befbf3c" + integrity sha512-6yoGqbJcMldVCevkFiHDBTB1V5Hq+G/haPlGIuaFZHpXC0HADB0EN1ryQAAceiW+ryS3niUwvdFbGiqHqBrfVA== + +"@vueuse/nuxt@^14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@vueuse/nuxt/-/nuxt-14.0.0.tgz#55f817da27444b48e8b0c707eea11ad3486839e5" + integrity sha512-6DNZ1DLw3UI52TtVX4jmL8oD/L3jFgtWeQmsSXP+0myMhpmlBpWB2xe1x5UdwdHly9j1Fq9DI8wz+LsW6wvdeg== + dependencies: + "@nuxt/kit" "^4.1.3" + "@vueuse/core" "14.0.0" + "@vueuse/metadata" "14.0.0" + local-pkg "^1.1.2" + "@vueuse/shared@10.11.1": version "10.11.1" resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-10.11.1.tgz#62b84e3118ae6e1f3ff38f4fbe71b0c5d0f10938" @@ -3006,6 +3027,11 @@ resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-13.9.0.tgz#7168b4ed647e625b05eb4e7e80fe8aabd00e3923" integrity sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g== +"@vueuse/shared@14.0.0": + version "14.0.0" + resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-14.0.0.tgz#15a424285fd6d453d1a99d1caba8cc293992868d" + integrity sha512-mTCA0uczBgurRlwVaQHfG0Ja7UdGe4g9mwffiJmvLiTtp1G4AQyIjej6si/k8c8pUwTfVpNufck+23gXptPAkw== + "@webcontainer/env@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@webcontainer/env/-/env-1.1.1.tgz#23021b2bb24befeeef53dba8996d1886b7016515" @@ -3064,9 +3090,9 @@ ajv@^6.12.4: uri-js "^4.2.2" alien-signals@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/alien-signals/-/alien-signals-3.0.1.tgz#73362f460ca91534e0a7becd9b32a6dbf37a9b7c" - integrity sha512-ec02Wv5iOg7yG979PH9ykv5KN/KHznOxMlKy/Jr8lnBo3T94d4MUGo7FVdM8B2fM0e94twzEcWCyWzfIyeV19g== + version "3.0.3" + resolved "https://registry.yarnpkg.com/alien-signals/-/alien-signals-3.0.3.tgz#f54e89180e490a9577e4f6f7203720e4335a8715" + integrity sha512-2JXjom6R7ZwrISpUphLhf4htUq1aKRCennTJ6u9kFfr3sLmC9+I4CxxVi+McoFnIg+p1HnVrfLT/iCt4Dlz//Q== ansi-regex@^5.0.1: version "5.0.1" @@ -3200,14 +3226,14 @@ balanced-match@^1.0.0: integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== bare-events@^2.5.4, bare-events@^2.7.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.8.0.tgz#ec962fa9e2bfafd4edd444942df1ed0c7aba8e4a" - integrity sha512-AOhh6Bg5QmFIXdViHbMc2tLDsBIRxdkIaIddPslJF9Z5De3APBScuqGP2uThXnIpqFrgoxMNC6km7uXNIMLHXA== + version "2.8.1" + resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.8.1.tgz#121afaeee9e9a8eb92e71d125bc85753d39913d0" + integrity sha512-oxSAxTS1hRfnyit2CL5QpAOS5ixfBjj6ex3yTNvXyY/kE719jQ/IjuESJBK2w5v4wwQRAHGseVJXx9QBYOtFGQ== bare-fs@^4.0.1: - version "4.4.11" - resolved "https://registry.yarnpkg.com/bare-fs/-/bare-fs-4.4.11.tgz#e9fe3deefb294ed02e696e5a5dfcc14252a2c806" - integrity sha512-Bejmm9zRMvMTRoHS+2adgmXw1ANZnCNx+B5dgZpGwlP1E3x6Yuxea8RToddHUbWtVV0iUMWqsgZr8+jcgUI2SA== + version "4.5.0" + resolved "https://registry.yarnpkg.com/bare-fs/-/bare-fs-4.5.0.tgz#f3227b4bc79a65ca7e91a1c05be5919c7c7d8340" + integrity sha512-GljgCjeupKZJNetTqxKaQArLK10vpmK28or0+RwWjEl5Rk+/xG3wkpmkv+WrcBm3q1BwHKlnhXzR8O37kcvkXQ== dependencies: bare-events "^2.5.4" bare-path "^3.0.0" @@ -3235,9 +3261,9 @@ bare-stream@^2.6.4: streamx "^2.21.0" bare-url@^2.2.2: - version "2.3.0" - resolved "https://registry.yarnpkg.com/bare-url/-/bare-url-2.3.0.tgz#06bb523cfdd5bb8dd224bf4e0062ff0231eca998" - integrity sha512-c+RCqMSZbkz97Mw1LWR0gcOqwK82oyYKfLoHJ8k13ybi1+I80ffdDzUy0TdAburdrR/kI0/VuN8YgEnJqX+Nyw== + version "2.3.1" + resolved "https://registry.yarnpkg.com/bare-url/-/bare-url-2.3.1.tgz#95e33e99bdc768766ca94246fdc397e88675ec9c" + integrity sha512-v2yl0TnaZTdEnelkKtXZGnotiV6qATBlnNuUMrHl6v9Lmmrh9mw9RYyImPU7/4RahumSwQS1k2oKXcRfXcbjJw== dependencies: bare-path "^3.0.0" @@ -3251,10 +3277,10 @@ base64-js@^1.1.2, base64-js@^1.3.0, base64-js@^1.3.1: resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== -baseline-browser-mapping@^2.8.9: - version "2.8.17" - resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.8.17.tgz#85aff3f7dd6326ea25b77ce834b96bb698545dc6" - integrity sha512-j5zJcx6golJYTG6c05LUZ3Z8Gi+M62zRT/ycz4Xq4iCOdpcxwg7ngEYD4KA0eWZC7U17qh/Smq8bYbACJ0ipBA== +baseline-browser-mapping@^2.8.19: + version "2.8.19" + resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.8.19.tgz#8d99bb7f06bc6ea5c9c1b961e631a1713069bbe0" + integrity sha512-zoKGUdu6vb2jd3YOq0nnhEDQVbPcHhco3UImJrv5dSkvxTc2pl2WjOPsjZXDwPDSl5eghIMuY3R6J9NDKF3KcQ== better-sqlite3@^12.4.1: version "12.4.1" @@ -3330,15 +3356,15 @@ brotli@^1.3.2: base64-js "^1.1.2" browserslist@^4.0.0, browserslist@^4.24.0, browserslist@^4.24.4, browserslist@^4.25.1, browserslist@^4.26.3: - version "4.26.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.26.3.tgz#40fbfe2d1cd420281ce5b1caa8840049c79afb56" - integrity sha512-lAUU+02RFBuCKQPj/P6NgjlbCnLBMp4UtgTx7vNHd3XSIJF87s9a5rA3aH2yw3GS9DqZAUbOtZdCCiZeVRqt0w== + version "4.27.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.27.0.tgz#755654744feae978fbb123718b2f139bc0fa6697" + integrity sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw== dependencies: - baseline-browser-mapping "^2.8.9" - caniuse-lite "^1.0.30001746" - electron-to-chromium "^1.5.227" - node-releases "^2.0.21" - update-browserslist-db "^1.1.3" + baseline-browser-mapping "^2.8.19" + caniuse-lite "^1.0.30001751" + electron-to-chromium "^1.5.238" + node-releases "^2.0.26" + update-browserslist-db "^1.1.4" buffer-crc32@^1.0.0: version "1.0.0" @@ -3428,7 +3454,7 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001702, caniuse-lite@^1.0.30001746: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001702, caniuse-lite@^1.0.30001751: version "1.0.30001751" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001751.tgz#dacd5d9f4baeea841641640139d2b2a4df4226ad" integrity sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw== @@ -3704,12 +3730,12 @@ cookie@^1.0.2: resolved "https://registry.yarnpkg.com/cookie/-/cookie-1.0.2.tgz#27360701532116bd3f1f9416929d176afe1e4610" integrity sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA== -copy-anything@^3.0.2: - version "3.0.5" - resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-3.0.5.tgz#2d92dce8c498f790fa7ad16b01a1ae5a45b020a0" - integrity sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w== +copy-anything@^4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/copy-anything/-/copy-anything-4.0.5.tgz#16cabafd1ea4bb327a540b750f2b4df522825aea" + integrity sha512-7Vv6asjS4gMOuILabD3l739tsaxFQmC+a7pLZm02zyvs8p977bL3zEgq3yDk5rn9B0PbYgIv++jmHcuUab4RhA== dependencies: - is-what "^4.1.8" + is-what "^5.2.0" core-js-compat@^3.44.0: version "3.46.0" @@ -4015,15 +4041,15 @@ detect-libc@^1.0.3: resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== -detect-libc@^2.0.0, detect-libc@^2.0.2, detect-libc@^2.0.3, detect-libc@^2.0.4: +detect-libc@^2.0.0, detect-libc@^2.0.2, detect-libc@^2.0.3: version "2.1.2" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== devalue@^5.3.2: - version "5.4.1" - resolved "https://registry.yarnpkg.com/devalue/-/devalue-5.4.1.tgz#6086910772fa055d707f60a3e5858d26ef9dcf55" - integrity sha512-YtoaOfsqjbZQKGIMRYDWKjUmSB4VJ/RElB+bXZawQAQYAo4xu08GKTMVlsZDTF6R2MbAgjcAQRPI5eIyRAT2OQ== + version "5.4.2" + resolved "https://registry.yarnpkg.com/devalue/-/devalue-5.4.2.tgz#d002d836f9e92fc0c3bd9b76ea69129cbf99dca7" + integrity sha512-MwPZTKEPK2k8Qgfmqrd48ZKVvzSQjgW0lXLxiIBA8dQjtf/6mw6pggHNLcyDKyf+fI6eXxlQwPsfaCMTU5U+Bw== devlop@^1.0.0, devlop@^1.1.0: version "1.1.0" @@ -4104,10 +4130,10 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.5.227: - version "1.5.237" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.237.tgz#eacf61cef3f6345d0069ab427585c5a04d7084f0" - integrity sha512-icUt1NvfhGLar5lSWH3tHNzablaA5js3HVHacQimfP8ViEBOQv+L7DKEuHdbTZ0SKCO1ogTJTIL1Gwk9S6Qvcg== +electron-to-chromium@^1.5.238: + version "1.5.238" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.238.tgz#cdf5ee412df435174490f5aa5793df815b4ee157" + integrity sha512-khBdc+w/Gv+cS8e/Pbnaw/FXcBUeKrRVik9IxfXtgREOWyJhR4tj43n3amkVogJ/yeQUqzkrZcFhtIxIdqmmcQ== embla-carousel-auto-height@^8.6.0: version "8.6.0" @@ -4449,23 +4475,22 @@ eslint-visitor-keys@^4.2.0, eslint-visitor-keys@^4.2.1: integrity sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ== eslint@^9.37.0: - version "9.37.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.37.0.tgz#ac0222127f76b09c0db63036f4fe289562072d74" - integrity sha512-XyLmROnACWqSxiGYArdef1fItQd47weqB7iwtfr9JHwRrqIXZdcFMvvEcL9xHCmL0SNsOvF0c42lWyM1U5dgig== + version "9.38.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.38.0.tgz#3957d2af804e5cf6cc503c618f60acc71acb2e7e" + integrity sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw== dependencies: "@eslint-community/eslint-utils" "^4.8.0" "@eslint-community/regexpp" "^4.12.1" - "@eslint/config-array" "^0.21.0" - "@eslint/config-helpers" "^0.4.0" + "@eslint/config-array" "^0.21.1" + "@eslint/config-helpers" "^0.4.1" "@eslint/core" "^0.16.0" "@eslint/eslintrc" "^3.3.1" - "@eslint/js" "9.37.0" + "@eslint/js" "9.38.0" "@eslint/plugin-kit" "^0.4.0" "@humanfs/node" "^0.16.6" "@humanwhocodes/module-importer" "^1.0.1" "@humanwhocodes/retry" "^0.4.2" "@types/estree" "^1.0.6" - "@types/json-schema" "^7.0.15" ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.6" @@ -4840,9 +4865,9 @@ get-stream@^9.0.0: is-stream "^4.0.1" get-tsconfig@^4.10.1: - version "4.12.0" - resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.12.0.tgz#cfb3a4446a2abd324a205469e8bda4e7e44cbd35" - integrity sha512-LScr2aNr2FbjAjZh2C6X6BxRx1/x+aTDExct/xyq2XKbYOiG5c0aK7pMsSuyc0brz3ibr/lbQiHD9jzt4lccJw== + version "4.13.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.13.0.tgz#fcdd991e6d22ab9a600f00e91c318707a5d9a0d7" + integrity sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ== dependencies: resolve-pkg-maps "^1.0.0" @@ -5322,9 +5347,9 @@ ini@~1.3.0: integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== ioredis@^5.8.1: - version "5.8.1" - resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.8.1.tgz#2d2dae406be71665607906f57b3c971bb4b089ae" - integrity sha512-Qho8TgIamqEPdgiMadJwzRMW3TudIg6vpg4YONokGDudy4eqRIJtDbVX72pfLBcWxvbn3qm/40TyGUObdW4tLQ== + version "5.8.2" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-5.8.2.tgz#c7a228a26cf36f17a5a8011148836877780e2e14" + integrity sha512-C6uC+kleiIMmjViJINWk80sOQw5lEzse1ZmvD+S/s8p8CWapftSaC+kocGTx6xrbrJ4WmYQGC08ffHLr6ToR6Q== dependencies: "@ioredis/commands" "1.4.0" cluster-key-slot "^1.1.0" @@ -5400,7 +5425,7 @@ is-builtin-module@^5.0.0: dependencies: builtin-modules "^5.0.0" -is-core-module@^2.16.0: +is-core-module@^2.16.1: version "2.16.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== @@ -5518,10 +5543,10 @@ is-wayland@^0.1.0: resolved "https://registry.yarnpkg.com/is-wayland/-/is-wayland-0.1.0.tgz#ed966c54a608af5ba3c407922589859a0d424fe5" integrity sha512-QkbMsWkIfkrzOPxenwye0h56iAXirZYHG9eHVPb22fO9y+wPbaX/CHacOWBa/I++4ohTcByimhM1/nyCsH8KNA== -is-what@^4.1.8: - version "4.1.16" - resolved "https://registry.yarnpkg.com/is-what/-/is-what-4.1.16.tgz#1ad860a19da8b4895ad5495da3182ce2acdd7a6f" - integrity sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A== +is-what@^5.2.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/is-what/-/is-what-5.5.0.tgz#a3031815757cfe1f03fed990bf6355a2d3f628c4" + integrity sha512-oG7cgbmg5kLYae2N5IVd3jm2s+vldjxJzK1pcu9LfpGuQ93MQSzo0okvRna+7y5ifrD+20FE8FvjusyGaz14fw== is-wsl@^2.2.0: version "2.2.0" @@ -5726,73 +5751,79 @@ lighthouse-logger@^2.0.1: debug "^4.4.1" marky "^1.2.2" -lightningcss-darwin-arm64@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz#3d47ce5e221b9567c703950edf2529ca4a3700ae" - integrity sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ== - -lightningcss-darwin-x64@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz#e81105d3fd6330860c15fe860f64d39cff5fbd22" - integrity sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA== - -lightningcss-freebsd-x64@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz#a0e732031083ff9d625c5db021d09eb085af8be4" - integrity sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig== - -lightningcss-linux-arm-gnueabihf@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz#1f5ecca6095528ddb649f9304ba2560c72474908" - integrity sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q== - -lightningcss-linux-arm64-gnu@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz#eee7799726103bffff1e88993df726f6911ec009" - integrity sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw== - -lightningcss-linux-arm64-musl@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz#f2e4b53f42892feeef8f620cbb889f7c064a7dfe" - integrity sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ== - -lightningcss-linux-x64-gnu@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz#2fc7096224bc000ebb97eea94aea248c5b0eb157" - integrity sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw== - -lightningcss-linux-x64-musl@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz#66dca2b159fd819ea832c44895d07e5b31d75f26" - integrity sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ== - -lightningcss-win32-arm64-msvc@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz#7d8110a19d7c2d22bfdf2f2bb8be68e7d1b69039" - integrity sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA== - -lightningcss-win32-x64-msvc@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz#fd7dd008ea98494b85d24b4bea016793f2e0e352" - integrity sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg== - -lightningcss@1.30.1: - version "1.30.1" - resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.30.1.tgz#78e979c2d595bfcb90d2a8c0eb632fe6c5bfed5d" - integrity sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg== +lightningcss-android-arm64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz#6966b7024d39c94994008b548b71ab360eb3a307" + integrity sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A== + +lightningcss-darwin-arm64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.2.tgz#a5fa946d27c029e48c7ff929e6e724a7de46eb2c" + integrity sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA== + +lightningcss-darwin-x64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.2.tgz#5ce87e9cd7c4f2dcc1b713f5e8ee185c88d9b7cd" + integrity sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ== + +lightningcss-freebsd-x64@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.2.tgz#6ae1d5e773c97961df5cff57b851807ef33692a5" + integrity sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA== + +lightningcss-linux-arm-gnueabihf@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.2.tgz#62c489610c0424151a6121fa99d77731536cdaeb" + integrity sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA== + +lightningcss-linux-arm64-gnu@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.2.tgz#2a3661b56fe95a0cafae90be026fe0590d089298" + integrity sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A== + +lightningcss-linux-arm64-musl@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.2.tgz#d7ddd6b26959245e026bc1ad9eb6aa983aa90e6b" + integrity sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA== + +lightningcss-linux-x64-gnu@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.2.tgz#5a89814c8e63213a5965c3d166dff83c36152b1a" + integrity sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w== + +lightningcss-linux-x64-musl@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.2.tgz#808c2e91ce0bf5d0af0e867c6152e5378c049728" + integrity sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA== + +lightningcss-win32-arm64-msvc@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.2.tgz#ab4a8a8a2e6a82a4531e8bbb6bf0ff161ee6625a" + integrity sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ== + +lightningcss-win32-x64-msvc@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.2.tgz#f01f382c8e0a27e1c018b0bee316d210eac43b6e" + integrity sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw== + +lightningcss@1.30.2: + version "1.30.2" + resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.30.2.tgz#4ade295f25d140f487d37256f4cd40dc607696d0" + integrity sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ== dependencies: detect-libc "^2.0.3" optionalDependencies: - lightningcss-darwin-arm64 "1.30.1" - lightningcss-darwin-x64 "1.30.1" - lightningcss-freebsd-x64 "1.30.1" - lightningcss-linux-arm-gnueabihf "1.30.1" - lightningcss-linux-arm64-gnu "1.30.1" - lightningcss-linux-arm64-musl "1.30.1" - lightningcss-linux-x64-gnu "1.30.1" - lightningcss-linux-x64-musl "1.30.1" - lightningcss-win32-arm64-msvc "1.30.1" - lightningcss-win32-x64-msvc "1.30.1" + lightningcss-android-arm64 "1.30.2" + lightningcss-darwin-arm64 "1.30.2" + lightningcss-darwin-x64 "1.30.2" + lightningcss-freebsd-x64 "1.30.2" + lightningcss-linux-arm-gnueabihf "1.30.2" + lightningcss-linux-arm64-gnu "1.30.2" + lightningcss-linux-arm64-musl "1.30.2" + lightningcss-linux-x64-gnu "1.30.2" + lightningcss-linux-x64-musl "1.30.2" + lightningcss-win32-arm64-msvc "1.30.2" + lightningcss-win32-x64-msvc "1.30.2" lilconfig@^3.1.3: version "3.1.3" @@ -6523,9 +6554,9 @@ motion-utils@^12.23.6: integrity sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ== motion-v@^1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/motion-v/-/motion-v-1.7.2.tgz#90c51269ce2107b2f640cfb47037f8e1df4b810a" - integrity sha512-h2qfae2LUMLw5KIjQF5cT+r0MrLwP4AFDMOisyp25x/oDI3PHgjLHJrhHx77q8iBNegk4llt5p6deC12EJ5fvQ== + version "1.7.3" + resolved "https://registry.yarnpkg.com/motion-v/-/motion-v-1.7.3.tgz#2dc491559f66b3ccb02f46d0d2e2e8958ddb0dd9" + integrity sha512-lwgrge7Y7FF9LxBxZ//MsSLPPjh4z1yYE9ie236Pa89mRCsBlONXbLcseln6G6LyAG8pt3PpzUxWt2grwMcBAA== dependencies: framer-motion "12.23.12" hey-listen "^1.0.8" @@ -6711,10 +6742,10 @@ node-mock-http@^1.0.2, node-mock-http@^1.0.3: resolved "https://registry.yarnpkg.com/node-mock-http/-/node-mock-http-1.0.3.tgz#4e55e093267a3b910cded7354389ce2d02c89e77" integrity sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog== -node-releases@^2.0.21: - version "2.0.25" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.25.tgz#95479437bd409231e03981c1f6abee67f5e962df" - integrity sha512-4auku8B/vw5psvTiiN9j1dAOsXvMoGqJuKJcR+dTdqiXEK20mMTk1UEo3HS16LeGQsVG6+qKTPM9u/qQ2LqATA== +node-releases@^2.0.26: + version "2.0.26" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.26.tgz#fdfa272f2718a1309489d18aef4ef5ba7f5dfb52" + integrity sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA== nopt@^8.0.0: version "8.1.0" @@ -6756,9 +6787,9 @@ nth-check@^2.0.1, nth-check@^2.1.1: boolbase "^1.0.0" nuxt-component-meta@^0.14.0: - version "0.14.0" - resolved "https://registry.yarnpkg.com/nuxt-component-meta/-/nuxt-component-meta-0.14.0.tgz#09b9b054cf3a83321b50003443b7be63021ff774" - integrity sha512-RaL6bHJujuZmw/G+uNWAHYktf3k4hdlBIy+FqudXji42IefrJKdSMkh5ixyhsfEHWsuTYGKxD2NU3sq990KGrQ== + version "0.14.1" + resolved "https://registry.yarnpkg.com/nuxt-component-meta/-/nuxt-component-meta-0.14.1.tgz#9ccf05b4ae1c3c1a390220c47aa9cb05b2476bf1" + integrity sha512-Q8NuynMJleiutBx4cD33TLp5HCGGmGfz/dE+PNOsAScSAG54hmpPk2beeIwh2VZJoMzPAyPPAqbsdIKpMcOHbA== dependencies: "@nuxt/kit" "^4.1.1" citty "^0.1.6" @@ -6826,28 +6857,28 @@ nuxt-schema-org@^5.0.9: pkg-types "^2.3.0" sirv "^3.0.2" -nuxt-site-config-kit@3.2.10: - version "3.2.10" - resolved "https://registry.yarnpkg.com/nuxt-site-config-kit/-/nuxt-site-config-kit-3.2.10.tgz#337099640471c7a488d2214bd604a8da2f4dd1d2" - integrity sha512-HHBqcOLxYuw1HiAinaR/aGBvTZUdv7YcLsYDW2kuKAhLpiChACYM6lX3RTyrpLe6BNGRUJB69DbJ1VM8+QYWEA== +nuxt-site-config-kit@3.2.11: + version "3.2.11" + resolved "https://registry.yarnpkg.com/nuxt-site-config-kit/-/nuxt-site-config-kit-3.2.11.tgz#0ef33cd4dc4f9347d5bf10eb4ad8c72a970f4d20" + integrity sha512-Um9/JiJpskAC8H18pHs3D/c7ikKj37/OsM1rvTqDgdzShSzOAxGGN+8qBVtGaqp1V+9BuPFSXhr1+TV7+RRsRA== dependencies: "@nuxt/kit" "^4.1.3" pkg-types "^2.3.0" - site-config-stack "3.2.10" + site-config-stack "3.2.11" std-env "^3.10.0" ufo "^1.6.1" nuxt-site-config@^3.2.5, nuxt-site-config@^3.2.9: - version "3.2.10" - resolved "https://registry.yarnpkg.com/nuxt-site-config/-/nuxt-site-config-3.2.10.tgz#175be858bb607f0285fa9cf09804c4762b7bc9ea" - integrity sha512-2iyjOy3B1gIKlzNFMw3D9WpFw9kMlT5H4DqL3NAvmRf+Sem2vrhOzm8snON7Fxn94OYA5jNjgzusivNEM6InEQ== + version "3.2.11" + resolved "https://registry.yarnpkg.com/nuxt-site-config/-/nuxt-site-config-3.2.11.tgz#a0883e54cdd58eacca0d59a63a8773e07b022437" + integrity sha512-hU78O5f0/n1LOIorDe6iKbW3xw19bao8YbQ7RCiUtVM+1XbD11JWzUXWygX7atV+KtzGhZUbTbhjxmfbnlF//A== dependencies: "@nuxt/kit" "^4.1.3" - nuxt-site-config-kit "3.2.10" + nuxt-site-config-kit "3.2.11" pathe "^2.0.3" pkg-types "^2.3.0" sirv "^3.0.2" - site-config-stack "3.2.10" + site-config-stack "3.2.11" ufo "^1.6.1" nuxt@^4.1.3: @@ -7121,9 +7152,9 @@ package-json-from-dist@^1.0.0: integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== package-manager-detector@^1.1.0, package-manager-detector@^1.3.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/package-manager-detector/-/package-manager-detector-1.4.1.tgz#8f683009e02cc2ca1c4e2c887316075108239189" - integrity sha512-dSMiVLBEA4XaNJ0PRb4N5cV/SEP4BWrWZKBmfF+OUm2pQTiZ6DDkKeWaltwu3JRhLoy59ayIkJ00cx9K9CaYTg== + version "1.5.0" + resolved "https://registry.yarnpkg.com/package-manager-detector/-/package-manager-detector-1.5.0.tgz#8dcf7b78554047ddf5da453e6ba07ebc915c507e" + integrity sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw== pako@^0.2.5: version "0.2.9" @@ -7853,7 +7884,7 @@ rehype-sort-attributes@^5.0.1: "@types/hast" "^3.0.0" unist-util-visit "^5.0.0" -reka-ui@2.5.1, reka-ui@^2.0.0: +reka-ui@2.5.1: version "2.5.1" resolved "https://registry.yarnpkg.com/reka-ui/-/reka-ui-2.5.1.tgz#4623b9ad0281d1747b76dffdb620496a92f7ac1d" integrity sha512-QJGB3q21wQ1Kw28HhhNDpjfFe8qpePX1gK4FTBRd68XTh9aEnhR5bTJnlV0jxi8FBPh0xivZBeNFUc3jiGx7mQ== @@ -7869,6 +7900,22 @@ reka-ui@2.5.1, reka-ui@^2.0.0: defu "^6.1.4" ohash "^2.0.11" +reka-ui@^2.0.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/reka-ui/-/reka-ui-2.6.0.tgz#3b96712744decb9da8f4b1af79d16a499c84b826" + integrity sha512-NrGMKrABD97l890mFS3TNUzB0BLUfbL3hh0NjcJRIUSUljb288bx3Mzo31nOyUcdiiW0HqFGXJwyCBh9cWgb0w== + dependencies: + "@floating-ui/dom" "^1.6.13" + "@floating-ui/vue" "^1.1.6" + "@internationalized/date" "^3.5.0" + "@internationalized/number" "^3.5.0" + "@tanstack/vue-virtual" "^3.12.0" + "@vueuse/core" "^12.5.0" + "@vueuse/shared" "^12.5.0" + aria-hidden "^1.2.4" + defu "^6.1.4" + ohash "^2.0.11" + remark-emoji@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/remark-emoji/-/remark-emoji-5.0.2.tgz#2a66df174806ed2dc68c329d475b7d993d2d4506" @@ -7991,11 +8038,11 @@ resolve-pkg-maps@^1.0.0: integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== resolve@^1.22.1: - version "1.22.10" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" - integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== + version "1.22.11" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.11.tgz#aad857ce1ffb8bfa9b0b1ac29f1156383f68c262" + integrity sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ== dependencies: - is-core-module "^2.16.0" + is-core-module "^2.16.1" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -8025,34 +8072,34 @@ rollup-plugin-visualizer@^6.0.4: yargs "^17.5.1" rollup@^4.43.0, rollup@^4.52.4: - version "4.52.4" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.52.4.tgz#71e64cce96a865fcbaa6bb62c6e82807f4e378a1" - integrity sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ== + version "4.52.5" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.52.5.tgz#96982cdcaedcdd51b12359981f240f94304ec235" + integrity sha512-3GuObel8h7Kqdjt0gxkEzaifHTqLVW56Y/bjN7PSQtkKr0w3V/QYSdt6QWYtd7A1xUtYQigtdUfgj1RvWVtorw== dependencies: "@types/estree" "1.0.8" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.52.4" - "@rollup/rollup-android-arm64" "4.52.4" - "@rollup/rollup-darwin-arm64" "4.52.4" - "@rollup/rollup-darwin-x64" "4.52.4" - "@rollup/rollup-freebsd-arm64" "4.52.4" - "@rollup/rollup-freebsd-x64" "4.52.4" - "@rollup/rollup-linux-arm-gnueabihf" "4.52.4" - "@rollup/rollup-linux-arm-musleabihf" "4.52.4" - "@rollup/rollup-linux-arm64-gnu" "4.52.4" - "@rollup/rollup-linux-arm64-musl" "4.52.4" - "@rollup/rollup-linux-loong64-gnu" "4.52.4" - "@rollup/rollup-linux-ppc64-gnu" "4.52.4" - "@rollup/rollup-linux-riscv64-gnu" "4.52.4" - "@rollup/rollup-linux-riscv64-musl" "4.52.4" - "@rollup/rollup-linux-s390x-gnu" "4.52.4" - "@rollup/rollup-linux-x64-gnu" "4.52.4" - "@rollup/rollup-linux-x64-musl" "4.52.4" - "@rollup/rollup-openharmony-arm64" "4.52.4" - "@rollup/rollup-win32-arm64-msvc" "4.52.4" - "@rollup/rollup-win32-ia32-msvc" "4.52.4" - "@rollup/rollup-win32-x64-gnu" "4.52.4" - "@rollup/rollup-win32-x64-msvc" "4.52.4" + "@rollup/rollup-android-arm-eabi" "4.52.5" + "@rollup/rollup-android-arm64" "4.52.5" + "@rollup/rollup-darwin-arm64" "4.52.5" + "@rollup/rollup-darwin-x64" "4.52.5" + "@rollup/rollup-freebsd-arm64" "4.52.5" + "@rollup/rollup-freebsd-x64" "4.52.5" + "@rollup/rollup-linux-arm-gnueabihf" "4.52.5" + "@rollup/rollup-linux-arm-musleabihf" "4.52.5" + "@rollup/rollup-linux-arm64-gnu" "4.52.5" + "@rollup/rollup-linux-arm64-musl" "4.52.5" + "@rollup/rollup-linux-loong64-gnu" "4.52.5" + "@rollup/rollup-linux-ppc64-gnu" "4.52.5" + "@rollup/rollup-linux-riscv64-gnu" "4.52.5" + "@rollup/rollup-linux-riscv64-musl" "4.52.5" + "@rollup/rollup-linux-s390x-gnu" "4.52.5" + "@rollup/rollup-linux-x64-gnu" "4.52.5" + "@rollup/rollup-linux-x64-musl" "4.52.5" + "@rollup/rollup-openharmony-arm64" "4.52.5" + "@rollup/rollup-win32-arm64-msvc" "4.52.5" + "@rollup/rollup-win32-ia32-msvc" "4.52.5" + "@rollup/rollup-win32-x64-gnu" "4.52.5" + "@rollup/rollup-win32-x64-msvc" "4.52.5" fsevents "~2.3.2" run-applescript@^7.0.0: @@ -8270,10 +8317,10 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== -site-config-stack@3.2.10: - version "3.2.10" - resolved "https://registry.yarnpkg.com/site-config-stack/-/site-config-stack-3.2.10.tgz#c2bbae84aaf55bd35b8071a9623237b4f47890f7" - integrity sha512-y6cMJWSRUup1DX1KILvrUH9mVInqvtjFSYOSJMkWC0eIm9n43qYtxM9DMDKEgS5kZXEGmW8A0H3svunyIPLtTg== +site-config-stack@3.2.11: + version "3.2.11" + resolved "https://registry.yarnpkg.com/site-config-stack/-/site-config-stack-3.2.11.tgz#51ff6fb61a9fdb745aa1adc0a1e111449f4c30ac" + integrity sha512-KRJ49L58VtJJo3WdB7hXv6lq3oEJNOoBpig1v+OuHSppiBp7X6xqcAByJHveeBpBE9kHwqy/sn1LEnIibQ4nOA== dependencies: ufo "^1.6.1" @@ -8517,11 +8564,11 @@ stylehacks@^7.0.5: postcss-selector-parser "^7.1.0" superjson@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/superjson/-/superjson-2.2.2.tgz#9d52bf0bf6b5751a3c3472f1292e714782ba3173" - integrity sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q== + version "2.2.3" + resolved "https://registry.yarnpkg.com/superjson/-/superjson-2.2.3.tgz#c42236fff6ecc449b7ffa7f023a9a028a5ec9c87" + integrity sha512-ay3d+LW/S6yppKoTz3Bq4mG0xrS5bFwfWEBmQfbC7lt5wmtk+Obq0TxVuA9eYRirBTQb1K3eEpBRHMQEo0WyVw== dependencies: - copy-anything "^3.0.2" + copy-anything "^4" supports-color@^10.0.0: version "10.2.2" @@ -8591,10 +8638,10 @@ tailwind-variants@^3.1.1: resolved "https://registry.yarnpkg.com/tailwind-variants/-/tailwind-variants-3.1.1.tgz#40a87a7f24a3c372faecedd23a9c40e40bb2033d" integrity sha512-ftLXe3krnqkMHsuBTEmaVUXYovXtPyTK7ckEfDRXS8PBZx0bAUas+A0jYxuKA5b8qg++wvQ3d2MQ7l/xeZxbZQ== -tailwindcss@4.1.14, tailwindcss@^4.1.14: - version "4.1.14" - resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-4.1.14.tgz#a5907cc2202a2a1f5f15bac6f2031e53117e43a8" - integrity sha512-b7pCxjGO98LnxVkKjaZSDeNuljC4ueKUddjENJOADtubtdo8llTaJy7HwBMeLNSSo2N5QIAgklslK1+Ir8r6CA== +tailwindcss@4.1.15, tailwindcss@^4.1.14: + version "4.1.15" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-4.1.15.tgz#1437ee75ed8f66d8d866da5e25daa38d06ce5cea" + integrity sha512-k2WLnWkYFkdpRv+Oby3EBXIyQC8/s1HOFMBUViwtAh6Z5uAozeUSMQlIsn/c6Q2iJzqG6aJT3wdPaRNj70iYxQ== tapable@^2.2.0: version "2.3.0" @@ -8642,7 +8689,7 @@ tar-stream@^3.0.0, tar-stream@^3.1.5: fast-fifo "^1.2.0" streamx "^2.15.0" -tar@^7.4.0, tar@^7.4.3, tar@^7.5.1: +tar@^7.4.0, tar@^7.4.3: version "7.5.1" resolved "https://registry.yarnpkg.com/tar/-/tar-7.5.1.tgz#750a8bd63b7c44c1848e7bf982260a083cf747c9" integrity sha512-nlGpxf+hv0v7GkWBK2V9spgactGOp0qvfWRxUMjqHyzrt3SgwE48DIv/FhqPHJYLHpgW1opq3nERbz5Anq7n1g== @@ -8796,10 +8843,10 @@ unctx@^2.4.1: magic-string "^0.30.17" unplugin "^2.1.0" -undici-types@~7.14.0: - version "7.14.0" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.14.0.tgz#4c037b32ca4d7d62fae042174604341588bc0840" - integrity sha512-QQiYxHuyZ9gQUIrmPo3IA+hUl4KYk8uSA7cHrcKd/l3p1OTpZcM0Tbp9x7FAtXdAYhlasd60ncPpgu6ihG6TOA== +undici-types@~7.16.0: + version "7.16.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46" + integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw== undici@^7.16.0: version "7.16.0" @@ -8978,9 +9025,9 @@ unplugin-utils@^0.3.0, unplugin-utils@^0.3.1: picomatch "^4.0.3" unplugin-vue-components@^29.1.0: - version "29.1.0" - resolved "https://registry.yarnpkg.com/unplugin-vue-components/-/unplugin-vue-components-29.1.0.tgz#6064dfd43ebfc2d54fc04d6c391d30c9f66d3360" - integrity sha512-z/9ACPXth199s9aCTCdKZAhe5QGOpvzJYP+Hkd0GN1/PpAmsu+W3UlRY3BJAewPqQxh5xi56+Og6mfiCV1Jzpg== + version "29.2.0" + resolved "https://registry.yarnpkg.com/unplugin-vue-components/-/unplugin-vue-components-29.2.0.tgz#5cf1aace82f6e7481fb068e6d23f33ef1ef849d6" + integrity sha512-QxBeBdmEflgtJRgMQMc/z/JVV5lcwXN5nOy5ehX6CKDGylIu6Qn4Goy8X95S0qOxF7EdI+uNhdBd4v5i0bvzCw== dependencies: chokidar "^3.6.0" debug "^4.4.3" @@ -8989,7 +9036,7 @@ unplugin-vue-components@^29.1.0: mlly "^1.8.0" tinyglobby "^0.2.15" unplugin "^2.3.10" - unplugin-utils "^0.3.0" + unplugin-utils "^0.3.1" unplugin-vue-router@^0.15.0: version "0.15.0" @@ -9096,10 +9143,10 @@ unwasm@^0.3.11: pkg-types "^2.2.0" unplugin "^2.3.6" -update-browserslist-db@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" - integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== +update-browserslist-db@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz#7802aa2ae91477f255b86e0e46dbc787a206ad4a" + integrity sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A== dependencies: escalade "^3.2.0" picocolors "^1.1.1" @@ -9219,9 +9266,9 @@ vite-plugin-vue-tracer@^1.0.0: source-map-js "^1.2.1" "vite@^5.0.0 || ^6.0.0 || ^7.0.0-0", vite@^7.1.9: - version "7.1.10" - resolved "https://registry.yarnpkg.com/vite/-/vite-7.1.10.tgz#47c9970f3b0fe9057bfbcfeff8cd370edd7bd41b" - integrity sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA== + version "7.1.11" + resolved "https://registry.yarnpkg.com/vite/-/vite-7.1.11.tgz#4d006746112fee056df64985191e846ebfb6007e" + integrity sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg== dependencies: esbuild "^0.25.0" fdir "^6.5.0" From 1bf90e83f145f0b81fbb11efbcd18c1854e469ae Mon Sep 17 00:00:00 2001 From: Dan Pastori Date: Wed, 22 Oct 2025 16:24:53 -0500 Subject: [PATCH 087/170] Fixed OG Images --- docs/app/components/OgImage/OgImageDocs.vue | 99 ++++++--------------- 1 file changed, 29 insertions(+), 70 deletions(-) diff --git a/docs/app/components/OgImage/OgImageDocs.vue b/docs/app/components/OgImage/OgImageDocs.vue index dadabc9a5..bc5448b8d 100644 --- a/docs/app/components/OgImage/OgImageDocs.vue +++ b/docs/app/components/OgImage/OgImageDocs.vue @@ -1,76 +1,35 @@ - + \ No newline at end of file From ce7f643eab98dd5e75b425bb5dc0d5c654c0d5d0 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 16:30:34 -0500 Subject: [PATCH 088/170] Add migration guide from official PHP images to serversideup/php, detailing key differences, default configurations, and step-by-step instructions for updating Dockerfiles and docker-compose.yml files, enhancing user onboarding and transition experience. --- .../1.migrating-from-official-php-images.md | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 docs/content/docs/5.guide/1.migrating-from-official-php-images.md diff --git a/docs/content/docs/5.guide/1.migrating-from-official-php-images.md b/docs/content/docs/5.guide/1.migrating-from-official-php-images.md new file mode 100644 index 000000000..cdd616b5f --- /dev/null +++ b/docs/content/docs/5.guide/1.migrating-from-official-php-images.md @@ -0,0 +1,89 @@ +--- +head.title: 'Migrating from official PHP Docker images - Docker PHP - Server Side Up' +description: 'Learn how easy it is to move from the official PHP docker images to serversideup/php.' +layout: docs +title: Migrating from official PHP images +--- + +::lead-p +Migrating from the official PHP images to serversideup/php is easy because our images are based on the official PHP images. We just give you a "batteries included" experience that's ready for production. +:: + +## Understand our default configurations +Before you make the switch, you should understand our default configurations and make sure they line up with your requirements. As always, perform these changes on a test branch and use automated testing to ensure your application is working as expected. + +:u-button{to="/docs/getting-started/default-configurations" label="Learn more about our default configurations" aria-label="Learn more about our default configurations" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## Key differences +::warning +Because our images run as `www-data` by default, you may need to update file permissions for mounted volumes. +:: + +| | **Official PHP Images** |**serversideup/php** | +|-------------------------|-------------------------|---------------------| +| Base Operating System | Debian, Alpine | Debian, Alpine | +| PHP Compilation | PHP Source Code | PHP Source Code (based on official PHP images) | +| Run PHP, pinned to the minor version | ✅ | ✅ | +| Multi-arch support | ✅ | ✅ | +| Init System | Docker CMD | Docker CMD or [S6-Overlay](https://github.com/just-containers/s6-overlay) | +| Published Registry| DockerHub | [DockerHub](https://hub.docker.com/r/serversideup/php), [GitHub Packages](https://github.com/serversideup/docker-php/pkgs/container/php) | +| Unprivileged by default | ❌ | ✅ | +| Variable-first configuration | ❌ | ✅ | +| Includes `composer` | ❌ | ✅ | +| Includes [`install-php-extensions`](https://github.com/mlocati/docker-php-extension-installer) | ❌ | ✅ | +| Production-Ready by default| ❌ | ✅ | +| Built-in security optimizations | ❌ | ✅ | +| Optimized for Laravel & WordPress| ❌ | ✅ | +| NGINX + FPM variation| ❌ | ✅ | +| FrankenPHP variation| ❌ | ✅ | +| Native health checks | ❌ | ✅ | + +:u-button{to="/docs/getting-started/choosing-an-image" label="Learn more about choosing an image" aria-label="Learn more about choosing an image" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## Making the change +Making the change will literally take you two seconds. + +::steps{level="4"} + +#### Figure out which image you'd like to use +Review our [choosing an image](/docs/getting-started/choosing-an-image) guide to help you decide which image you'd like to use. + +#### Update your `Dockerfile` or `docker-compose.yml` file +:::tip +We simply change `php:8.4-apache` to `serversideup/php:8.4-fpm-apache` +::: +**Dockerfile** +:::code-group +```dockerfile [ORIGINAL: Dockerfile]{1} +FROM php:8.4-apache + +# Rest of your Dockerfile... +``` +```dockerfile [UPDATED: Dockerfile]{1} +FROM serversideup/php:8.4-fpm-apache + +# Rest of your Dockerfile... +``` +::: + +**docker-compose.yml** +:::code-group +```yml [ORIGINAL: docker-compose.yml]{3,5-6} +services: + php: + image: php:8.4-apache + ports: + - 80:80 + - 443:443 +``` +```yml [UPDATED: docker-compose.yml]{3,5-6} +services: + php: + image: serversideup/php:8.4-fpm-apache + ports: + - 80:8080 + - 443:8443 +``` +::: + +:: \ No newline at end of file From ae1dfb4ec0e3e751044836a44bde92d6b610ff72 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 16:30:40 -0500 Subject: [PATCH 089/170] Add 'diff' language support to Nuxt configuration, enhancing syntax highlighting for documentation and improving readability for users working with code diffs. --- docs/nuxt.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/nuxt.config.ts b/docs/nuxt.config.ts index d24c20172..00219ab09 100644 --- a/docs/nuxt.config.ts +++ b/docs/nuxt.config.ts @@ -26,6 +26,7 @@ export default defineNuxtConfig({ langs: [ 'jinja', 'bash', + 'diff', 'dockerfile', 'nginx', 'php', From 44d36262d02fa0863d81b4855f0b6fdbabbdcbd2 Mon Sep 17 00:00:00 2001 From: Dan Pastori Date: Wed, 22 Oct 2025 16:32:11 -0500 Subject: [PATCH 090/170] Added about --- docs/app/components/About.vue | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 docs/app/components/About.vue diff --git a/docs/app/components/About.vue b/docs/app/components/About.vue new file mode 100644 index 000000000..9619ebd8d --- /dev/null +++ b/docs/app/components/About.vue @@ -0,0 +1,34 @@ + \ No newline at end of file From 2c1f2c49a8cc5e2e96eec6b1e37806e6193b7906 Mon Sep 17 00:00:00 2001 From: Dan Pastori Date: Thu, 23 Oct 2025 07:45:43 -0500 Subject: [PATCH 091/170] Add new components and enhance existing documentation for improved user engagement and onboarding experience. Introduced 'FollowAlong', 'GetStarted', 'LandingSignup', and 'Testimonials' components to showcase community involvement and provide clear calls to action. Updated Nuxt configuration for Plausible analytics and refined CSS styles for better UI consistency. Updated OG images for social sharing. --- docs/app/app.config.ts | 32 ++++- docs/app/assets/css/main.css | 4 + docs/app/components/AppFooter.vue | 2 +- docs/app/components/AppHeader.vue | 124 ++++++++++-------- docs/app/components/FollowAlong.vue | 72 ++++++++++ docs/app/components/GetStarted.vue | 14 ++ docs/app/components/LandingSignup.vue | 41 ++++++ docs/app/components/Testimonials.vue | 39 ++++++ docs/app/pages/index.vue | 4 +- .../1.getting-started/4.choosing-an-image.md | 12 +- docs/content/index.md | 31 ++--- docs/nuxt.config.ts | 4 + docs/public/images/social-image.jpg | Bin 0 -> 229668 bytes .../images/testimonials/chris-fidao.png | Bin 0 -> 39044 bytes .../images/testimonials/johan-janssens.png | Bin 0 -> 36857 bytes docs/public/images/testimonials/ziga-zajc.png | Bin 0 -> 26483 bytes 16 files changed, 295 insertions(+), 84 deletions(-) create mode 100644 docs/app/components/FollowAlong.vue create mode 100644 docs/app/components/GetStarted.vue create mode 100644 docs/app/components/LandingSignup.vue create mode 100644 docs/app/components/Testimonials.vue create mode 100644 docs/public/images/social-image.jpg create mode 100644 docs/public/images/testimonials/chris-fidao.png create mode 100644 docs/public/images/testimonials/johan-janssens.png create mode 100644 docs/public/images/testimonials/ziga-zajc.png diff --git a/docs/app/app.config.ts b/docs/app/app.config.ts index 60977991b..e81b3495a 100644 --- a/docs/app/app.config.ts +++ b/docs/app/app.config.ts @@ -30,6 +30,36 @@ export default defineAppConfig({ 'Dockerfile': 'i-services-docker', 'nginx.conf': 'i-services-nginx', 'Terminal': 'i-ph-terminal-window-duotone' + }, + callout: { + slots: { + base: 'text-white [&_a]:text-white [&_a]:hover:text-white [&_a]:hover:border-white' + }, + variants: { + color: { + primary: { + base: '[&_a]:text-white [&_a]:hover:text-white [&_a]:hover:border-white' + }, + secondary: { + base: '[&_a]:text-white [&_a]:hover:text-white [&_a]:hover:border-white' + }, + success: { + base: '[&_a]:text-white [&_a]:hover:text-white [&_a]:hover:border-white' + }, + info: { + base: '[&_a]:text-white [&_a]:hover:text-white [&_a]:hover:border-white' + }, + warning: { + base: '[&_a]:text-white [&_a]:hover:text-white [&_a]:hover:border-white' + }, + error: { + base: '[&_a]:text-white [&_a]:hover:text-white [&_a]:hover:border-white' + }, + neutral: { + base: '[&_a]:text-white [&_a]:hover:text-white [&_a]:hover:border-white' + } + } + } } }, mode: 'dark', @@ -43,7 +73,7 @@ export default defineAppConfig({ root: 'border-t border-default', left: 'text-sm text-muted' } - } + }, }, seo: { siteName: 'PHP Docker Images (serversideup/php)' diff --git a/docs/app/assets/css/main.css b/docs/app/assets/css/main.css index af39d6b01..075cb4764 100644 --- a/docs/app/assets/css/main.css +++ b/docs/app/assets/css/main.css @@ -31,3 +31,7 @@ :root { --ui-container: var(--container-8xl); } + +ul ul ul { + border: none !important; +} \ No newline at end of file diff --git a/docs/app/components/AppFooter.vue b/docs/app/components/AppFooter.vue index f7a3c7fd9..947d8d20c 100644 --- a/docs/app/components/AppFooter.vue +++ b/docs/app/components/AppFooter.vue @@ -3,7 +3,7 @@ const { footer } = useAppConfig() diff --git a/docs/app/components/FollowAlong.vue b/docs/app/components/FollowAlong.vue new file mode 100644 index 000000000..7462446aa --- /dev/null +++ b/docs/app/components/FollowAlong.vue @@ -0,0 +1,72 @@ + \ No newline at end of file diff --git a/docs/app/components/GetStarted.vue b/docs/app/components/GetStarted.vue new file mode 100644 index 000000000..4495c6009 --- /dev/null +++ b/docs/app/components/GetStarted.vue @@ -0,0 +1,14 @@ + \ No newline at end of file diff --git a/docs/app/components/LandingSignup.vue b/docs/app/components/LandingSignup.vue new file mode 100644 index 000000000..b3cea8fcc --- /dev/null +++ b/docs/app/components/LandingSignup.vue @@ -0,0 +1,41 @@ + + + \ No newline at end of file diff --git a/docs/app/components/Testimonials.vue b/docs/app/components/Testimonials.vue new file mode 100644 index 000000000..a8c69a889 --- /dev/null +++ b/docs/app/components/Testimonials.vue @@ -0,0 +1,39 @@ + \ No newline at end of file diff --git a/docs/app/pages/index.vue b/docs/app/pages/index.vue index 90d5cefbf..aeb520f34 100644 --- a/docs/app/pages/index.vue +++ b/docs/app/pages/index.vue @@ -23,7 +23,7 @@ useSeoMeta({ ogTitle: title, description, ogDescription: description, - ogImage: 'https://ui.nuxt.com/assets/templates/nuxt/docs-light.png', - twitterImage: 'https://ui.nuxt.com/assets/templates/nuxt/docs-light.png' + ogImage: 'images/social-image.jpg', + twitterImage: 'images/social-image.jpg' }) diff --git a/docs/content/docs/1.getting-started/4.choosing-an-image.md b/docs/content/docs/1.getting-started/4.choosing-an-image.md index e442deb83..f6f8c0b36 100644 --- a/docs/content/docs/1.getting-started/4.choosing-an-image.md +++ b/docs/content/docs/1.getting-started/4.choosing-an-image.md @@ -35,12 +35,12 @@ If you don't specify a variation, it defaults to `cli` and the latest supported Our most popular tags include: | ⚙️ Variation | 🚀 Version | | ------------ | ---------- | -| cli | **Debian Based** [![serversideup/php:8.4-cli](https://img.shields.io/docker/image-size/serversideup/php/8.4-cli?label=serversideup%2Fphp%3A8.4-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-cli&page=1&ordering=-name) [![serversideup/php:8.3-cli](https://img.shields.io/docker/image-size/serversideup/php/8.3-cli?label=serversideup%2Fphp%3A8.3-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-cli&page=1&ordering=-name) [![serversideup/php:8.2-cli](https://img.shields.io/docker/image-size/serversideup/php/8.2-cli?label=serversideup%2Fphp%3A8.2-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-cli&page=1&ordering=-name) [![serversideup/php:8.1-cli](https://img.shields.io/docker/image-size/serversideup/php/8.1-cli?label=serversideup%2Fphp%3A8.1-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-cli&page=1&ordering=-name) [![serversideup/php:8.0-cli](https://img.shields.io/docker/image-size/serversideup/php/8.0-cli?label=serversideup%2Fphp%3A8.0-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-cli&page=1&ordering=-name) [![serversideup/php:7.4-cli](https://img.shields.io/docker/image-size/serversideup/php/7.4-cli?label=serversideup%2Fphp%3A7.4-cli){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-cli&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:8.4-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-cli-alpine?label=serversideup%2Fphp%3A8.4-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-cli-alpine&page=1&ordering=-name) [![serversideup/php:8.3-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-cli-alpine?label=serversideup%2Fphp%3A8.3-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-cli-alpine&page=1&ordering=-name) [![serversideup/php:8.2-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.2-cli-alpine?label=serversideup%2Fphp%3A8.2-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-cli-alpine&page=1&ordering=-name) [![serversideup/php:8.1-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.1-cli-alpine?label=serversideup%2Fphp%3A8.1-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-cli-alpine&page=1&ordering=-name) [![serversideup/php:8.0-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.0-cli-alpine?label=serversideup%2Fphp%3A8.0-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-cli-alpine&page=1&ordering=-name) [![serversideup/php:7.4-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/7.4-cli-alpine?label=serversideup%2Fphp%3A7.4-cli-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-cli-alpine&page=1&ordering=-name) | -| fpm | **Debian Based** [![serversideup/php:8.4-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm?label=serversideup%2Fphp%3A8.4-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm&page=1&ordering=-name) [![serversideup/php:8.3-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm?label=serversideup%2Fphp%3A8.3-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm&page=1&ordering=-name) [![serversideup/php:8.2-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm?label=serversideup%2Fphp%3A8.2-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm&page=1&ordering=-name) [![serversideup/php:8.1-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm?label=serversideup%2Fphp%3A8.1-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm&page=1&ordering=-name) [![serversideup/php:8.0-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm?label=serversideup%2Fphp%3A8.0-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm&page=1&ordering=-name) [![serversideup/php:7.4-fpm](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm?label=serversideup%2Fphp%3A7.4-fpm){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:8.4-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-alpine?label=serversideup%2Fphp%3A8.4-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.3-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-alpine?label=serversideup%2Fphp%3A8.3-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.2-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-alpine?label=serversideup%2Fphp%3A8.2-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.1-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-alpine?label=serversideup%2Fphp%3A8.1-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.0-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-alpine?label=serversideup%2Fphp%3A8.0-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-alpine&page=1&ordering=-name) [![serversideup/php:7.4-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-alpine?label=serversideup%2Fphp%3A7.4-fpm-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-alpine&page=1&ordering=-name) | -| fpm-apache | **Debian Based** [![serversideup/php:8.4-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-apache?label=serversideup%2Fphp%3A8.4-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.3-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-apache?label=serversideup%2Fphp%3A8.3-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.2-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-apache?label=serversideup%2Fphp%3A8.2-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.1-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-apache?label=serversideup%2Fphp%3A8.1-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.0-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-apache?label=serversideup%2Fphp%3A8.0-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-apache&page=1&ordering=-name) [![serversideup/php:7.4-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-apache?label=serversideup%2Fphp%3A7.4-fpm-apache){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-apache&page=1&ordering=-name) | -| fpm-nginx | **Debian Based** [![serversideup/php:8.4-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-nginx?label=serversideup%2Fphp%3A8.4-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.3-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-nginx?label=serversideup%2Fphp%3A8.3-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.2-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-nginx?label=serversideup%2Fphp%3A8.2-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.1-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-nginx?label=serversideup%2Fphp%3A8.1-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.0-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-nginx?label=serversideup%2Fphp%3A8.0-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-nginx&page=1&ordering=-name) [![serversideup/php:7.4-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-nginx?label=serversideup%2Fphp%3A7.4-fpm-nginx){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-nginx&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:8.4-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.4-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.3-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.3-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.2-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.2-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.1-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.1-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.0-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.0-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:7.4-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-nginx-alpine?label=serversideup%2Fphp%3A7.4-fpm-nginx-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-nginx-alpine&page=1&ordering=-name) | -| frankenphp | **Debian Based** [![serversideup/php:8.4-frankenphp](https://img.shields.io/docker/image-size/serversideup/php/8.4-frankenphp?label=serversideup%2Fphp%3A8.4-frankenphp){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-frankenphp&page=1&ordering=-name) [![serversideup/php:8.3-frankenphp](https://img.shields.io/docker/image-size/serversideup/php/8.3-frankenphp?label=serversideup%2Fphp%3A8.3-frankenphp){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-frankenphp&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:8.4-frankenphp-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-frankenphp-alpine?label=serversideup%2Fphp%3A8.4-frankenphp-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-frankenphp-alpine&page=1&ordering=-name) [![serversideup/php:8.3-frankenphp-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-frankenphp-alpine?label=serversideup%2Fphp%3A8.3-frankenphp-alpine){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-frankenphp-alpine&page=1&ordering=-name) | -| unit (deprecated) | **Debian Based** [![serversideup/php:8.4-unit](https://img.shields.io/docker/image-size/serversideup/php/8.4-unit?label=serversideup%2Fphp%3A8.4-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-unit&page=1&ordering=-name) [![serversideup/php:8.3-unit](https://img.shields.io/docker/image-size/serversideup/php/8.3-unit?label=serversideup%2Fphp%3A8.3-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-unit&page=1&ordering=-name) [![serversideup/php:8.2-unit](https://img.shields.io/docker/image-size/serversideup/php/8.2-unit?label=serversideup%2Fphp%3A8.2-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-unit&page=1&ordering=-name) [![serversideup/php:8.1-unit](https://img.shields.io/docker/image-size/serversideup/php/8.1-unit?label=serversideup%2Fphp%3A8.1-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-unit&page=1&ordering=-name) [![serversideup/php:8.0-unit](https://img.shields.io/docker/image-size/serversideup/php/8.0-unit?label=serversideup%2Fphp%3A8.0-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-unit&page=1&ordering=-name) [![serversideup/php:7.4-unit](https://img.shields.io/docker/image-size/serversideup/php/7.4-unit?label=serversideup%2Fphp%3A7.4-unit){.h-5.w-auto}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-unit&page=1&ordering=-name) | +| cli | **Debian Based** [![serversideup/php:8.4-cli](https://img.shields.io/docker/image-size/serversideup/php/8.4-cli?label=serversideup%2Fphp%3A8.4-cli){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-cli&page=1&ordering=-name) [![serversideup/php:8.3-cli](https://img.shields.io/docker/image-size/serversideup/php/8.3-cli?label=serversideup%2Fphp%3A8.3-cli){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-cli&page=1&ordering=-name) [![serversideup/php:8.2-cli](https://img.shields.io/docker/image-size/serversideup/php/8.2-cli?label=serversideup%2Fphp%3A8.2-cli){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-cli&page=1&ordering=-name) [![serversideup/php:8.1-cli](https://img.shields.io/docker/image-size/serversideup/php/8.1-cli?label=serversideup%2Fphp%3A8.1-cli){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-cli&page=1&ordering=-name) [![serversideup/php:8.0-cli](https://img.shields.io/docker/image-size/serversideup/php/8.0-cli?label=serversideup%2Fphp%3A8.0-cli){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-cli&page=1&ordering=-name) [![serversideup/php:7.4-cli](https://img.shields.io/docker/image-size/serversideup/php/7.4-cli?label=serversideup%2Fphp%3A7.4-cli){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-cli&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:8.4-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-cli-alpine?label=serversideup%2Fphp%3A8.4-cli-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-cli-alpine&page=1&ordering=-name) [![serversideup/php:8.3-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-cli-alpine?label=serversideup%2Fphp%3A8.3-cli-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-cli-alpine&page=1&ordering=-name) [![serversideup/php:8.2-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.2-cli-alpine?label=serversideup%2Fphp%3A8.2-cli-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-cli-alpine&page=1&ordering=-name) [![serversideup/php:8.1-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.1-cli-alpine?label=serversideup%2Fphp%3A8.1-cli-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-cli-alpine&page=1&ordering=-name) [![serversideup/php:8.0-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.0-cli-alpine?label=serversideup%2Fphp%3A8.0-cli-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-cli-alpine&page=1&ordering=-name) [![serversideup/php:7.4-cli-alpine](https://img.shields.io/docker/image-size/serversideup/php/7.4-cli-alpine?label=serversideup%2Fphp%3A7.4-cli-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-cli-alpine&page=1&ordering=-name) | +| fpm | **Debian Based** [![serversideup/php:8.4-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm?label=serversideup%2Fphp%3A8.4-fpm){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm&page=1&ordering=-name) [![serversideup/php:8.3-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm?label=serversideup%2Fphp%3A8.3-fpm){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm&page=1&ordering=-name) [![serversideup/php:8.2-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm?label=serversideup%2Fphp%3A8.2-fpm){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm&page=1&ordering=-name) [![serversideup/php:8.1-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm?label=serversideup%2Fphp%3A8.1-fpm){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm&page=1&ordering=-name) [![serversideup/php:8.0-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm?label=serversideup%2Fphp%3A8.0-fpm){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm&page=1&ordering=-name) [![serversideup/php:7.4-fpm](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm?label=serversideup%2Fphp%3A7.4-fpm){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:8.4-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-alpine?label=serversideup%2Fphp%3A8.4-fpm-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.3-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-alpine?label=serversideup%2Fphp%3A8.3-fpm-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.2-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-alpine?label=serversideup%2Fphp%3A8.2-fpm-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.1-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-alpine?label=serversideup%2Fphp%3A8.1-fpm-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.0-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-alpine?label=serversideup%2Fphp%3A8.0-fpm-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-alpine&page=1&ordering=-name) [![serversideup/php:7.4-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-alpine?label=serversideup%2Fphp%3A7.4-fpm-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-alpine&page=1&ordering=-name) | +| fpm-apache | **Debian Based** [![serversideup/php:8.4-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-apache?label=serversideup%2Fphp%3A8.4-fpm-apache){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.3-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-apache?label=serversideup%2Fphp%3A8.3-fpm-apache){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.2-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-apache?label=serversideup%2Fphp%3A8.2-fpm-apache){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.1-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-apache?label=serversideup%2Fphp%3A8.1-fpm-apache){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.0-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-apache?label=serversideup%2Fphp%3A8.0-fpm-apache){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-apache&page=1&ordering=-name) [![serversideup/php:7.4-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-apache?label=serversideup%2Fphp%3A7.4-fpm-apache){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-apache&page=1&ordering=-name) | +| fpm-nginx | **Debian Based** [![serversideup/php:8.4-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-nginx?label=serversideup%2Fphp%3A8.4-fpm-nginx){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.3-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-nginx?label=serversideup%2Fphp%3A8.3-fpm-nginx){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.2-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-nginx?label=serversideup%2Fphp%3A8.2-fpm-nginx){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.1-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-nginx?label=serversideup%2Fphp%3A8.1-fpm-nginx){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.0-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-nginx?label=serversideup%2Fphp%3A8.0-fpm-nginx){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-nginx&page=1&ordering=-name) [![serversideup/php:7.4-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-nginx?label=serversideup%2Fphp%3A7.4-fpm-nginx){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-nginx&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:8.4-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.4-fpm-nginx-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.3-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.3-fpm-nginx-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.2-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.2-fpm-nginx-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.1-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.1-fpm-nginx-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.0-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.0-fpm-nginx-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:7.4-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-nginx-alpine?label=serversideup%2Fphp%3A7.4-fpm-nginx-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-nginx-alpine&page=1&ordering=-name) | +| frankenphp | **Debian Based** [![serversideup/php:8.4-frankenphp](https://img.shields.io/docker/image-size/serversideup/php/8.4-frankenphp?label=serversideup%2Fphp%3A8.4-frankenphp){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-frankenphp&page=1&ordering=-name) [![serversideup/php:8.3-frankenphp](https://img.shields.io/docker/image-size/serversideup/php/8.3-frankenphp?label=serversideup%2Fphp%3A8.3-frankenphp){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-frankenphp&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:8.4-frankenphp-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-frankenphp-alpine?label=serversideup%2Fphp%3A8.4-frankenphp-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-frankenphp-alpine&page=1&ordering=-name) [![serversideup/php:8.3-frankenphp-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-frankenphp-alpine?label=serversideup%2Fphp%3A8.3-frankenphp-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-frankenphp-alpine&page=1&ordering=-name) | +| unit (deprecated) | **Debian Based** [![serversideup/php:8.4-unit](https://img.shields.io/docker/image-size/serversideup/php/8.4-unit?label=serversideup%2Fphp%3A8.4-unit){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-unit&page=1&ordering=-name) [![serversideup/php:8.3-unit](https://img.shields.io/docker/image-size/serversideup/php/8.3-unit?label=serversideup%2Fphp%3A8.3-unit){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-unit&page=1&ordering=-name) [![serversideup/php:8.2-unit](https://img.shields.io/docker/image-size/serversideup/php/8.2-unit?label=serversideup%2Fphp%3A8.2-unit){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-unit&page=1&ordering=-name) [![serversideup/php:8.1-unit](https://img.shields.io/docker/image-size/serversideup/php/8.1-unit?label=serversideup%2Fphp%3A8.1-unit){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-unit&page=1&ordering=-name) [![serversideup/php:8.0-unit](https://img.shields.io/docker/image-size/serversideup/php/8.0-unit?label=serversideup%2Fphp%3A8.0-unit){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-unit&page=1&ordering=-name) [![serversideup/php:7.4-unit](https://img.shields.io/docker/image-size/serversideup/php/7.4-unit?label=serversideup%2Fphp%3A7.4-unit){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-unit&page=1&ordering=-name) | ## The full tag schema Our tagging process is quite flexible, and it can become quite complex, but don't worry -- we've spent a ton of time applying sensible defaults to give you the best experience. diff --git a/docs/content/index.md b/docs/content/index.md index 34bf5d857..740f864a1 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -173,23 +173,18 @@ Horizon, queues, tasks, storage linking, migrations - these images handle it all --- :: -::u-page-section{class="dark:bg-gradient-to-b from-neutral-950 to-neutral-900"} - :::u-page-c-t-a - --- - links: - - label: Start building - to: '/docs/getting-started' - trailingIcon: i-lucide-arrow-right - - label: View on GitHub - to: 'https://github.com/nuxt-ui-templates/docs' - target: _blank - variant: subtle - icon: i-simple-icons-github - title: Ready to build an amazing documentation? - description: Join thousands of developers building with Nuxt and Nuxt UI. Get this template and start shipping today. - class: dark:bg-neutral-950 - --- +::u-page-section +#title +Built to run from Dev → Prod - :stars-bg - ::: +#description +Get the full benefits of containerization. Stop using containers in dev only. Works with Kubernetes, Docker Swarm and more. :: + +:get-started + +:testimonials + +:landing-signup + +:follow-along \ No newline at end of file diff --git a/docs/nuxt.config.ts b/docs/nuxt.config.ts index 7bcb79eb2..265d6043b 100644 --- a/docs/nuxt.config.ts +++ b/docs/nuxt.config.ts @@ -81,6 +81,10 @@ export default defineNuxtConfig({ env: process.env.NUXT_SITE_ENV || 'production' }, + plausible: { + apiHost: 'https://a.521dimensions.com' + }, + llms: { domain: 'https://serversideup.net/open-source/docker-php/', title: 'PHP Docker Images (serversideup/php)', diff --git a/docs/public/images/social-image.jpg b/docs/public/images/social-image.jpg new file mode 100644 index 0000000000000000000000000000000000000000..9ad70ff90fafb180541913a1dc6db92d2b1e9912 GIT binary patch literal 229668 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
|<*oCk_I-K2 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

2Sk;#WFnjp9BY8w@y+C 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 z zBv$cgF%u<+TRHZAeNi#gou!{lRyM{~nQea4e&pZsvhnt}iF|?VnV?UnDg-g?wzUOF zwll+g^CX)fc{MDN8`?gxLtl%jb9@Pmu8w*obsWo9Pm~{gQg%UexX9JU zk@ieY=u$3f!J&1=obfJ`ez!=s&y=Lrb7(Exqi%u0ex0O}wC_pC=X1Gr#b&PR#nR4C zicIUtX^uhtqX6DL#+B;fXPR>&!J;T)X7bV19}#d?*t1NYJVFxieoOTd{(QoV=I_fP zBGz0pSIZ|yCUSU&@edJo~EM_mQIovUte}v{>XA>TB25XZWv?{V$+x;)03-H#&mSsD9 zHK0k~F6OMn;^a>u+L9r{Ai1CPFz2hlFxQbKW@|H4bXys9 zk~$it*n7BB`&_nYQ00=I-bFGwV`k6E^C$ONC#jvA6G;^inE&$cESLP(FY#~lYJcAk z{ZCA>^!Fe5KX5GmV=n!FgiHT_{#gHKuND4}Y|j6f1^Mqa4S(7t=ag6RpVTGr>8F;A@f*k6RrHG8lf8rc5p7DwWr6sB&1O@D)T zzOD)F2khnW)*++MxLbgrC=(TooNzy9hVIf&jNb=EQ5y6^OW=pL;x&v9mn%;03svoC zGHjR>8-CCwpReP|(RG%~(AUu|_SlEkPBRrsYgCn3GR@iF@rnI#`oP=~|KuLFS&KWd zi}}e#)MWqbEd5}GflRjMF}vdRmfdmtEEL$YdYgb(fgAmRE$tcU@1=Nub-1T7Q^)CG zga;Av*${eNwbS{@h~|ZCg_0e`*8Kj|Y9ZmC&#CY#=js2P&Hl&o{qHSb!5PqMzA{nE z%31bcThW>NG;=YP)%LOLCJN0T#*(9!QS>I2^uh`636GgYg@QuDFW2kqUk_jQ+fsjw zEf3jn_U=+n%8TB6z>0ngmP)~&0JzeZrd~hQG=A~Z`Ye}YR#Rjvl=HsgSUUdtzALMo zJs}r@Y(mn_M)Jy4>|I7@AL4rFY=45q+T>oK*g~?8n6K>Ro*%icl5{5P!s^}r!@Y+L z51HOI_PRy$JI|^ZD@y1%d+u%&UIue)PoRab2}0Bkum(_T`nkKQ92~6Bgt?0f5?-bT zWu_eL3cD7W?%YvjB>~6tu6MJ?an9GVB)LcX4|^%D$iFqtDr>Fr(NCyLdm+0OebXx4 zTazA=gh~w%*Y4X_i1PD%Q2HA)afA;7g|zVtDm_qTeArr zLK(~z;b1o?AwkQDEdA(w_?dQGLLSqHDbK21us6hoyQU@vBr+Rax|mws#lqn-e#con z+R)mTn0jabsllZx!w)9t`lLQOdT6<@wx*`GKK(*NU2R>%$>rs$rztWA&Lz3Niw?EVPqsNNknnx%#Ry#hLN*Cx0 z-|1pjoM(@FTbT$YCln{sSYL+PnH59XYm29=eE}2~n|O@GqIInWEhwf9fwd?#<&#P<=TPyy8`O+;E|>S&Xam1=Em!dWr}8cU9xmHgt_nI0V#8yHv- z+?0{8Z8kMM{dKG+F7s^tP*j?GLnL)b7a2mDbFzT8Qt`%p%-_PVV0fg=s@uhnnUWPE zbv2K#>}%0L5W7x?hdc{%uej50^CWyvnLBUl;g>dhJbHc}V9yc$1 z_*pVbBY~y!07?I|Q%Kq=Ux9qJ@!bxqhl&q1SqJ*$Dy6+I`J|LO8(jqjIgLJ?Bi>{4 z*Z-PC_n*6KegK42UPCAbva^2@!!k~Xh#WlZI@f=fDn&V}{BhIvR*MphJ%+UtuWsw*+QWft1YTo{txxZTUI%Qw_k#3(wmxfo>(N}`) zwJJPqD$&0Kg*7x?MfLmgC(;(u8LvN17CMn(i=ty=zqeW0iKJ*ueB1ATr@<1t>OFR6 z)w?$LSuihJOpzLvly>cI>_}mieGFCuP|a({5I?>i+dhB9*7BSS|9xBM%A(xKZkIdm zp5t*LL$BUEELsk>#%h(#Q$pEOZSj(;Rk|9WN$$b9%xgTNeU`$gypUp;k%eX5xnC-} zuIPPJ^{YQARTc9XL7ey&@z#@!TB7W!09VKT=r$~{-}{k*OH22 zoScQt+-${M4UAbgCoX*N-$Gjyx|uFn%X_STn$Z2~e@JN{Jm0MGbpUKOJZq`s>Tr$v z8wJZIb`}^Pp87BgJb_@zi(*Lo!(Lt%fILZU`byZVL(Nyzj6WrPS!R93)LpcYx_8kc zD~QQ&NKYq?g{K;YbozXub!V&eabG-wz6$CYVgbzo3oGF`zE~W0oEgY#=PN@(w6J6uU&-8W z-7L+py7a(v#EzIf?;?3&bT_jnCfBdGA|Ie2XTY}6ung*z+n=+?lJLkaS6Jg{!+S2i z=?&Kyv@&h9YqM68kh_UQeyh=Vo$>`QU8K*Dk?vlygW!#)a1Y&AhAlGn!E51A@Zqn~ z#$&Yt@frM10u<84l{V+}z(<&bjBI0+AS#e52(KQ0$wu7-ZxcjShN<)d9d>k*QLHOv z0B?Ydqynq z=;-B0v~TJBQ=< zeVqZg-oz}{EyhYxi{#4zi@lZfIJOPjO3A9C#22g4xv7#<_@zZ+fD&A_;CXxDRadFr zz26sdtICABLG}7fHT+A?@>}r8v{AkkYFR7_ig1Np**RUg?)0!-Tml?7ryJ`6+dak6 z-2)3|ZQz6(EX)qrrGqclm|zQP-|bSjxhNMZ$Lq(H(}DqD8WUfDBisSS8JU`5sQ9031^-fenBRP!oIPV&VS%Y z$C|t%$&IOAj>j}5=VBa`&MV9+q8RBUGIePkJS+!x0M%zLxZ*ip1zKrEr!O*O;812K zJG&Xxk&ow|svlk_?A(WQwNNlTsdxq|NiW9@Kelj_MD6k<_kE^b9C{?UL>M>ci`@c` zmlr>a+|JeCItDurF&bK{6G^)bG4M&g;=*j5$z84wGvB|9uiTV^Il(qgV1{kuTEgip zQQ)u ztQwHL-{Kx&`_FY`(pHiIRiDN2>Z8oy7A>w2+cpL7!6b;_@=m9+;$%;-t8(sINHY-9 zxcJa(+79F)qf5~8Y?6A*t;nRYA@}AXov>D`-*|}x#wZEaBrK0X+N}WaL?EuTY{Tz@ zeb^?}wcr$Z-C~BD>of~Xvj}GJoaNOA@IFPb7juPPo%~=t$ZXm{`tv>g)D;V(*yllG zZZY5T{9~WZ25-2ZM}lH)n#2ccyl1V+Z_yau9aKS+B=IXIq8fW%E^PQ-K8SQ2^ zf!>oT%gb~bWzX*VgQw5v#`m*IlhR;maE-X#3D+3eRi@C z4D5k;Enlvh-4L@*(hGkWvZf|PhV2mT5i^Fr#4E#bvUj+skj*Sg?laQF-OYS{MVV1w zDQ??_{t^Il>;Rj%%>l)DN~mqg+H&HWWip~^ge2dCHBBQ{a-@tIGq!sY-j;1^SNEp5 z#;iYaP5)=E6`T-W64Vf#8#k=rR6G|AJuw>&4X6m-w@S}>kG&|k0dTt_rCa(vTL1&z zR)MPBxXD-JszUuYsX>S&UnBSkw81(H)_ErGD(*#Bhp!U+crIPE-OUBAIMtBtb7|Bo zZ^!PC?3m(jkE?=zKxbaQp$vV~E&WaKPhfs-hk>iU{$YkPVa-z7ls?F=2(OV6Ny70v z7EN-~Nq6`f+*tM%Dl=WXE3lMNa*!$y4xEd_|#FKQsq#36IoZv zm1y8J^0H9pXMxb$8BD4|4ox^-fIobOIAd*)N5wgsCi_=GlaO zgLngGKEfI*DORru_pe;ceVCircklNgPv3?YAsn;FRuy+(djUZ7_RsM%RLEX`I}XjN z?wSfq#O&tphAVu@P#X6PEX|@y;40`Ua_mH2`Uw9qvtMQc*V9HoP&|ryE030j5KoSP zfl_FMK26uF(|j&XxlxAJ7M~)zXD5I^(Qua#jL0Af5dv3;?{&M<`NnuB2u14`sl4ay z7%Ki6G`9xND7>V!c%A!{Z#X5qF5NObe{$UOD`&$*zuxrmO(71ryigeaG8DM<=7+>_ zn-zhPN&5L)Q38!5P7z|FQVI@}cTCQ@WVRuNxh7FiAmfh0Gq=;v4BoPO?U5-3YHR^Q z?c=EGU0*iuWqkTZ8UGa}0ysXYurb)Wc3Y?UeWco)WpgM34QsRXiL-Uz$bQAJESkiU zsrF;#3!-0B*w!t@tZEexG^2lsfPe$(_3`3kMxhrzPx*{Q$?K}VdO2X&9N2DFK>FSL z<~6VpoL69z3cd({cx@-c9z|S0xr&8ySeQ28$2frAgk-C|+#PI8D&C_A7W5q*_xe(= zVphY>ycLgx6Ku(&M!UYoT%v{+EvP8wxaOb-uSCUKV%!HKx85TbRNGK5sj1XZBy1$b zIRzVSnd5(f0N6PgmDbdCtBxdwb^dClG(av=$=mY5RXDR{YG2?cKlkd_@ep*r$Us!+ zaqpJgZ^wm*Ydw$lCC%@iwBN>U0|R@Cz?cCHeF(1P7*i#Uy)tJ9o3oEImcLaM<6_%q z%wP#tzcenphuNQOR4ZMd=0DeL&^aRr$G$jsZn3Gzp*V=YcQEn;mfl|`s%-8$To;G& z8i?$Hc7oAH!zN*T5u+_P{#)vH)MfOoCVg6%Jl>4=)WTKvN2kI$N_6=o-ZpWFb%_df zog3rY7J0*t7N{azAYHaVW{m63vUKIT92ufWmv}F*W@1Ma&Ik;G)eFc&+FnzkGYD8+ zqb-dvsW`U_vxBe2RUi)=rfYN-n7}{JfrG7Nidj%pJ>wPZxtl%nU@lXDYc^IH*&OKE zlwkdmEt6inSfG;T+B9VN!OLZET^Vaz+akb~2Z_^vM5})rpZ@K)|EXy8r2FPDA<^$w z6$4B>q5SBt$X+5>dY11LODAw_D8OGX56sl&hHerFZhg^PTlh6Mca9eI}Y#nDOozR}TN zkoiam6E-fzc>r%?WR6F(0L~5=#b-aLUm1lc2;^DPk&+h30I0mh6s~q13BwCUvHEvS z!I`v%(a9&C9kWSzbRoRLbgZw6ErF-(YN7On$*&vPwO_*9)LII!ZrcKWw2;|2q0N9? zy_??^4>sHFJMlxPdQ_{j;_>(V{V)lfmI>5=*&SbERuYVwj}4uHd>>cfGTYxTEz z3#C|S?^4jqXS&s&)EKDy;C^;%Z=#VMw-qs8%NG|1m#dF&MM9^M<0Q@@SZwPMyfKIF z$V@}lqVLwFSq8F9I%kQ4a9Bsde#ntZ^WZA7^d%PK_wq(cfX$SLb51}RZ&@Du)6vWw-FC*yys^g|UXQ9I2ZGYf{}TZ5c2Z^#eEUJGhN;iw10cX$%CL zD~U*DY9Kh6O-G&8n%O_UAXnfvPVqAMS|LsEB!us{S?#B?h3NemGr!#b;B1MabBvps z-@hEvHQM=$0G!81Xz-rmk1)|v@pL2@#Y6z<41k3|PW~im59KH`P4;-ngv0ZRE~uK( zml=8Qu(eD%V?_|B(Xl$!#sRFOs$KQ9QQvD-^0j>Y9u%{(WIGG{5U+UB25ksOOK= z9Z6z@PQ>Mt^*atCS_!c323H!8U=M6zz}ssP0?^}W96vapy)kFfft)C1MYp}yiQk96 z0TZI00!0_AZ7?{FS+;aX7hkr1YW7K;b%Hcj66-7bz#UVg8nU6OS7C~MgE74s4}z?= zn0O7YH4HZ74nTR-re#Z~D&Z?w)c$u$P2@_ z%cXAy0@=trK(E$2ctvAko-%M*MJhCU0I;9 zFo>Cu+?bH>!IDmq%eKyghFepQF1;RF_B|*>xIc%_v1KQOzk^l&*HDu-br zD>iJxZL8f%mtDm#uE15d7aLVw8*&(nS`IvSKhE8I*vL_4*0DLqXZVU~3@FQ5!Py}vnT+rYbh zW!)>!+GO|F(YIS#_*3s^V&CqY&Ssa?5(0|NPo7mTj1Vij5G=iOM^|V68X7*V!5lWh zd>QhF2~5ny?~S~7IV#c1yx=&*Z}&rk@l(>+Ke#WamR(=S9=yG_ZG`_}R;oo8uL+j- zF@oQ6G!v0w5e03zj8Ig!bYM(J%*IWl-avZHvlfw2Rkj514IMn*ztGjMid4q9k>4+^ z%Q+6qG(E6v$%>wDi{aGXw4Ng<;NHw3x$=to8GI8Q$rnzX^Jh+3qh-0jj)X-~rMiFI z?Pn7eF-R%>#iEo$dA||yPTjH;J?7MRA3LMbfHgtVe?1^Z2_UUfR%HGSsO+9?a4EQN7O#%P;eylgLHzJ+-Ie^R-WNDQH#jktk(uzI7ATyz^(XyN zAOgS)rJgCJNu5ZEph+`aH-Bd4xKh(fN>uE;uI0zRR^&LQvmf{b(k+sNw#Os^P{AQ~ zsvLw=-rNAkc4CXn7zNEpcX54Bu0ZdAi#Yd2*5cx6j$t;rlUt_-*VkXyL!6SHi0z(< zCC@hvm-l-Idcpy@X1>xz-G6H;W+ESiHM?tk5sUx!~e1BtBu^Ok5aBn&Qxnq85V&K4jcHnKY_OfDoE;`A=3rwQi2v>u(_HtzH?fGHD z@hF1WqGxtu`3FzOJr%_vIRk&z?9bE^2;>7FVmE(3_dFO*6g4#8Va`3x!j&x^Cq$># z%@7&Ofh_T2LiK_Kj6F8OHF*)_mhCxOw>lf*W~P7l%6h^xJEIS?oY0RN_OG&c8unnd zPa{@4{t;RHe}Ga@Kt3RwBpmzF8UnN1A*{9#yhADMvWN#f=b8$~T04BI;Sdww zrAD7)pRR;{dw0kq+cBkZmt)A;1zTa8$d|5v)||@>OnNpPNA?V{BXy#j`o-X}_Lc3> z1nQ@YrUk0K-wO=8acR=o=L3)Wmu4|u#qVung`9`hpAQz8OE}g0Cw^-4lfE2)>qaAv zRX$}AJT~2`im{WS*|miWG4Zv}LfqINz5>3d*wC`C4V?Sw1KtxDkGDouBb16&TSLjW ziW#oS)f@w%yKSH4Jmr>lXo~@nr}EBvMfrqk2dTvNGr1J4_dsRrt6Qm2WuViwyV>Qn zd_v8i@hGiM*0t%OpVI)@k907T{b*ObLOnw9PPOA?F<_9A5Q+NYmM|FkeCQ5q?V*dI z_Om&QOD({LIj1TVl$QkM#(l1;Trf7X$trE#aNjH_jSllG9iKX3;t+l#Hfq1y=zE(Z zH%jiQ9_=|O-ILyR{?)X)D)Q0X!Ny(Uk`F6bHI38OI(kxKHX^H4$?aqLW`@B>v07Og za@HY}CUjzfb8kw?x|qS z()+shT7}nb>7#Zh)u{u{it*^^Lr(4tAZytQma??4t;y^OOmDisCJxZ|D~b} zfiD{`g<~TQ7lwciCjMjZIGWX7_zkfaXK;i*KjG^^^SET4^6u)@%9j!Eu0Afgk=pJ; z8>;|4tq=D)Ac>zknEBqi9`^R>A*p({n+9ufO#DWospJdMXJNQKDzLhl4H6Vj(dD^e+up}e%D%th|+0i>l>OHu2ssMyO(U*LC`=pk|ur#cvPVRGbgo~ zWAqP-d=Xc0ir?muP?u4u1aU+7a@|VuX4MLPaan!yGu8`7?saj10^3Omz80j`SJ<)Z z_b`hJHi@i?WueorgE+yQ-GDidA^0837c~JEZy3%4pH~`SOK1uWYl5Tw0S60<0fG~d zm14{$QfxKSUg(h*^A&pN*F9%b@J9iMu6&W9l>)R}+?UR%5~R0?y}xW>P_o#x{G>r) zqN)CMod6H{qZd-h31`qnsGX-HZeyUcVX%5vTNr$Rl-wfb*?iQcw90foxXvEZcb z^}&_xMLpwRc70Mm%BMilD!IUm#xK zw9r}>m@p?WizybMJina)A7UpkoGP{s*>0h6QY@49UL>m_v2q@s(x(}KLGRFf>H!lv zTx|Eu3b$x`Vei5BXX!1%uj>yUXHG<7XT{N1S1PPZg$Hk<)Ic$6wtgjz$|yqC=X9Z_ zq&j_-z!0i$u{M$od#aGF!K@=(k5C3`C&*FeqV8CzG8Myi_dfd~=+5tgI0>a)vCoe( zc{{}1UE_|s`XJHR`G#K+v*-x|UmOoDgN{{bkpogAx4}EKS@02rwiDdF5XSC(WM*QE zK6|E!X&&mSi=ru9eNRzuISBP<@MZD#@1qFPL44(ir?zb5F%msy{aa?pOPJ`$mZ`2- zEck^Yzy+^)n?`867H=7{xe5&?{wD@?@kdIqW@EQne&HT~(~3P{*4(k1lWH7CW zCP|^`9q;s!%pkQ+% zGa3vr5P*k0epH^-@PaSkHw^c->ZDl_L`S+g=Qn8O4&IjaX7(p8Y7j5<97ic`Sjwtc zh*29$`+aCde`Rfz<#^$o>WE(CRyyV^#(04tNFy*xNKnK)9k5GMm(tm@9N=dXFT(na z6_DQdfYqn?vSVER4+s__m13Zu0J1FlorI7rA+CYOt@XG|j55F6)n@TT%6W2@r4yLA9#k99!cqpmkrCb%xv% z_SR=I$B0(@V3Q7vNW6MbZgv$zZfV)@gKX#IS>v&YFZBwCXTBW9r8y2;I9A`puLCP0 z1*Y=8g**6360FGR;~-oggU=k8g zPqAauol7m9~z3{@k3=8e8pZGJF zm-93*Na!UdwAft_2Lr6u+4s8Z1ko?KKJRjgiFnJ(FCaf1%hsS3=+{D_y&WT&2}YI903Xx0CT--)UTq>EPRpB{)8 z(8MJRZRUZQSkf+>Dvd8OXjq}^^vx0N{)YYYr;J;A z$=lX)xKg5g@c_2|Qt+0>IX-QcoU?R~ftrftV4=EbH!31>Rtip{+p-ZvL$Cap#SRB1 z0;snh`f=Y30)*~|jbr)3rCY!DKnXxz7@3em z$JBP+vQp=Y!jFG`*dh#eiw8c88R@e9u0yGo{M&Yr!u=b@|7(PK++;zNm|3Am&y7pZ3l)s);O%<5AjSvq>u|vPe`=Y$9OG zVnn3cgc>Rf$>0kkV?<*bI} zlUx>9QoqvRL35rtJ0?&=%)=T{;<6jN(QdVhFnMFm>2KkhQ(}u2ySIPx8?yDdm0TT? z<@Vr=-*2;KCGKgkXs14KD#F-g#sWs9--No(}-Rq`mNc0!Q+8xX_)o7|p6AtLsQ2O;930JKzZ zU@A!^M4AY{-q`Jj$wL#|)L_Hj(7oiggTVe8Jq3Ihz*8~+lTJV;{#@A_F>`qx$k}Lc z@S6m7p>Lq)wXfE;k{f8$^18X>*};J8H|KJ{>z#e93`%emJ3JJ(zz-)0QN&92{ZRSf zpSi?nHAVUApyz`%vaC7(cU`OnLVwZXxNU{Nnr+n2D)Z9)Ai@0%ne2KlF)$+zhjW8<{dw4$`tF1)`({!t6KDzj|9^gYB=L(tnTc<(9D7G$iW7D#pT zp!j8;OU8xlC4Wp|kfBtKBM;3OJ73JuI~CpdORnXJgTJ0LZ&*tE#VbLr?Irvp z-ACJ}lQsUteL1~nU(8*&H5M`g?u(vBgK4CqZ;7;QDuYtiz&p5k*hkuV_F%ri4%gUh zQ)rmz?OQ)Ja7-;=rC_o^bER>ksxPdTF9$zbMoR_z_JZYNPO9}$omjiwNxcC3<=elI z?m+s6MyTO6>;pBK{*sxhUHj6h(#KhKJsOfonmxK1vT4Vye2>uBmLKv2S>2X0jk^m< z+S5M=(`AwZ-pnT+$+HnXE!W>^2enPeL9XOzg`G<^YzE(ze>Pq*uiIt~JN&Mm_gEsP z=9NCJqxATEc^qx-XjO$DoEG2bZ%pgnknn?5>llPcsyDC-4b^DaE>tzPeZ-jY{O@t z!g1zT#5qq#J)r4)a$>zEPjo60oKmP>j_8wPvxsp%^u?Tv?yJl_M>3TfzFBTQM|6Da zWp8J$w>Qb$%+l+Ojnk@2-+`ToD=3`_iVjs{jeBdd&RJtcd#tr)CUaM5P*zUW?P?m!rm^HL<}uA6G`$s~)cXx|U?GzYbqPCxA2ZF?`Pxqafl zU%^N{y=pn2wLf@`m`L^gql-q7$%00FmJ@gs#_yt&#MnAFC|>bL_yE&~QwJOBOTnNI zCq=tEJX8T`j3)&WIhe?*$9314YD#O0*uvC`I*wrf#G3wz=y$zswoY3&F&F<Mwmx{T!$qksts371n9zTmp@L zlBq5|*=ss9<&;v+s~bsoNFf^rK=h^k#(<9|8eT)Lo*UzZcXI?@(}MKL%dO26MRTtI zL>o_p^a7*Ayq~s4Qq{mVpL>6h(%vKE8YTPuQA@UYC+hD*&Cc_s|Dq7=gu|&YXG9gY zLrmOj(LN`q8?Tq>i=)c{c|N-{Gt;@NDm~AU>TzOKRh?%Edm-|jDB^wqnAUm06gd$h zU^sOw(O10qy5arT z0w(^)H`$d_UgY@JrPBX&&ftH*i2l*H_&?u@C?}GGp1e($;;Z)8*o16-U_Mn$8XGE# zt!U47^V6p~2ZROP)z4BdbsQ^D+!8@rX+C;_T)K|>`Mp@P?@IWul{+1u_GQ_{YYs-$ zx8&Tsd@e;PSFcVqx;%K+rbG4P7pj&+-f1n*UUuFkX>!{YoU2wD-#oniP?u(eS=jRR zjLWNjsl%#E`O7PZjKn)#=8oY^-`z9&l7>t{yChIq1@6gm1L;rQz7-c88*wRgzMkiy zVI z?Vj}}4t>Azhcq+0SBgDQGn51M1jGa@bu4UM*~f4wpOC^17DhF=q`LJrJHWTm#{6+By2uS@LiJN++5QU1Bw|VZ3Nlb6?8`>G2Qs`}wMJDTZ;mZNwhZpHn zAcHPdUVv7;>#qn}wh>WyTO8T!sCn+P+>kwC8lcm~Er{J(0)$_R#xj3u5ls>;_^wf%xdrw9(j!;(m(<~Bl zP4NYS7rk1e-^=66-UU`0Uke;R`tCi0@n(GUDNk3=?F~LY+tJku7W=c~@uJEZX`m;s z|5)Xw#A#R|56kGOpMK>njlNs|3zz#LE1YrF-7o@!HkD-NnIlYO8unf4=F)6%U)63J zlSZ-XPSpdUvheM>qYH;eey-(?nvOYt06@rp!4$3JsD>3$%1CxF>1Ohc7CpJx7~amG zZnj3$Kuc*QOPgD-J$<)zY-Gt}t^Co@i)k*1IRQD7>eTFaN-ZA`kLBp-g zcH{ZIX^{eXDu47PpiCM<7k%*XRMN)oFm?sX#{PZ^xk3NF24bySD7$vUd*E$Eb{B}gaFWRRzsQxk~C zAyDUZ{2Pwk1Hfu$b^JQ&n+iAx`FJ0>=hQkXwJ32Nm6-)%FZVSaAUTEuvSf{|b^JaH zAZZt{=nEnR5b&i3?Ex_s9>bH-I}M%!2z!3ARar-!ID_o&-SBI({nk+_kreXkQyQYo zo&oo4$Od|0Urwx}W-=g_Itc&<15w1`83DNw$^R*jGYXyz;LRFn5Zx?T81YTIdm53r zZp3RWXyYQtP4+xVBnHiIcB1m<(6A$6xDttOMXo5G1h<_{`IlJ%S1Ftn;iL#xig2X} z&DX}hCEQbldx~(Q7kXbp?@QFCmZ=0!bky7NUD0 zx)+Nj578kCHIGZfKEe#K~#7F?Y#$p zBUny14~#m4Md%R4Oj@@A|p@_(y!C@Q>t}xb@b)TB)=%2Kb1t z&So;ZDIgP#Mgy&|g*fsP!3m=XaUARKa)?mL5%GC>P6RFX;)x(g;lkVuE}!T|s+EQB z=YY7u*M(So>MnWhetynmDwTeUOT9OjOYQeIy`zMG1c!%zpoa)jP_OT9MA2(J#J5r? zCZaF`MMj0j_kDddn@trKj}n)rrm9w}`n(8P=iy$jf)|GHQvtG39l!STKY|~*WW6AV{d-byC(4ieEh%)*22Dz>_!~i9#J#3XqNo2fom?? zj*mZj8jV_$H!?!2Va%M|z_4Y6h1!COBUS;C2f?~Ajg%56K=N<-y;E~JZI=8k^pQ&Y zIDG6F{7eRMMTA96tb7jir|%ohD4!|jQRFD#_qXh4$ZJHq>A|;C=yvmo-6`U|#)(hd z#WT4(z3E5y;s@~fffB3*YA4>D+jw8zO*OPLofZ(?;O)#H%Nw&}VgRYQhFUsklp#a%$-?);ATOyc|e@bP_o#3%0QTYl#5+pE>o3Es>-=}e|i%nRLjqqe~vfih8>$!dpVOOKb2DG;Gvw!69JLu%?&i>QC{n42IoCyXzCosGS7=cAXqDn zrR6H-C|D3JXunqud1*^NkET|>!|(7i1^>wlcKy{y?XFZC-8lIeBTOI?eL$yuTm|a2%~ThO$ z3OIJ^EJ3^AsWADwd!OUOL^vIwZ=X+?U^#;URYMse7LQgmqdJqu#0J!;sZ4spPp9_; z8J`07hqvMT^!UCLtmcV(cGr&l`99v850Sv^3n&=!fHM;!00NQ;*aHFW=`7OxNdt#e z)WVLng9yS_azo{&iHVcn-A_4GYuWFN?Twbh(F#roI-g&~ZSiJ@v6!_2j#IFFVl^b7 z-#7*$ps939nR;hd%?2@_qaI@HyhTAJo_ScImj8)x`S#rPe9V`NAWm>o-MRAgT_?&1 z{^(YGpB>*ff+c3Je)KQz!z)`X0$if^S(+UqDP4x3!00Al{^AEPPd6 zoGui)y720q+xa)%sHlldU_i70W6^Mtm=@YX8aA4*NJ2AeYMkkFX3DYePGfZ*N-Xem z19?B+d+x$KnvvXabMC%1wIW<01+Jx9Do~lSC{5oNMnbXrdVR5%QZiLuC)XYFI%B@S z6{+=x!aDhfI1{ZVHweAqNErSIy6>X+wzyfpZ~DRi=QeyF9N$x~P_z{NuRG~!-73~W zT=S;lmry-7(NsqHTc8^nk4asBt6?&M5f;zxk*Hb2L!Q`m7!Y7zC=O-a_%C?=|C}-;y-=PGajRC0+B3vuSgdniv`VRI8AJ^8_i>Q=eY;} z>udOdcZ}co3zPUB9p5vJMXyHK=6y5;w>nl_4q4cgW)B4F=BI3|&G9=5LBxcqV5F#b zTDo&JY!h>l!y2}Zb)h$(CJ_k**M^9Ul^8W1mSC2Q`CR+O3gSa^^W`Ce(V}oU2S9`? zi7~24oPBY$x_m-;>~%0$b0 zSM>f2t}xD8;w?4x=0-|v$|m;Ze`4A!za+xq#Vr*a+2I1*hjSh_kM$uf3r}w`O$_Dn zv+DI`qICjGBdBA5b~IiYaw`}@hyrczPL9M=6yP44jZh;QJGWFe8p~lb5nvHk(KftB zxsI0oX)sotc&?(c0*xn{>yzIVx<^L9e5a2kh;Df_OF?u*2B6f0m{7y~rzSivb>Gax zAGsahgX6m@ScaGS*nM=f_sD{^LW5D%%k$d1FOH(bL2^J=Fp`F1#N%q2N2@_?CHJXO zqo7sDLDf*L(zurEc-i(12wHXh+!pZ&)FTUEOsSzRQ{?OL%L!n9W)l%at-QQ4{kQ=5Y0v^~eR0 z0r7|}VJX~^(SWM$C;;w8#1^y3_ld>|?0E%N;GKq0veS907K}#}*s0kC^$=s#vMt4C z&3eNGuEp%pM5>1L1O0pvJ`)wEaH@9-gTd@)im;?@R)v^J`Cidha?bL*5V;~)noDL= zfgD#C+1Japsc?tkt^C`4-%a8At_arjV;|kgTe~mR@PzfWtkw`UFIYoyiz0X!&Pp_z zYA#D)#-1TH;aTs=Q*a!3p$2lpmY60A9$!%^&12J0FZ%ksjKJ`n4Zbzq5`4qm-3-;s z64RAVrwm56=hf*Qs?fx3!0s|4e1315c2L4OioYo|hfbg8`)G=&oy0_@EJ%-(p_kVO zhT>=$;gLYIuP!PDQH7voBLYy(+#+=nauawWfEx2`C;7RWrdQ*==ca~6t3+P>v;nj#)KxCz?!+RZSLedoJMj-TLXlN zDeNRk71Ie#0HaaQPtPk!o0!rtN_wIY@lfUt9e20(ks9+uW!hgEG(QMsi zRCttxL?nKuz&J9Cr8`;gP^6xinm#LBYWAYYf_1}ci@Fh$COf)Xt=Mo&m}r_xrGoPE zJg(io3F)|QTyp`nUbre$BMYC+W|Q}I9-UgNGsY<9rO6v8KRs(=1^-p3sa9x)eS5=& zENwd=G+o4b)mjxz7Y__qGy1Dzk+Egv&8Ev*l2s15&W8Pd=N-B{F=zggYz@z7d398% zX}ierS0DZeb|UeY_N$vr_LMdgwAadyh0d!V-p7DGlH~X)E$m3(Mi6P0ASHps>xan3%bqDtci)RpWy&4Y#4>#gpC6|SToq8nl7En zAoSWH8!-Up#OJ9+PpHKjy3WH#ia=ENH z#p^I(29r6hNY021e7af1_D$>cDn&E;mcr22+eH>r=(K>teC`|^Y3Z~>XSRY%HCAdt zgo&qd^yC=@;_gdK;Mi(8L~YHY56eTT2O1a;H(m`HIv;X${&ZM1)saf=$Xr=3Sz}pW zLq~*$)`<)!ChMKelHUuI72NZMKl=6y*SA%$PJZdXy_#6&`{4`9um{8xhrZAmFZ+Aah`)s0^CT>$+F@$Ax}L#72H5Q&?db_iAlzx@fei^;P2wSMGV<^HsqpsEfx>2VjK>n zRimDpUqnEyVbcGE4uMI{5xz?;yAcfGy5w4;uw^qD40dePg`%kI^G&-B>e#@N#`4ud znP^UbY+!^q7yR5z$~ZSI<;$x2Swc00 zIr!P%{I&x6Z(FSJ@O{6#v(akYC47x6pxiXoKwKQzIbs4Dexn_$vneo%7SQyVKvsRV zDRN;8>%E!OV2W7UGmN$F4HLJM@2FPm6yhf8RW5AYz{J?4$Ot9D&#&=DXVNL%)lD0& zal5?Lj16gN0lR7$8$OC`j#MgRG@7Ky#Fh~^uZ~qXPflGxz;kG=7@DG`0_f?DmDpr# z-BtncBHw;!^512hJnIFj#^t%WG#O`Bo%0|XQZ{5{)vuUyd8DX$#T0r0zn|AH9;(nH zo@Y~Y_*sQ~j^{#?oR)i(({$;Wk3z8*jo7n4-`|r@;fG(fi(FQfn$K`>k#366Xc>1su?eg@v!x!Ut_u>tp0X)6 z@-rjn>O9fd#7~ukt(yROg&K-ZDW=X%V}SwjMaC@~O(B0xet(wQNsdf5gIqpu_(54; zerIW=f>YCTI6b$BLuY1gz3#?qKE8MFR9bi!zM7ARIy!ba-(dl(6VKEK2C#*C+RA6j7>D5CdFa=?3I;e{N$To zttK*Xx$B;buD88PKZ)~o1mAVDwKcSaavUUdPKNM#X|7jG*Tcus@`_%6g<-7ovn8yQ ztNgvL*DilsUa6>tll5;Y10Q2yX$2Q%<}f{9!iBj796fy&bCo8Jotvd8U(S`A^;>Uz z{rpgOXtiF^T&~vA40df>hrjvCQR8o#_?btkI*I`MMFw0pyX1eJ!%G;_)5#L{9>LXTZy9)1;vl;JbS3{ z7{TjI)p13&?tC;|*)xJJT28c3QfHTQj@P)p~ek0B9T(QEVAb-e=CvGYsiKW zih<{}LLsd4yPN#3Dh0Ml4Zlc@H@iZx-x4SrPo!JJ$KyRYPNQZ zrV!z%^JlGDR~#h(RYMaU47BDOS^mm+j3(DxaZKbqAS7g8n;DNg0SXD(T%|QfEBxB4*r01^72{62!bp z0-iV(4TfnZPo7l`;dO9cq18UAplu*Lug&I19Rih@VoSNm<`a*xQm$Zbb`B+KnuWO% z78h5z-k}D=Wr-yqFZUsz&1*)i&>Q(&0RcBznRarTj>QTkr@;_Vt?5(X>R93X7pdVE zDWEl33&mpUH0}OZ|K_KE7vIA1O`F2cfBfIy8b;p#&`ihJfKa)k*-X}OD*R~zxq8YB!80ch!}xy*;q6o5vy)~{(iCs+ zZ?&(_*S_lNOR;r0quylb^EILI=`?KQ`w6-0#b%Qzma`j0K3lMp2)rS49Y+PLErq6t z)e=m|M^zq`islh?MWy-W1WS85HEMG5dLmic>y!qtd< zbwZS9%NiWHv|M@lmDgVKrKcZ%eiGlr@l6TVpMK<*C#X#SlqcWUYM7W;oi|duuIMM?nm~iINFWje$xRf&5YkRTIADdvfLU2k(RN0Y7_*sF&>%{1S!8puBzP@C8`$p^ z&7n?#2o|wkuF!)#8E>Qt*ne`4SZmp&-*jj}@xIjTNFAbT2_x8!Cvx1D3R)+L>8&MD!v<&@X@}zt{SK+(#^E;}mVZC5Yr?Kl3XhB9g(e&b= zEK|eOd97ud#U=h8S?woOg=|tWl`Zi~BTqNyB5{?-Dld`dn}R69EA@_i-wHKXD>Rlu z>NLv@<5f3Wk^!5(_1agy?Bn|%+5ZiL`ESY;#+l~taz!T8^k^0&O;3`lZHs@rrBHVk#t4lh;q*6%`Hxp!0 zrFT@Rgft=3xbE^Tf_xNh`)_aN4uUf8vEo_{FV_!7T(ZE##^!eF&YLf<*=16AeH3GhTL1!UD!)a*_dM*PSMC z`Q;VH`a;1+V*bP}H-N#q@j+4`;nF)AT5M`=X3GYrO$I`gr2T4|h;Q<=Vzjd z5pR`=rOFhR<%+-$W9q1|DPZ*YxDLzo2$#z>%q=dWOs`Tx3|R_KnqSnYa0Bx9wS#>a zC}vT}#ONj78t&^tKETW0@|GJv{>3kT{ruK9L^p(K|8|&$l}}ijp{=Z!-xr zg3t5m?&?;JwW2O|6Wu)pYN#AS;s&8RwryOCbI+eK-YT_#@0zGtv*t1nT-u6?d~BM5 z=yzyaBolWNVQ8W4$!SoSe_!HFEpvTR($G!l7tvTjsGpS;vmN+JMyMl2wV#7*BukVw z_1rw`Er-T3M5gdo(wK`y-fU{%y3i4Ul!&!3vrwj13e`brM3QP_`8~4xX+N*7V>hj2 zOaYr18ROqIfQtU!A}Y&E)KtB=dgs;3`w@*HU&x}^-9@1ja~<`i@`XD;_`(12byE;u zw_ttbzy7P+O0~vqTJ+!R zqgJZn#_j8I-&2#yk_&^K$>jBhN1=&Z%1v|T7FL7BHmqYx8l$AxBWxK>>%u+SD^P$n zos|>kOV~A(LvxAO#5){D6f{r%E??#wV%Iap53z5;QV~seoU%!I;;C^R1Z#OJaP;hW zJ@tA^HIs?8%7%!sv{cf*6;gs$k@e*Bh9JTvfsRmNh9GK!){<}mW@YfWTB9Igx zVd0zHgw?RFCNamDovJF|bj%SlN;FvAW=0gc3Bu!wYIgzX;&Crj7EG^-RIH{i$OY6W zJs4QGMv2m`mtDj4Z(wL>SgD>|vD<{y&@>@6IbW{j(#i^E&d*Sz7EtEY!1u(;w z$#aqGjT%2cs~}Vo`;x#4*Ivw`3OH|q1d=;jIVRp>3Mz=p1flg>MeUeyP5pg+IK?o= z;2Ix;JfCw5O^uVq)KtDnoG>Xk*1W3Vgi(^#qBzh7a+7*gn|>^*C!WUqY+5mYKXl?G zZn<(jmYNmfmOMY3JKoQ!c5718RZ11zSQ-qL!djk(w6)B1^=S7T$#JJ)M>-di)Fk0N zkSEsJq@G%_XvkO5Qqt{akwVv3nd&mHc4)( zjMDNlvF8PPiDv!A$Ho7arDsv)ZsG+?^{xm_OW1aTLD!NoP@*)WH%t0f)kJ`V zpOTVtE<&xogx;QR#c55xUjU>mzB1`tWTgb8LPyP>$>J22*#u|Ps=`CnGHv!cwzx$> zxe&ArDJ?C}DUcN|O~}jA%z11c?IR1lLd}vVwyWtiku2e^ZX`*1vDL7a+B6P=x0+gj zdY(;Vrg>edv~B9a&2(XQ2@%a~_fWqE#Ag?1UNVt-nZ@2-(hhlDM-ir6&d1`+ITT07 z5T%Q}!5(Ur5kfpX*#B7M+=?Fvhu}9;zV0Sh75tX48lUJ{z4v zS~jqPO$v3+f8VXQ-uj_?@4dJ5EeRImNVmt$a3Y%*aOApwOok zB?TNVl;c3Tk)zd_rmz8Pp(#=slPY8Yw}+!g&XCLMM)x{~k{UG0WfAmHudP9Mzm?7r zY?m~rs;|*SQZj?*_Z`Ra^9>w4asr1BJ;RMRL_u26K(U0%7D(HW4M&vCC^i*A&hT?2 zKB%UTjzKeKAU-Q;HK7WsyXQn5P2r! zLpHs*V3C&4HTtG1t*@!IzN%pT@-P3y#K}{Ww~Y)ABh%l5X04^oIyCg+_$J1vx=05| z0N16)=IEvh@LZx>TO;7??d!$L!h&Ljz~hauNp@m3J)aAr;gT>3N;_<$IEEJ^CRZv` z1(;^Jpw+NOFE4G(qb)8lnWKusxWT~Y<4VWp^G_EOY zv^={=UTRVCp{#+Hc_B_rwr4%;P+Ek$TsCR2;=)OBWV>PnCaKYjtoDvgS3)iQk8PJh zc@;I9S5qz42vYCcecNpx+I!baW38_$Sew@j-~Rl`a~K^Rrsi3JuO;V!dNPvhBs)Bx zp-WHU%4!lBNjhq(kS=b$PLHKh)^w6|z6;AsRpbS#M!9iRWlP9M z>f{7BahKGaHN|hSlv%Y>y3k(QsA}!z(`c#I$twFy!6S}oP@{DTa4nH&2qd#2LWW>| zfxtOi$e?#^ABK7fVi#MAt;9={-C4Jpp_Z1k-CjJ+lh;Zj`LAwplj18&XQ(yNLM`n+ zV?s}i$t~7#@W4s@=70Gpo;)&xIGaM&%NyrKOXyRYb&9@mboT|=zGD-1TyX^soPC7e z>jF=yN?}QvV7T>2VRN{ob~3gFB}s7JmiCK(X$pV^;fk>hZCzw+|K2w4nk?y=YlZu% z+6ne`Uc#ek`x39EWN*~urf*jIqS{y2S}!SB58wBZiLPw!HZOjX!XY=GA8T*G+o`6s82CF1pL~Lh{9OY_@RkS#n~9$6gcrh zLYglT0&x=ZRPU)Y%>?mWgMwC+=#i*VDxLr& z0+)E)`Y$aUQ*)`LuHRI%C>vU`DAtXye_tFge8}_qOW%-S6}oe`Qte=Dpul(%Z8rrf zZW1fmblYZVBJR>SHlPb%pg<(acSy!mU*o5FMaE(;+xa_LYR@nynhm zX9oSnKGlj6yp~K*b+yZNWt)4}bkj8~VC|)sp-3+;46U0UE^FvVf~K`vLp`M`wcuR& zJl1X4pnTITvC7HQXHcf_mYW%jj;!Ol9zfH2fNCZ*!@%x#sg{l{S&Bx&okgK(pY58H z=t9S)(%EF7rqtXI}}!l`wa9R^fxtshZ!VDKW+q784|LmZzz^?2=3I-r9}JDCU**{iV?reA8GE5kO`{cP zlu=z+==-z3`m>kRS}!SBXJ<<98%{-<+jDw$jyH-+%pKQN$ZBa-Po6{^%~w~ET0*iL zgb<}U>Lx2JU@`Db`Ff*nn)na)cVlL{LX5=sb>+#IbQ!hH_x4dx1TS@WbrD-+X*x+< zN=qUN$#86%m-$W61Q9-d&)?$uSKfffzp@Vpo;ijauf9xgsyGqPJ$F!>&Gz*TV5ybH zm%jXa6gbfq40V)iCVLfSyy+dc(rgkR$s+s4^oDhVHzJ#9VG>Vh5(86IA?&u8FahWi zj*(cTXSJ1TULsz}>WG^R`11OnB*P!p4PcLxBtexDi-+9(ix~r)LthU;xi}<#XthOK zs4gx&dr?7)(>8MMS%HsrbB5N0>pNrv_%@j__N<9@vDa8No|t^;Uti$;&F533YKrLV zFVZp;ux;yBtXn^d9hYq;W1pi81n>KX1najx`m48{n_HY1+b~MEyo{4mvkau>u%=i* z|6s3n$;(kC_fyD*dV1(_G%z(c$M{lKZUqMUnj(cn`VHjs3?Gol6P$JBH7{e_u1jx# z^huZ4;vBu5CQYdXL+gYVUM-FJlXRgEA13g9n!HV)YMps{kqhKiPM$u2H@x-jxc`yo z@aa!KivRJkztaxNIr2Yw3F&an8qFgVw5n}U#Ltx*&j^4JqFyzN{ZG*A8tA5*UDfbY z*sR-pdSm`#V!KRA2rhb{K~Vv#6r4(~lW5`YLRJek(!NRJyXKl*$~PT4e2nb3bQsJ^ ztsAy&S&#h>9wcn=R2#NaY-|AC;v-2TF7)NCu93K3w!{2gBv2Q7r?A4I<^84=qL@LG zi6M@NnUtZXk`zNaB6k`E- z6%qWDX?wVKbPb9<13Za7T+K*jQ~8s?c1?-&gd&DhrY_9j$kT__yNKxj&(F-_^qDCP zjEvx^=bq>5=pOU2M8TQn-=xbP)g4}c%bW0tKmU81Qk)@P0LF*A$v6*S|5Ha$t>;aB z9-W0Uor4mE&z0nRQD7m2$y^r?$Apc1OifMW)mL7MbBB+bPz@J6llK%ON-LypVzrIy zhVb%huD~cY?RD4gRBh7B#qQ}U*a~hR!^4AgK9;pbWkfT0lGjw_x_s*M4`R*Qer}Q` zK39kp@WvG@1F?Y!uK!ic>pD$y`SPvTP&1kS@iGvB%$?PUwy?uy(6rxusuJUBQd^v(TfJlx`!z#E zgRW^V{#wkDr_rzp1z13ICO?8e`XCT||J9#=F6l5F6NjZqIlT5YufjoUh7(5_rjcG5 zN^Gj3LEAw1ZLHv>Y-*0_`M_WlmP%E{OMMw)Lpl#>YP#3mxC`SWL&S_RZrHUG>&Aw) zqf8;MaVHaC7kwf$iwb%gL6gKHwZtMB@BaQFT)J_b8^Xh7>));rqDFJMc6b<{{M?uD z_xB&enbR}8IlkgUffK%OoSb9xi?|_2e3_Dnqh#KOcHWMu7tEwh*?bSZ-3;N!<}DM9 z_l=>yCyQ;{))8j(Xll^V(2(+hLdo%>#3upy%7@ zZDgpf*d{*83fm4nu`2@cr3N9~y>RZniT?4MC%>v-&CRd8U$PEIx_Xg|GAOS!@x;?# z!QoRgID4J~waf@QS>SncGU8^hFicP;1Kfyh4|H{>(;8qEbs!|C!9bF))gA-lQ)M4| z_NZ}nLlga1ToAV#{KG!ycBy1!-gMKAIQ0Bc@?)WGd88c_U=x0=TJV&v5YH+W@5cZP z1;t@T%vl{*U9t|Zf5j$TL&9|Znlbcrr%chOR^&lFJPA3)O)sg`?xES2kc`qB+W4(b zj;zQ{k>xrp6K@uYLrJU9dtF&t;@|pk(~Z|)_wH9v}r5G*7c#l^&g{9Zdgyj8R*4epO`0dSzV!G!iJdZz|%rqL*zLsE!ZsoQW7)_Q?p zt<;)tAM7cjRc$B}UT5s6#W2AC{Mg6%>Os{YCePi}_SNcXZQd_>(X#}j?CD0`^aqei zTrYOKh%0w8Dp-HhoOReFH%kWlwx79iXY4{q@q&k|sZIXJAAC$TMohBR_0MtwWj+)d z!ZF;9sfscEv?5}*7JleWyK&pCucXJDReD6tq!{_oWFAQMN*BSZ6qe@FSq&9Q-znFN zK|&>Q-4?v^>!c!SiGpM@KuMeOM?sRhVyc{7AFIH6D(&n@W!Qbgo5U`> z(7psi%y}KHu&vr29qY$>;=RWo+sBKOM7>s0)5~!wNO2aqCNw3;GNJ2QRS+$;ouOx>hg-+qk)!g z0LFydu7*fR%XG3*X6=mk>cy5hkCCi>N<7*St2|7%p0P{aO+GnU{q~*kR<|Q}|8|+b zE(=$>HCNBwzdJwv>b);2Sm(~I+_rI`hJh{*Rm+J8crRC%srIWNq)=vD)k+*E)gWd! zG;Gk=86^`yHd@2$aD!o8@b+$qEx)7EZ-uIJAI1_`l-i`pXRdzyt29>1D%=< z+QMZDNy+-7hN~~1z_0wuKgX+Yx&i?MyisM=^sq`v1b|wJB;`CqEyDwY7$8ga5{BnKUj-TbllMFop+@--*tON_v$F_`T^J|*BUg{hemJ-7kP%*}R$7v%M3 zWSd-}_5yV#PZ!p_&bR7WMa@sB7Dpf_i;!p>FJ85fmTFPP_~zHX1`j>-fL5RQo~t4B zJ6ZuD8HN;7QwN6`8Q2d|OO`5zs7VqCn6a&_qgLJIx3{MM77S zg`t6MMjS|XCRIIlL8ag$+fBxwxJvL=HrJ)O`V~eFL{lvjclJ_91>8z}u(z)V)mg6V zFnPZMNnbif5+AMe{R4$=tqBZNE~e-@M&lPNU+D3a^-0r)rtyT|OFzX$^8y)5_u|aRT?Y4#Fs5&8sfOFZ}Gy`0J1V7rf`k zZ$W>~BX?#_EknL*`ogs4tY4U!)_CFk?2=Y&%T|$W(wy>CG0HT1DTa?Ci>-Vu#ErEJ za!VehP8Q}D72M|-Es*t*Vu$(pdAY4vuB>PrRn}0tzeveH)LU$7Y&DeL3resuI8Udb zwL*a-5mqOKA=#+L0)$q(*oWsHfGzET8RY>x5~KYZy}4o;>_fDid+0<9UxORQgn9

7@VMJqqg**eyWb>sXjCgkv7HW}4ljgUQ5@Xo& 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�Y;16%kw0 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 literal 0 HcmV?d00001 diff --git a/docs/public/images/testimonials/ziga-zajc.png b/docs/public/images/testimonials/ziga-zajc.png new file mode 100644 index 0000000000000000000000000000000000000000..1586c8ba4a8d860d9fed4fe2b4e04d3136ccd4b5 GIT binary patch literal 26483 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 eo8R Date: Thu, 23 Oct 2025 08:32:26 -0500 Subject: [PATCH 092/170] Update GitHub link in app configuration to point to the correct Docker PHP repository for improved user navigation. --- docs/app/app.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/app/app.config.ts b/docs/app/app.config.ts index e81b3495a..99957b4e1 100644 --- a/docs/app/app.config.ts +++ b/docs/app/app.config.ts @@ -163,7 +163,7 @@ export default defineAppConfig({ { icon: 'i-lucide-star', label: 'Star on GitHub', - to: 'https://github.com/serversideup/', + to: 'https://github.com/serversideup/docker-php', target: '_blank' }, { From d48b8b32bac2ff8f27042a64a661aa711becd8df Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 23 Oct 2025 08:40:48 -0500 Subject: [PATCH 093/170] Update Laravel task scheduler, queue, horizon, and reverb documentation to promote Spin Pro for zero-downtime deployments, enhancing clarity and user experience. --- .../docs/3.framework-guides/1.laravel/2.task-scheduler.md | 2 +- docs/content/docs/3.framework-guides/1.laravel/3.queue.md | 4 ++-- docs/content/docs/3.framework-guides/1.laravel/4.horizon.md | 4 ++-- docs/content/docs/3.framework-guides/1.laravel/4.reverb.md | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md b/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md index 65c04d207..7c36a08ea 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md +++ b/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md @@ -10,7 +10,7 @@ Running a Laravel task scheduler with Docker can be a little different from trad ## Important concepts ::tip{to="https://getspin.pro/docs/services/laravel-scheduler" target="_blank"} -If you want the easiest way to get up and running with Laravel Task Scheduler on a VPS using Docker and zero downtime deployments, we recommend using [Spin Pro](https://getspin.pro/docs/services/laravel-scheduler){target="_blank"}. +Want to skip the setup? [Spin Pro](https://getspin.pro/docs/services/laravel-scheduler){target="_blank"} handles Laravel schedulers on your VPS with Docker and zero-downtime deployments—all configured for you. :: 1. If you're using `fpm-apache` or `fpm-nginx`, might need to set the stop signal to `SIGTERM` for a graceful shutdown (see this [PR](https://github.com/serversideup/docker-php/pull/437){target="_blank"} for more details why) diff --git a/docs/content/docs/3.framework-guides/1.laravel/3.queue.md b/docs/content/docs/3.framework-guides/1.laravel/3.queue.md index d93de2674..26548b114 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/3.queue.md +++ b/docs/content/docs/3.framework-guides/1.laravel/3.queue.md @@ -13,8 +13,8 @@ php artisan queue:work --tries=3 ``` ## Important concepts -::tip{to="https://getspin.pro/docs/services/laravel-queues" target="_blank"} -If you want the easiest way to get up and running with Laravel Queues on a VPS using Docker and zero downtime deployments, we recommend using [Spin Pro](https://getspin.pro/docs/services/laravel-queues){target="_blank"}. +::tip{to="https://getspin.pro/docs/services/laravel-scheduler" target="_blank"} +Want to skip the setup? [Spin Pro](https://getspin.pro/docs/services/laravel-scheduler){target="_blank"} handles Laravel schedulers on your VPS with Docker and zero-downtime deployments—all configured for you. :: 1. It's usually best to run the queue as a separate container (but using the same image) 1. If you're using `fpm-apache` or `fpm-nginx`, might need to set the stop signal to `SIGTERM` for a graceful shutdown (see this [PR](https://github.com/serversideup/docker-php/pull/437){target="_blank"} for more details why) diff --git a/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md b/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md index c9d4c0a6d..1cd773482 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md +++ b/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md @@ -13,8 +13,8 @@ php artisan horizon ``` ## Important concepts -::tip{to="https://getspin.pro/docs/services/laravel-horizon" target="_blank"} -If you want the easiest way to get up and running with Laravel Horizon on a VPS using Docker and zero downtime deployments, we recommend using [Spin Pro](https://getspin.pro/docs/services/laravel-horizon){target="_blank"}. +::tip{to="https://getspin.pro/docs/services/laravel-scheduler" target="_blank"} +Want to skip the setup? [Spin Pro](https://getspin.pro/docs/services/laravel-scheduler){target="_blank"} handles Laravel schedulers on your VPS with Docker and zero-downtime deployments—all configured for you. :: 1. In most cases, you probably want to run this as a separate container from your web container 1. If you're using `fpm-apache` or `fpm-nginx`, might need to set the stop signal to `SIGTERM` for a graceful shutdown (see this [PR](https://github.com/serversideup/docker-php/pull/437){target="_blank"} for more details why) diff --git a/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md b/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md index 6e104f873..1c8613928 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md +++ b/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md @@ -13,8 +13,8 @@ php artisan reverb:start ``` ## Important concepts -::tip{to="https://getspin.pro/docs/services/laravel-reverb" target="_blank"} -If you want the easiest way to get up and running with Laravel Reverb on a VPS using Docker and zero downtime deployments, we recommend using [Spin Pro](https://getspin.pro/docs/services/laravel-reverb){target="_blank"}. +::tip{to="https://getspin.pro/docs/services/laravel-scheduler" target="_blank"} +Want to skip the setup? [Spin Pro](https://getspin.pro/docs/services/laravel-scheduler){target="_blank"} handles Laravel schedulers on your VPS with Docker and zero-downtime deployments—all configured for you. :: 1. You will need to follow the [Laravel Reverb setup instructions](https://laravel.com/docs/12.x/reverb) to install the Laravel Reverb package into your Laravel application. 1. In most cases, you probably want to run this as a separate container from your web container From a840bd1d1d6ac03a32913f06ab57817bfe1f3fb7 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 23 Oct 2025 08:58:19 -0500 Subject: [PATCH 094/170] Enhance navigation processing in documentation layout by adding functions to check active paths and manage section expansion. This improves user experience by ensuring relevant sections are expanded based on the current route. --- docs/app/layouts/docs.vue | 53 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 50 insertions(+), 3 deletions(-) diff --git a/docs/app/layouts/docs.vue b/docs/app/layouts/docs.vue index f2d1194e2..7e9b6919d 100644 --- a/docs/app/layouts/docs.vue +++ b/docs/app/layouts/docs.vue @@ -1,12 +1,59 @@ From 2ceda24deec639492a8c68af943d5ebb87c43806 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 23 Oct 2025 09:09:41 -0500 Subject: [PATCH 095/170] Update social media links in documentation components to reflect the rebranding of Twitter to 'X', enhancing consistency across the site. Updated links in About.vue, FollowAlong.vue, and ServerSideUp.vue components, as well as in the About section of the documentation. --- docs/app/components/About.vue | 4 ++-- docs/app/components/FollowAlong.vue | 2 +- docs/app/components/ServerSideUp.vue | 2 +- docs/content/docs/1.getting-started/8.about.md | 3 +++ 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/app/components/About.vue b/docs/app/components/About.vue index 9619ebd8d..19e2931e1 100644 --- a/docs/app/components/About.vue +++ b/docs/app/components/About.vue @@ -3,7 +3,7 @@

Dan Pastori
- + @@ -18,7 +18,7 @@
Jay Rogers
- + diff --git a/docs/app/components/FollowAlong.vue b/docs/app/components/FollowAlong.vue index 7462446aa..d5baa5149 100644 --- a/docs/app/components/FollowAlong.vue +++ b/docs/app/components/FollowAlong.vue @@ -9,7 +9,7 @@
+ :to="'https://x.com/serversideup'" target="_blank">
diff --git a/docs/app/components/ServerSideUp.vue b/docs/app/components/ServerSideUp.vue index 19f17ed60..ed5e65528 100644 --- a/docs/app/components/ServerSideUp.vue +++ b/docs/app/components/ServerSideUp.vue @@ -172,7 +172,7 @@
- - + + + - Twitter + X (Twitter)

From 16285363d5521832169a1e293ff3bfea660ff145 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 23 Oct 2025 09:44:11 -0500 Subject: [PATCH 100/170] Update documentation to change background color from neutral to black for improved visual consistency across multiple sections. --- docs/content/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content/index.md b/docs/content/index.md index 740f864a1..17a62a2ec 100644 --- a/docs/content/index.md +++ b/docs/content/index.md @@ -4,7 +4,7 @@ seo: description: Production-ready PHP Docker images for Laravel, WordPress, and more. --- -::u-page-hero{class="dark:bg-neutral-950"} +::u-page-hero{class="dark:bg-black"} --- orientation: vertical --- @@ -45,7 +45,7 @@ Built upon the official PHP images, our production-ready serversideup/php images --- :: -::u-page-section{class="dark:bg-neutral-950"} +::u-page-section{class="dark:bg-black"} #title These images [give a lot more]{.text-pink-500} than other PHP Docker Images. @@ -159,7 +159,7 @@ These images [give a lot more]{.text-pink-500} than other PHP Docker Images. ::: :: -::u-page-section{class="dark:bg-neutral-950"} +::u-page-section{class="dark:bg-black"} #title Highly optimized for Laravel 💪 From 5e4ebcb01074554498a3b0d0d39e32c6f801046d Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 23 Oct 2025 10:20:20 -0500 Subject: [PATCH 101/170] Add documentation for installing additional PHP extensions in Docker images, including usage examples and best practices for security and performance. This enhances user guidance for customizing their PHP environment. --- .../2.installing-additional-php-extensions.md | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 docs/content/docs/6.customizing-the-image/2.installing-additional-php-extensions.md diff --git a/docs/content/docs/6.customizing-the-image/2.installing-additional-php-extensions.md b/docs/content/docs/6.customizing-the-image/2.installing-additional-php-extensions.md new file mode 100644 index 000000000..093b43af5 --- /dev/null +++ b/docs/content/docs/6.customizing-the-image/2.installing-additional-php-extensions.md @@ -0,0 +1,115 @@ +--- +head.title: 'Installing additional PHP extensions - Docker PHP - Server Side Up' +description: 'Learn how to add any PHP extension that you need for your application.' +layout: docs +title: Installing PHP extensions +--- + +::lead-p +serversideup/php includes the [`install-php-extensions`](https://github.com/mlocati/docker-php-extension-installer){target="_blank"} tool by default. This tool allows you to install almost any PHP module that you'll need. +:: + +## Default extensions +By default, we include a number of PHP extensions to get you up and running. You can learn more why we have certain defaults and what's all included on our default configurations page. + +:u-button{to="/docs/getting-started/default-configurations#default-php-extensions" label="Learn more about default extensions" aria-label="Learn more about default extensions" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## What extensions are supported? +Since we're using `install-php-extensions`, we have a wide support of extensions across many versions of PHP. You can find the full list of supported extensions on the project's README. + +:u-button{to="https://github.com/mlocati/docker-php-extension-installer#supported-php-extensions" label="View the supported extensions" aria-label="View the supported extensions" size="md" color="primary" variant="outline" target="_blank" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## Installing extensions +Once you have your extensions ready for installation, you need to use `root` permissions to install them. In most cases, the best experience is to use a `Dockerfile` to do this while you package your application in a container. + +If you're not familiar with the concept of packaging your application for deployment, we recommend you to read our guide on how to do it. + +:u-button{to="/docs/deployment-and-production/packaging-your-app-for-deployment" label="Learn more about packaging your application for deployment" aria-label="Learn more about packaging your application for deployment" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +### Preparing your Dockerfile +::warning +**Our images are unprivileged by default.** This means you'll need to switch to `root` to do "root things", then switch back to the `www-data` user. This ensures your container image is hardened against security vulnerabilities. +:: + +```dockerfile [Dockerfile] +# Choose our base image +FROM serversideup/php:8.4-fpm-nginx + +# Switch to root so we can do root things +USER root + +# Install the intl and bcmath extensions with root permissions +RUN install-php-extensions intl bcmath + +# Drop back to our unprivileged user +USER www-data +``` + +## Building images with Docker Compose +Here's a simple example with Docker Compose that builds an image with the `intl` and `bcmath` extensions. + +::code-tree{defaultValue="Dockerfile"} + +```dockerfile [Dockerfile] +# Choose our base image +FROM serversideup/php:8.4-fpm-nginx + +# Switch to root so we can do root things +USER root + +# Install the intl and bcmath extensions with root permissions +RUN install-php-extensions intl bcmath + +# Drop back to our unprivileged user +USER www-data +``` + +```yml [compose.yml] +services: + php: + # Use "build" instead of "image" + build: + # Use the Dockerfile in the current directory + context: . + dockerfile: Dockerfile + # Expose localhost:80 to NGINX's port 8080 + ports: + - 80:8080 + # Mount current directory to /var/www/html + volumes: + - ./:/var/www/html +``` + +```php [public/index.php] + +``` +:: + +Once we have our project ready, we can bring our container up with: + +::tip +We use the `--build` flag to tell Docker to rebuild the image from scratch. Good practice in development if you're making changes to your Dockerfile. +:: + +```bash [Terminal] +docker compose up --build +``` + +## Real-life example showing development to production +If you're looking for a more realistic example how this looks from development to production, check out our guide below. + +:u-button{to="/docs/deployment-and-production/development-to-production" label="Learn more about development to production" aria-label="Learn more about development to production" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## Common PHP extensions that you might need +We compiled a list of extensions for you to reference. + +| Extension | Description | Why it's not included by default | +|-----------|-------------|-------------------------------- +[intl](https://www.php.net/manual/en/intro.intl.php){target="_blank"} | Internationalization functions, [used by Laravel for validating emails](https://laravel.com/docs/10.x/validation#rule-email){target="_blank"} with "DNS" or "spoof" validation. | Our tests showed this module will add about 40 MB of space to the Docker image, so we decided to not include it by default. | + +::tip{to="https://github.com/serversideup/docker-php/discussions/new?category=q-a" target="_blank"} +Don't see the extension you need? Having trouble? [Open a discussion on GitHub →](https://github.com/serversideup/docker-php/discussions/new?category=q-a) +:: From 6d78f9b529551a198cab590cceef02eef18ddaf1 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 23 Oct 2025 10:32:35 -0500 Subject: [PATCH 102/170] Add a tip in the documentation encouraging users to support our work by purchasing products or sponsoring us on GitHub. This enhances community engagement and appreciation for our open source efforts. --- docs/content/docs/1.getting-started/8.about.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/content/docs/1.getting-started/8.about.md b/docs/content/docs/1.getting-started/8.about.md index eb9329ee3..a88d67a40 100644 --- a/docs/content/docs/1.getting-started/8.about.md +++ b/docs/content/docs/1.getting-started/8.about.md @@ -11,6 +11,10 @@ We're taking the extra effort to open source as much as we can. Not only could t ::about :: +::tip{to="https://serversideup.net/products/" target="_blank"} +If you appreciate our work, consider supporting us by buying our products or sponsoring us on GitHub. +:: + ## About Us We're [Dan](https://x.com/danpastori){target="_blank"} and [Jay](https://x.com/jaydrogers){target="_blank"} - a two person team with a passion for open source products. We created [Server Side Up](https://serversideup.net){target="_blank"} to help share what we learn. From 8c844c027a335a34e396cbb9c8d415d0d2434519 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 23 Oct 2025 11:08:31 -0500 Subject: [PATCH 103/170] Update documentation for FrankenPHP to include a warning about known performance issues on Alpine, advising users to consider the Debian version for better stability. This enhances user awareness and guides them towards optimal choices for their PHP environment. --- docs/content/docs/1.getting-started/4.choosing-an-image.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/1.getting-started/4.choosing-an-image.md b/docs/content/docs/1.getting-started/4.choosing-an-image.md index ef026a644..2ce8ec862 100644 --- a/docs/content/docs/1.getting-started/4.choosing-an-image.md +++ b/docs/content/docs/1.getting-started/4.choosing-an-image.md @@ -39,7 +39,7 @@ Our most popular tags include: | fpm | **Debian Based** [![serversideup/php:8.4-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm?label=serversideup%2Fphp%3A8.4-fpm){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm&page=1&ordering=-name) [![serversideup/php:8.3-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm?label=serversideup%2Fphp%3A8.3-fpm){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm&page=1&ordering=-name) [![serversideup/php:8.2-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm?label=serversideup%2Fphp%3A8.2-fpm){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm&page=1&ordering=-name) [![serversideup/php:8.1-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm?label=serversideup%2Fphp%3A8.1-fpm){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm&page=1&ordering=-name) [![serversideup/php:8.0-fpm](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm?label=serversideup%2Fphp%3A8.0-fpm){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm&page=1&ordering=-name) [![serversideup/php:7.4-fpm](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm?label=serversideup%2Fphp%3A7.4-fpm){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:8.4-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-alpine?label=serversideup%2Fphp%3A8.4-fpm-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.3-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-alpine?label=serversideup%2Fphp%3A8.3-fpm-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.2-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-alpine?label=serversideup%2Fphp%3A8.2-fpm-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.1-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-alpine?label=serversideup%2Fphp%3A8.1-fpm-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-alpine&page=1&ordering=-name) [![serversideup/php:8.0-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-alpine?label=serversideup%2Fphp%3A8.0-fpm-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-alpine&page=1&ordering=-name) [![serversideup/php:7.4-fpm-alpine](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-alpine?label=serversideup%2Fphp%3A7.4-fpm-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-alpine&page=1&ordering=-name) | | fpm-apache | **Debian Based** [![serversideup/php:8.4-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-apache?label=serversideup%2Fphp%3A8.4-fpm-apache){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.3-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-apache?label=serversideup%2Fphp%3A8.3-fpm-apache){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.2-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-apache?label=serversideup%2Fphp%3A8.2-fpm-apache){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.1-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-apache?label=serversideup%2Fphp%3A8.1-fpm-apache){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-apache&page=1&ordering=-name) [![serversideup/php:8.0-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-apache?label=serversideup%2Fphp%3A8.0-fpm-apache){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-apache&page=1&ordering=-name) [![serversideup/php:7.4-fpm-apache](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-apache?label=serversideup%2Fphp%3A7.4-fpm-apache){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-apache&page=1&ordering=-name) | | fpm-nginx | **Debian Based** [![serversideup/php:8.4-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-nginx?label=serversideup%2Fphp%3A8.4-fpm-nginx){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.3-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-nginx?label=serversideup%2Fphp%3A8.3-fpm-nginx){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.2-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-nginx?label=serversideup%2Fphp%3A8.2-fpm-nginx){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.1-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-nginx?label=serversideup%2Fphp%3A8.1-fpm-nginx){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-nginx&page=1&ordering=-name) [![serversideup/php:8.0-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-nginx?label=serversideup%2Fphp%3A8.0-fpm-nginx){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-nginx&page=1&ordering=-name) [![serversideup/php:7.4-fpm-nginx](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-nginx?label=serversideup%2Fphp%3A7.4-fpm-nginx){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-nginx&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:8.4-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.4-fpm-nginx-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.3-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.3-fpm-nginx-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.2-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.2-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.2-fpm-nginx-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.1-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.1-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.1-fpm-nginx-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:8.0-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.0-fpm-nginx-alpine?label=serversideup%2Fphp%3A8.0-fpm-nginx-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-fpm-nginx-alpine&page=1&ordering=-name) [![serversideup/php:7.4-fpm-nginx-alpine](https://img.shields.io/docker/image-size/serversideup/php/7.4-fpm-nginx-alpine?label=serversideup%2Fphp%3A7.4-fpm-nginx-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-fpm-nginx-alpine&page=1&ordering=-name) | -| frankenphp | **Debian Based** [![serversideup/php:8.4-frankenphp](https://img.shields.io/docker/image-size/serversideup/php/8.4-frankenphp?label=serversideup%2Fphp%3A8.4-frankenphp){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-frankenphp&page=1&ordering=-name) [![serversideup/php:8.3-frankenphp](https://img.shields.io/docker/image-size/serversideup/php/8.3-frankenphp?label=serversideup%2Fphp%3A8.3-frankenphp){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-frankenphp&page=1&ordering=-name)
**Alpine Based** [![serversideup/php:8.4-frankenphp-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-frankenphp-alpine?label=serversideup%2Fphp%3A8.4-frankenphp-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-frankenphp-alpine&page=1&ordering=-name) [![serversideup/php:8.3-frankenphp-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-frankenphp-alpine?label=serversideup%2Fphp%3A8.3-frankenphp-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-frankenphp-alpine&page=1&ordering=-name) | +| frankenphp | **Debian Based** [![serversideup/php:8.4-frankenphp](https://img.shields.io/docker/image-size/serversideup/php/8.4-frankenphp?label=serversideup%2Fphp%3A8.4-frankenphp){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-frankenphp&page=1&ordering=-name) [![serversideup/php:8.3-frankenphp](https://img.shields.io/docker/image-size/serversideup/php/8.3-frankenphp?label=serversideup%2Fphp%3A8.3-frankenphp){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-frankenphp&page=1&ordering=-name)
**Alpine Based**
⚠️ Some users are experiencing [known performance issues](https://frankenphp.dev/docs/known-issues/){target="_blank"} with FrankenPHP on Alpine. Consider using the Debian version.
[![serversideup/php:8.4-frankenphp-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.4-frankenphp-alpine?label=serversideup%2Fphp%3A8.4-frankenphp-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-frankenphp-alpine&page=1&ordering=-name) [![serversideup/php:8.3-frankenphp-alpine](https://img.shields.io/docker/image-size/serversideup/php/8.3-frankenphp-alpine?label=serversideup%2Fphp%3A8.3-frankenphp-alpine){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-frankenphp-alpine&page=1&ordering=-name) | | unit (deprecated) | **Debian Based** [![serversideup/php:8.4-unit](https://img.shields.io/docker/image-size/serversideup/php/8.4-unit?label=serversideup%2Fphp%3A8.4-unit){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.4-unit&page=1&ordering=-name) [![serversideup/php:8.3-unit](https://img.shields.io/docker/image-size/serversideup/php/8.3-unit?label=serversideup%2Fphp%3A8.3-unit){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.3-unit&page=1&ordering=-name) [![serversideup/php:8.2-unit](https://img.shields.io/docker/image-size/serversideup/php/8.2-unit?label=serversideup%2Fphp%3A8.2-unit){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.2-unit&page=1&ordering=-name) [![serversideup/php:8.1-unit](https://img.shields.io/docker/image-size/serversideup/php/8.1-unit?label=serversideup%2Fphp%3A8.1-unit){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.1-unit&page=1&ordering=-name) [![serversideup/php:8.0-unit](https://img.shields.io/docker/image-size/serversideup/php/8.0-unit?label=serversideup%2Fphp%3A8.0-unit){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=8.0-unit&page=1&ordering=-name) [![serversideup/php:7.4-unit](https://img.shields.io/docker/image-size/serversideup/php/7.4-unit?label=serversideup%2Fphp%3A7.4-unit){.h-5.w-auto :zoom=false}](https://hub.docker.com/r/serversideup/php/tags?name=7.4-unit&page=1&ordering=-name) | ## The full tag schema From e0fa43e3e7394da798e5a7dc7bc10e1092090ddc Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 23 Oct 2025 11:11:38 -0500 Subject: [PATCH 104/170] Update documentation for FPM variations to include enhanced tips linking to the Environment Variable Specification. This improves user guidance for environment variable customization across FPM-Apache, FPM-NGINX, and FPM sections. --- docs/content/docs/2.image-variations/fpm-apache.md | 4 ++-- docs/content/docs/2.image-variations/fpm-nginx.md | 4 ++-- docs/content/docs/2.image-variations/fpm.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/content/docs/2.image-variations/fpm-apache.md b/docs/content/docs/2.image-variations/fpm-apache.md index 9ed604cf9..07dfd4184 100644 --- a/docs/content/docs/2.image-variations/fpm-apache.md +++ b/docs/content/docs/2.image-variations/fpm-apache.md @@ -211,7 +211,7 @@ The FPM-Apache variation supports extensive customization through environment va | `SSL_PRIVATE_KEY_FILE` | `/etc/ssl/private/self-signed-web.key` | Path to SSL private key | | `HEALTHCHECK_PATH` | `/healthcheck` | Path for health check endpoint | -::tip +::tip{to="/docs/reference/environment-variable-specification"} For a complete list of available environment variables, see the [Environment Variable Specification →](/docs/reference/environment-variable-specification). :: @@ -230,7 +230,7 @@ For a complete list of available environment variables, see the [Environment Var | `PHP_UPLOAD_MAX_FILE_SIZE` | `100M` | Maximum upload file size | | `PHP_POST_MAX_SIZE` | `100M` | Maximum POST request size | -::tip +::tip{to="/docs/reference/environment-variable-specification"} For a complete list of available environment variables, see the [Environment Variable Specification →](/docs/reference/environment-variable-specification). :: diff --git a/docs/content/docs/2.image-variations/fpm-nginx.md b/docs/content/docs/2.image-variations/fpm-nginx.md index c44bed551..6b5785f37 100644 --- a/docs/content/docs/2.image-variations/fpm-nginx.md +++ b/docs/content/docs/2.image-variations/fpm-nginx.md @@ -215,7 +215,7 @@ The FPM-NGINX variation supports extensive customization through environment var | `SSL_PRIVATE_KEY_FILE` | `/etc/ssl/private/self-signed-web.key` | Path to SSL private key | | `HEALTHCHECK_PATH` | `/healthcheck` | Path for health check endpoint | -::tip +::tip{to="/docs/reference/environment-variable-specification"} For a complete list of available environment variables, see the [Environment Variable Specification →](/docs/reference/environment-variable-specification). :: @@ -275,7 +275,7 @@ services: PHP_OPCACHE_ENABLE: "1" ``` -::note +::note{to="/docs/reference/environment-variable-specification"} These are just examples. Review the [Environment Variable Specification](/docs/reference/environment-variable-specification) for a complete list of available environment variables to match your needs. :: diff --git a/docs/content/docs/2.image-variations/fpm.md b/docs/content/docs/2.image-variations/fpm.md index 802027470..74e6989b4 100644 --- a/docs/content/docs/2.image-variations/fpm.md +++ b/docs/content/docs/2.image-variations/fpm.md @@ -188,7 +188,7 @@ The FPM variation supports extensive customization through environment variables | `PHP_MEMORY_LIMIT` | `256M` | Maximum memory a script can use | | `PHP_MAX_EXECUTION_TIME` | `99` | Maximum time a script can run (seconds) | -::tip +::tip{to="/docs/reference/environment-variable-specification"} For a complete list of available environment variables, see the [Environment Variable Specification →](/docs/reference/environment-variable-specification). :: From 79dc2314e7cc0a945a9496047264fb2d76554faa Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 23 Oct 2025 11:13:06 -0500 Subject: [PATCH 105/170] Update documentation for installing additional PHP extensions to include a direct link to the `install-php-extensions` project. This enhances clarity and provides users with easy access to the full list of supported extensions across PHP versions. --- .../2.installing-additional-php-extensions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/6.customizing-the-image/2.installing-additional-php-extensions.md b/docs/content/docs/6.customizing-the-image/2.installing-additional-php-extensions.md index 093b43af5..3c7517d40 100644 --- a/docs/content/docs/6.customizing-the-image/2.installing-additional-php-extensions.md +++ b/docs/content/docs/6.customizing-the-image/2.installing-additional-php-extensions.md @@ -15,7 +15,7 @@ By default, we include a number of PHP extensions to get you up and running. You :u-button{to="/docs/getting-started/default-configurations#default-php-extensions" label="Learn more about default extensions" aria-label="Learn more about default extensions" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} ## What extensions are supported? -Since we're using `install-php-extensions`, we have a wide support of extensions across many versions of PHP. You can find the full list of supported extensions on the project's README. +Since we're using [`install-php-extensions`](https://github.com/mlocati/docker-php-extension-installer){target="_blank"}, we have a wide support of extensions across many versions of PHP. You can find the full list of supported extensions on the project's README. :u-button{to="https://github.com/mlocati/docker-php-extension-installer#supported-php-extensions" label="View the supported extensions" aria-label="View the supported extensions" size="md" color="primary" variant="outline" target="_blank" trailing-icon="i-lucide-arrow-right" class="font-bold"} From 4dba9d554c5b3624288f1ae1a1ac5914378c12d2 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 23 Oct 2025 11:15:19 -0500 Subject: [PATCH 106/170] Link Unit warning --- docs/content/docs/2.image-variations/unit.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/2.image-variations/unit.md b/docs/content/docs/2.image-variations/unit.md index 20c0917bd..82274e1fa 100644 --- a/docs/content/docs/2.image-variations/unit.md +++ b/docs/content/docs/2.image-variations/unit.md @@ -4,7 +4,7 @@ description: 'Unit was offered as a variation, but the entire project was archiv --- ## Unit was archived by NGINX and is no longer maintained -::caution +::caution{to="https://github.com/nginx/unit?tab=readme-ov-file#nginx-unit" target="_blank"} In October 2025, NGINX stopped supporting NGINX Unit and archived the project. NGINX Unit will eventually be removed from our project. [See the official announcement →](https://github.com/nginx/unit?tab=readme-ov-file#nginx-unit){target="_blank"} :: From 828903906d317cdd6dd56ae39f909c03a480da43 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 23 Oct 2025 11:24:44 -0500 Subject: [PATCH 107/170] Updated reference on entrypoint script --- docs/content/docs/8.reference/2.command-reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/8.reference/2.command-reference.md b/docs/content/docs/8.reference/2.command-reference.md index 71a0cbed0..02263e4db 100644 --- a/docs/content/docs/8.reference/2.command-reference.md +++ b/docs/content/docs/8.reference/2.command-reference.md @@ -33,7 +33,7 @@ docker-php-serversideup-dep-install-debian git ``` ## docker-php-serversideup-entrypoint -For our images that **DO NOT use S6 Overlay**, this is our default entrypoint script. +Our default entrypoint script that is used for all images. ## docker-php-serversideup-install-php-ext-installer This is an internal helper script to shorten up the syntax for the installation of the PHP extension installer. From fdf834250621c99ef09807a1181b64a4c01df2a3 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 24 Oct 2025 09:50:15 -0500 Subject: [PATCH 108/170] Unit archive clarification --- docs/content/docs/2.image-variations/unit.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/2.image-variations/unit.md b/docs/content/docs/2.image-variations/unit.md index 82274e1fa..972ca0fd0 100644 --- a/docs/content/docs/2.image-variations/unit.md +++ b/docs/content/docs/2.image-variations/unit.md @@ -3,7 +3,7 @@ title: Unit description: 'Unit was offered as a variation, but the entire project was archived in October 2025. This variation is no longer supported.' --- -## Unit was archived by NGINX and is no longer maintained +## Unit is no longer maintained by NGINX ::caution{to="https://github.com/nginx/unit?tab=readme-ov-file#nginx-unit" target="_blank"} In October 2025, NGINX stopped supporting NGINX Unit and archived the project. NGINX Unit will eventually be removed from our project. [See the official announcement →](https://github.com/nginx/unit?tab=readme-ov-file#nginx-unit){target="_blank"} :: From 89c44d13a8e8205dbdfe151ac48fdf26e434c543 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 24 Oct 2025 10:08:21 -0500 Subject: [PATCH 109/170] Remove CADDY_GLOBAL_LOG_LEVEL because it doesn't exists. Fixes https://github.com/serversideup/docker-php/issues/573#issuecomment-3439676871 --- .../docs/8.reference/1.environment-variable-specification.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/content/docs/8.reference/1.environment-variable-specification.md b/docs/content/docs/8.reference/1.environment-variable-specification.md index 352fca842..5c6fa2a08 100644 --- a/docs/content/docs/8.reference/1.environment-variable-specification.md +++ b/docs/content/docs/8.reference/1.environment-variable-specification.md @@ -51,7 +51,6 @@ Setting environment variables all depends on what method you're using to run you `CADDY_HTTP_SERVER_ADDRESS`
*Default: "http://"*|Set the server address for HTTP. (
Official docs)|frankenphp `CADDY_HTTPS_SERVER_ADDRESS`
*Default: "https://"*|Set the server address for HTTPS. (Official docs)|frankenphp `CADDY_LOG_FORMAT`
*Default: "console"*|Set the format for the Caddy log. (Official docs)|frankenphp -`CADDY_GLOBAL_LOG_LEVEL`
*Default: "warn"*|Set the global log level for the Caddy server. This can also be changed with `LOG_OUTPUT_LEVEL`, but `CADDY_GLOBAL_LOG_LEVEL` takes precedence. (Official docs)|frankenphp `CADDY_SERVER_LOG_LEVEL`
*Default: "warn"*|Set the server log level for the Caddy server. This can also be changed with `LOG_OUTPUT_LEVEL`, but `CADDY_SERVER_LOG_LEVEL` takes precedence. (Official docs)|frankenphp `CADDY_LOG_OUTPUT`
*Default: "stdout"*|Set the output for the Caddy log. (Official docs)|frankenphp `CADDY_PHP_SERVER_OPTIONS`
*Default: ""*|Set PHP server options for the Caddy server. (Official docs)|frankenphp From c95e4ab3b4d9f9e538a69fde318c1952e1a58f64 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 24 Oct 2025 10:17:45 -0500 Subject: [PATCH 110/170] Enhance migration documentation by removing outdated section on default configurations and adding new sections on testing applications and related resources. This improves clarity and provides users with essential steps for a successful transition to serversideup/php images. --- .../1.migrating-from-official-php-images.md | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/docs/content/docs/5.guide/1.migrating-from-official-php-images.md b/docs/content/docs/5.guide/1.migrating-from-official-php-images.md index cdd616b5f..ce8a897ae 100644 --- a/docs/content/docs/5.guide/1.migrating-from-official-php-images.md +++ b/docs/content/docs/5.guide/1.migrating-from-official-php-images.md @@ -9,11 +9,6 @@ title: Migrating from official PHP images Migrating from the official PHP images to serversideup/php is easy because our images are based on the official PHP images. We just give you a "batteries included" experience that's ready for production. :: -## Understand our default configurations -Before you make the switch, you should understand our default configurations and make sure they line up with your requirements. As always, perform these changes on a test branch and use automated testing to ensure your application is working as expected. - -:u-button{to="/docs/getting-started/default-configurations" label="Learn more about our default configurations" aria-label="Learn more about our default configurations" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} - ## Key differences ::warning Because our images run as `www-data` by default, you may need to update file permissions for mounted volumes. @@ -46,7 +41,7 @@ Making the change will literally take you two seconds. ::steps{level="4"} #### Figure out which image you'd like to use -Review our [choosing an image](/docs/getting-started/choosing-an-image) guide to help you decide which image you'd like to use. +Review our [choosing an image](/docs/getting-started/choosing-an-image) guide to help you decide which image you'd like to use. Also, make sure our [default configurations](/docs/getting-started/default-configurations) satisfy your requirements. #### Update your `Dockerfile` or `docker-compose.yml` file :::tip @@ -86,4 +81,17 @@ services: ``` ::: -:: \ No newline at end of file +#### Test your application +Make sure to test your application to ensure it's working as expected. + +#### Deploy and enjoy! +Making the change is that simple. + +:: + +## Related resources +If you need to customize the base image, review our guides below: + +- [Changing common PHP settings](/docs/customizing-the-image/changing-common-php-settings) +- [Installing additional PHP extensions](/docs/customizing-the-image/installing-additional-php-extensions) +- [Startup scripts](/docs/customizing-the-image/adding-your-own-start-up-scripts) \ No newline at end of file From 96a1132e5427940184428dbb42b127b8513d0295 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 28 Oct 2025 10:47:07 -0500 Subject: [PATCH 111/170] Fix typos in documentation: correct "confiugration" to "configuration" in .env.example and "ouput" to "output" in automations.md. This improves clarity and accuracy for users. --- docs/.env.example | 2 +- docs/content/docs/3.framework-guides/1.laravel/1.automations.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/.env.example b/docs/.env.example index 5b2ecd5c3..20f5b43aa 100644 --- a/docs/.env.example +++ b/docs/.env.example @@ -3,7 +3,7 @@ NUXT_SITE_URL=https://localhost:3000 NUXT_SITE_NAME="Docker PHP - Server Side Up" NUXT_SITE_ENV="development" -# Used for Nuxt App confiugration +# Used for Nuxt App configuration PLAUSIBLE_ENABLED=false BASE_PATH=http://localhost:3000/open-source/docker-php NUXT_APP_BASE_URL=/open-source/docker-php diff --git a/docs/content/docs/3.framework-guides/1.laravel/1.automations.md b/docs/content/docs/3.framework-guides/1.laravel/1.automations.md index 0dc20ed8a..e130c75a8 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/1.automations.md +++ b/docs/content/docs/3.framework-guides/1.laravel/1.automations.md @@ -151,7 +151,7 @@ In most cases, this is due to a bug in their application code that causes a migr If a failure occurs in the Laravel Automations script, it will exit with a non-zero exit code -- preventing the container from starting. :: -If you are experiencing issues, you can enable the `AUTORUN_DEBUG` environment variable to get more detailed ouput of what could be going wrong. +If you are experiencing issues, you can enable the `AUTORUN_DEBUG` environment variable to get more detailed output of what could be going wrong. If you need even more information, you can set `LOG_OUTPUT_LEVEL` to `debug` to get **A TON** of output of what's exactly happening. From f6607b7b864be2a47a5e107818a9d1abec1f58c1 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 28 Oct 2025 11:55:16 -0500 Subject: [PATCH 112/170] Add structured comments to Caddyfile for improved readability and organization. This includes sections for global configuration, common snippets, and dynamic imports, enhancing clarity for users managing Caddy configurations. --- .../frankenphp/etc/frankenphp/Caddyfile | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/variations/frankenphp/etc/frankenphp/Caddyfile b/src/variations/frankenphp/etc/frankenphp/Caddyfile index cdd989e2a..3a31f4027 100644 --- a/src/variations/frankenphp/etc/frankenphp/Caddyfile +++ b/src/variations/frankenphp/etc/frankenphp/Caddyfile @@ -1,5 +1,7 @@ +######################################################## +# Global Caddy configuration +######################################################## { - # Global Caddy configuration admin {$CADDY_ADMIN:off} import auto-https/{$CADDY_AUTO_HTTPS:off}.caddyfile @@ -55,9 +57,9 @@ fd00::/8 \ {$CADDY_GLOBAL_OPTIONS} } -(auto-https-off) { - tls {$SSL_CERTIFICATE_FILE} {$SSL_CERTIFICATE_KEY_FILE} -} +######################################################## +# Common snippets +######################################################## (auto-https-on) { # tls directive is not needed when auto_https is enabled @@ -150,8 +152,12 @@ fd00::/8 \ } } +######################################################## +# Dynamic imports +######################################################## + # Pull in the per-mode listeners (off|mixed|full) import ssl-mode/{$SSL_MODE:off}.caddyfile -# Add your web servers here +# Add additional Caddy configuration files from the caddyfile.d directory import caddyfile.d/*.caddyfile From ea324bf4538b7afe79a5a6d6c012cd2a3e0e670e Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 28 Oct 2025 12:57:53 -0500 Subject: [PATCH 113/170] Update Apache configuration to support customizable HTTP and HTTPS ports via environment variables. Added `APACHE_HTTP_PORT` and `APACHE_HTTPS_PORT` to documentation for improved user guidance on server configuration. --- .../docs/8.reference/1.environment-variable-specification.md | 2 ++ .../fpm-apache/etc/apache2/sites-available/ssl-full.conf | 4 ++-- .../fpm-apache/etc/apache2/sites-available/ssl-mixed.conf | 4 ++-- .../fpm-apache/etc/apache2/sites-available/ssl-off.conf | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/content/docs/8.reference/1.environment-variable-specification.md b/docs/content/docs/8.reference/1.environment-variable-specification.md index 5c6fa2a08..e127d8362 100644 --- a/docs/content/docs/8.reference/1.environment-variable-specification.md +++ b/docs/content/docs/8.reference/1.environment-variable-specification.md @@ -16,6 +16,8 @@ Setting environment variables all depends on what method you're using to run you **Variable Name**|**Description**|**Used in variation** :-----:|:-----:|:-----: `APACHE_DOCUMENT_ROOT`
*Default: "/var/www/html/public"*|Sets the directory from which Apache will serve files. (Official docs)|fpm-apache +`APACHE_HTTP_PORT`
*Default: "8080"*|Set the port for HTTP. (Official docs)|fpm-apache +`APACHE_HTTPS_PORT`
*Default: "8443"*|Set the port for HTTPS. (Official docs)|fpm-apache `APACHE_MAX_CONNECTIONS_PER_CHILD`
*Default: "0"*|Sets the limit on the number of connections that an individual child server process will handle.(Official docs)|fpm-apache `APACHE_MAX_REQUEST_WORKERS`
*Default: "150"*|Sets the limit on the number of simultaneous requests that will be served. (Official docs)|fpm-apache `APACHE_MAX_SPARE_THREADS`
*Default: "75"*|Maximum number of idle threads. (Official docs)|fpm-apache diff --git a/src/variations/fpm-apache/etc/apache2/sites-available/ssl-full.conf b/src/variations/fpm-apache/etc/apache2/sites-available/ssl-full.conf index 180a477ae..8b82a15cc 100644 --- a/src/variations/fpm-apache/etc/apache2/sites-available/ssl-full.conf +++ b/src/variations/fpm-apache/etc/apache2/sites-available/ssl-full.conf @@ -1,4 +1,4 @@ - + # Configure ServerAdmin and ServerName ServerName localhost ServerAdmin webmaster@localhost @@ -28,6 +28,6 @@ - + Include /etc/apache2/vhost-templates/https.conf \ No newline at end of file diff --git a/src/variations/fpm-apache/etc/apache2/sites-available/ssl-mixed.conf b/src/variations/fpm-apache/etc/apache2/sites-available/ssl-mixed.conf index b3d46bfaf..568b1817b 100644 --- a/src/variations/fpm-apache/etc/apache2/sites-available/ssl-mixed.conf +++ b/src/variations/fpm-apache/etc/apache2/sites-available/ssl-mixed.conf @@ -1,7 +1,7 @@ - + Include /etc/apache2/vhost-templates/http.conf - + Include /etc/apache2/vhost-templates/https.conf \ No newline at end of file diff --git a/src/variations/fpm-apache/etc/apache2/sites-available/ssl-off.conf b/src/variations/fpm-apache/etc/apache2/sites-available/ssl-off.conf index 81c73ca06..2e353dbbc 100644 --- a/src/variations/fpm-apache/etc/apache2/sites-available/ssl-off.conf +++ b/src/variations/fpm-apache/etc/apache2/sites-available/ssl-off.conf @@ -1,3 +1,3 @@ - + Include /etc/apache2/vhost-templates/http.conf \ No newline at end of file From 641f8fbd1c6ea593ae44d16b7ea8e8bc6217c3e7 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 28 Oct 2025 13:01:18 -0500 Subject: [PATCH 114/170] Introduce environment variables for customizable Apache HTTP and HTTPS ports in Dockerfile. This enhances flexibility for users configuring server settings. --- src/variations/fpm-apache/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/variations/fpm-apache/Dockerfile b/src/variations/fpm-apache/Dockerfile index 0171a05bf..2e52e80a7 100644 --- a/src/variations/fpm-apache/Dockerfile +++ b/src/variations/fpm-apache/Dockerfile @@ -38,6 +38,8 @@ LABEL org.opencontainers.image.title="serversideup/php (fpm-apache)" \ org.opencontainers.image.licenses="GPL-3.0-or-later" ENV APACHE_DOCUMENT_ROOT=/var/www/html/public \ + APACHE_HTTP_PORT="8080" \ + APACHE_HTTPS_PORT="8443" \ APACHE_START_SERVERS="2" \ APACHE_MIN_SPARE_THREADS="10" \ APACHE_MAX_SPARE_THREADS="75" \ From b8d4b7e19b0f5fc993e5789dbfccc75fda9b1726 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 28 Oct 2025 13:12:51 -0500 Subject: [PATCH 115/170] Update health check messages for Apache and NGINX to improve clarity during startup. Changed failure messages to indicate waiting for services to start, enhancing user experience during deployment. --- .../fpm-apache/etc/s6-overlay/s6-rc.d/apache2/data/check | 2 +- .../fpm-nginx/etc/s6-overlay/s6-rc.d/nginx/data/check | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/variations/fpm-apache/etc/s6-overlay/s6-rc.d/apache2/data/check b/src/variations/fpm-apache/etc/s6-overlay/s6-rc.d/apache2/data/check index 90cc5b6cd..119e0b4b4 100644 --- a/src/variations/fpm-apache/etc/s6-overlay/s6-rc.d/apache2/data/check +++ b/src/variations/fpm-apache/etc/s6-overlay/s6-rc.d/apache2/data/check @@ -10,7 +10,7 @@ if is_online; then echo "✅ Apache + PHP-FPM is running correctly." exit 0 else - echo "❌ There seems to be a failure in checking the Apache + PHP-FPM." + echo "Health check waiting for Apache + PHP-FPM to start..." status_code=$(curl $curl_options -w "%{http_code}" "$healthcheck_url") echo "HTTP Status Code: $status_code" exit 1 diff --git a/src/variations/fpm-nginx/etc/s6-overlay/s6-rc.d/nginx/data/check b/src/variations/fpm-nginx/etc/s6-overlay/s6-rc.d/nginx/data/check index e718322f8..117d018c0 100644 --- a/src/variations/fpm-nginx/etc/s6-overlay/s6-rc.d/nginx/data/check +++ b/src/variations/fpm-nginx/etc/s6-overlay/s6-rc.d/nginx/data/check @@ -10,7 +10,7 @@ if is_online; then echo "✅ NGINX + PHP-FPM is running correctly." exit 0 else - echo "👉 NGINX + PHP-FPM is not online. Waiting for it to start..." + echo "Health check waiting for NGINX + PHP-FPM to start..." if [ "$LOG_OUTPUT_LEVEL" = "debug" ]; then status_code=$(curl $curl_options -w "%{http_code}" "$healthcheck_url") echo "HTTP Status Code: $status_code" From be547d1bda37ff3baf310d3a0732fa801fd8aa14 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 28 Oct 2025 13:37:51 -0500 Subject: [PATCH 116/170] Refactor Apache and NGINX configurations to utilize environment variables for HTTP and HTTPS ports. This change enhances flexibility and consistency across configurations, allowing users to customize server settings more easily. Updated health check scripts to reflect the new port variables. --- src/variations/fpm-apache/Dockerfile | 2 +- src/variations/fpm-apache/etc/apache2/ports.conf | 6 +++--- .../fpm-apache/etc/apache2/sites-available/ssl-full.conf | 8 ++++---- .../fpm-apache/etc/apache2/sites-available/ssl-mixed.conf | 4 ++-- .../fpm-apache/etc/s6-overlay/s6-rc.d/apache2/data/check | 2 +- src/variations/fpm-nginx/Dockerfile | 4 +++- .../fpm-nginx/etc/nginx/site-opts.d/http.conf.template | 4 ++-- .../fpm-nginx/etc/nginx/site-opts.d/https.conf.template | 4 ++-- .../fpm-nginx/etc/nginx/sites-available/ssl-full | 4 ++-- .../fpm-nginx/etc/s6-overlay/s6-rc.d/nginx/data/check | 2 +- 10 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/variations/fpm-apache/Dockerfile b/src/variations/fpm-apache/Dockerfile index 2e52e80a7..456458018 100644 --- a/src/variations/fpm-apache/Dockerfile +++ b/src/variations/fpm-apache/Dockerfile @@ -177,4 +177,4 @@ WORKDIR ${APP_BASE_DIR} CMD ["/init"] HEALTHCHECK --start-period=60s --start-interval=3s --interval=10s --timeout=3s --retries=3 \ - CMD [ "sh", "-c", "curl --insecure --silent --location --show-error --fail http://localhost:8080$HEALTHCHECK_PATH || exit 1" ] + CMD [ "sh", "-c", "curl --insecure --silent --location --show-error --fail http://localhost:${APACHE_HTTP_PORT}${HEALTHCHECK_PATH} || exit 1" ] diff --git a/src/variations/fpm-apache/etc/apache2/ports.conf b/src/variations/fpm-apache/etc/apache2/ports.conf index 5284a27e6..78d20efb0 100644 --- a/src/variations/fpm-apache/etc/apache2/ports.conf +++ b/src/variations/fpm-apache/etc/apache2/ports.conf @@ -1,9 +1,9 @@ -Listen 8080 +Listen ${APACHE_HTTP_PORT} - Listen 8443 + Listen ${APACHE_HTTPS_PORT} - Listen 8443 + Listen ${APACHE_HTTPS_PORT} \ No newline at end of file diff --git a/src/variations/fpm-apache/etc/apache2/sites-available/ssl-full.conf b/src/variations/fpm-apache/etc/apache2/sites-available/ssl-full.conf index 8b82a15cc..056ddde91 100644 --- a/src/variations/fpm-apache/etc/apache2/sites-available/ssl-full.conf +++ b/src/variations/fpm-apache/etc/apache2/sites-available/ssl-full.conf @@ -1,4 +1,4 @@ - + # Configure ServerAdmin and ServerName ServerName localhost ServerAdmin webmaster@localhost @@ -9,9 +9,9 @@ # Turn on rewrite engine RewriteEngine On - # Redirect traffic from localhost to https://localhost:8443 + # Redirect traffic from localhost to https://localhost:${APACHE_HTTPS_PORT} RewriteCond %{SERVER_NAME} =localhost - RewriteRule ^ https://%{SERVER_NAME}:8443%{REQUEST_URI} [END,NE,R=permanent] + RewriteRule ^ https://%{SERVER_NAME}:${APACHE_HTTPS_PORT}%{REQUEST_URI} [END,NE,R=permanent] # Redirect all other traffic to https://host:443 RewriteCond %{SERVER_NAME} !=localhost @@ -28,6 +28,6 @@ - + Include /etc/apache2/vhost-templates/https.conf \ No newline at end of file diff --git a/src/variations/fpm-apache/etc/apache2/sites-available/ssl-mixed.conf b/src/variations/fpm-apache/etc/apache2/sites-available/ssl-mixed.conf index 568b1817b..1e03cefd2 100644 --- a/src/variations/fpm-apache/etc/apache2/sites-available/ssl-mixed.conf +++ b/src/variations/fpm-apache/etc/apache2/sites-available/ssl-mixed.conf @@ -1,7 +1,7 @@ - + Include /etc/apache2/vhost-templates/http.conf - + Include /etc/apache2/vhost-templates/https.conf \ No newline at end of file diff --git a/src/variations/fpm-apache/etc/s6-overlay/s6-rc.d/apache2/data/check b/src/variations/fpm-apache/etc/s6-overlay/s6-rc.d/apache2/data/check index 119e0b4b4..0ad09772d 100644 --- a/src/variations/fpm-apache/etc/s6-overlay/s6-rc.d/apache2/data/check +++ b/src/variations/fpm-apache/etc/s6-overlay/s6-rc.d/apache2/data/check @@ -1,6 +1,6 @@ #!/command/with-contenv sh curl_options="--fail --location --insecure --silent --show-error --output /dev/null" -healthcheck_url="http://localhost:8080${HEALTHCHECK_PATH}" +healthcheck_url="http://localhost:${APACHE_HTTP_PORT}${HEALTHCHECK_PATH}" is_online() { curl $curl_options "$healthcheck_url" diff --git a/src/variations/fpm-nginx/Dockerfile b/src/variations/fpm-nginx/Dockerfile index db2ff711e..84081ea61 100644 --- a/src/variations/fpm-nginx/Dockerfile +++ b/src/variations/fpm-nginx/Dockerfile @@ -124,6 +124,8 @@ ENV APP_BASE_DIR=/var/www/html \ NGINX_ERROR_LOG="/dev/stderr" \ NGINX_FASTCGI_BUFFERS="8 8k" \ NGINX_FASTCGI_BUFFER_SIZE="8k" \ + NGINX_HTTP_PORT="8080" \ + NGINX_HTTPS_PORT="8443" \ NGINX_LISTEN_IP_PROTOCOL="all" \ NGINX_SERVER_TOKENS=off \ NGINX_WEBROOT=/var/www/html/public \ @@ -259,4 +261,4 @@ WORKDIR ${APP_BASE_DIR} CMD ["/init"] HEALTHCHECK --start-period=60s --start-interval=3s --interval=10s --timeout=3s --retries=3 \ - CMD [ "sh", "-c", "curl --insecure --silent --location --show-error --fail http://localhost:8080$HEALTHCHECK_PATH || exit 1" ] + CMD [ "sh", "-c", "curl --insecure --silent --location --show-error --fail http://localhost:${NGINX_HTTP_PORT}${HEALTHCHECK_PATH} || exit 1" ] diff --git a/src/variations/fpm-nginx/etc/nginx/site-opts.d/http.conf.template b/src/variations/fpm-nginx/etc/nginx/site-opts.d/http.conf.template index 341e4b188..1d6ee8e6d 100644 --- a/src/variations/fpm-nginx/etc/nginx/site-opts.d/http.conf.template +++ b/src/variations/fpm-nginx/etc/nginx/site-opts.d/http.conf.template @@ -1,5 +1,5 @@ -listen 8080 default_server; -listen [::]:8080 default_server; +listen ${NGINX_HTTP_PORT} default_server; +listen [::]:${NGINX_HTTP_PORT} default_server; root $NGINX_WEBROOT; diff --git a/src/variations/fpm-nginx/etc/nginx/site-opts.d/https.conf.template b/src/variations/fpm-nginx/etc/nginx/site-opts.d/https.conf.template index 78f024953..0685ac17c 100644 --- a/src/variations/fpm-nginx/etc/nginx/site-opts.d/https.conf.template +++ b/src/variations/fpm-nginx/etc/nginx/site-opts.d/https.conf.template @@ -1,5 +1,5 @@ -listen 8443 ssl default_server; -listen [::]:8443 ssl default_server; +listen ${NGINX_HTTPS_PORT} ssl default_server; +listen [::]:${NGINX_HTTPS_PORT} ssl default_server; http2 on; root $NGINX_WEBROOT; diff --git a/src/variations/fpm-nginx/etc/nginx/sites-available/ssl-full b/src/variations/fpm-nginx/etc/nginx/sites-available/ssl-full index 850f5449b..df640dea0 100644 --- a/src/variations/fpm-nginx/etc/nginx/sites-available/ssl-full +++ b/src/variations/fpm-nginx/etc/nginx/sites-available/ssl-full @@ -1,8 +1,8 @@ # HTTP Redirect configuration # server { - listen 8080 default_server; - listen [::]:8080 default_server; + listen ${NGINX_HTTP_PORT} default_server; + listen [::]:${NGINX_HTTP_PORT} default_server; server_name _; diff --git a/src/variations/fpm-nginx/etc/s6-overlay/s6-rc.d/nginx/data/check b/src/variations/fpm-nginx/etc/s6-overlay/s6-rc.d/nginx/data/check index 117d018c0..28d87220e 100644 --- a/src/variations/fpm-nginx/etc/s6-overlay/s6-rc.d/nginx/data/check +++ b/src/variations/fpm-nginx/etc/s6-overlay/s6-rc.d/nginx/data/check @@ -1,6 +1,6 @@ #!/command/with-contenv sh curl_options="--fail --location --insecure --silent --show-error --output /dev/null" -healthcheck_url="http://localhost:8080${HEALTHCHECK_PATH}" +healthcheck_url="http://localhost:${NGINX_HTTP_PORT}${HEALTHCHECK_PATH}" is_online() { curl $curl_options "$healthcheck_url" From 750363b223c9c8d525e92eebff577ddb58ebf047 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 28 Oct 2025 13:38:48 -0500 Subject: [PATCH 117/170] Update health check command in Dockerfile to use CADDY_HTTP_PORT environment variable for improved configurability. This change enhances the flexibility of health checks in the frankenphp variation, aligning with recent updates to server configurations. --- src/variations/frankenphp/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/variations/frankenphp/Dockerfile b/src/variations/frankenphp/Dockerfile index b08b6e1c2..041a8f5b6 100644 --- a/src/variations/frankenphp/Dockerfile +++ b/src/variations/frankenphp/Dockerfile @@ -227,4 +227,4 @@ ENTRYPOINT ["docker-php-serversideup-entrypoint"] CMD ["frankenphp", "run", "--config", "/etc/frankenphp/Caddyfile", "--adapter", "caddyfile"] HEALTHCHECK --start-period=60s --start-interval=3s --interval=10s --timeout=3s --retries=3 \ - CMD [ "sh", "-c", "curl --insecure --silent --location --show-error --fail http://localhost:8080$HEALTHCHECK_PATH || exit 1" ] \ No newline at end of file + CMD [ "sh", "-c", "curl --insecure --silent --location --show-error --fail http://localhost:${CADDY_HTTP_PORT}${HEALTHCHECK_PATH} || exit 1" ] \ No newline at end of file From 9c61c452c896e3fb288ab1d7b1f1235503c2310b Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 28 Oct 2025 13:53:44 -0500 Subject: [PATCH 118/170] Add SSL full configuration template for NGINX and update entrypoint script to process it. This enhances the web server setup by providing a complete SSL configuration, improving security and flexibility for users deploying Laravel applications. --- src/s6/etc/entrypoint.d/10-init-webserver-config.sh | 1 + .../etc/nginx/sites-available/{ssl-full => ssl-full.template} | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) rename src/variations/fpm-nginx/etc/nginx/sites-available/{ssl-full => ssl-full.template} (91%) diff --git a/src/s6/etc/entrypoint.d/10-init-webserver-config.sh b/src/s6/etc/entrypoint.d/10-init-webserver-config.sh index 1b1652103..9a5ed8225 100644 --- a/src/s6/etc/entrypoint.d/10-init-webserver-config.sh +++ b/src/s6/etc/entrypoint.d/10-init-webserver-config.sh @@ -171,6 +171,7 @@ if [ "$DISABLE_DEFAULT_CONFIG" = false ]; then process_template /etc/nginx/nginx.conf.template /etc/nginx/nginx.conf process_template /etc/nginx/site-opts.d/http.conf.template /etc/nginx/site-opts.d/http.conf process_template /etc/nginx/site-opts.d/https.conf.template /etc/nginx/site-opts.d/https.conf + process_template /etc/nginx/sites-available/ssl-full.template /etc/nginx/sites-available/ssl-full # Configure NGINX IP listening protocol if NGINX is installed nginx_config_files="/etc/nginx/site-opts.d/http.conf /etc/nginx/site-opts.d/https.conf /etc/nginx/sites-available/ssl-full" diff --git a/src/variations/fpm-nginx/etc/nginx/sites-available/ssl-full b/src/variations/fpm-nginx/etc/nginx/sites-available/ssl-full.template similarity index 91% rename from src/variations/fpm-nginx/etc/nginx/sites-available/ssl-full rename to src/variations/fpm-nginx/etc/nginx/sites-available/ssl-full.template index df640dea0..c8841095f 100644 --- a/src/variations/fpm-nginx/etc/nginx/sites-available/ssl-full +++ b/src/variations/fpm-nginx/etc/nginx/sites-available/ssl-full.template @@ -23,7 +23,7 @@ server { if ($redirect_to_local_https) { access_log off; - return 301 https://localhost:8443$request_uri; + return 301 https://localhost:${NGINX_HTTPS_PORT}$request_uri; } return 301 https://$host$request_uri; From a34c6116705b8b8f5d6a15da466acc5e634b283a Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 28 Oct 2025 14:09:30 -0500 Subject: [PATCH 119/170] Update SSL generation script to improve clarity in Caddy Auto HTTPS notice. This change enhances user understanding by refining the messaging when SSL mode is off or when Caddy Auto HTTPS is enabled. --- src/variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh b/src/variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh index b7f408b72..8f3525500 100644 --- a/src/variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh +++ b/src/variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh @@ -13,7 +13,7 @@ if [ "$SSL_MODE" = "off" ]; then echo "ℹ️ NOTICE ($script_name): SSL mode is off, so we won't generate a self-signed SSL key pair." return 0 elif [ "$CADDY_AUTO_HTTPS" != "off" ]; then - echo "ℹ️ NOTICE ($script_name): Caddy Auto HTTPS is enabled, so we won't generate a default, self-signed, SSL key pair." + echo "ℹ️ NOTICE ($script_name): Caddy Auto HTTPS is enabled, so we won't generate a self-signed SSL key pair." return 0 fi From cf1c66f997fe1d1a320bbedd81dec94be269a2ac Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 28 Oct 2025 16:20:23 -0500 Subject: [PATCH 120/170] Refactor Dockerfile to create and set permissions for Composer cache directory. This change ensures the cache directory is properly established for improved performance and user experience in the frankenphp variation. --- src/variations/frankenphp/Dockerfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/variations/frankenphp/Dockerfile b/src/variations/frankenphp/Dockerfile index 041a8f5b6..6d6bf82cb 100644 --- a/src/variations/frankenphp/Dockerfile +++ b/src/variations/frankenphp/Dockerfile @@ -37,10 +37,10 @@ RUN set -eux; \ # Set the image version echo "${REPOSITORY_BUILD_VERSION}" > /etc/serversideup-php-version; \ echo "${FRANKENPHP_VERSION}" > /etc/serversideup-php-frankenphp-version; - # \ - # # Make composer cache directory - # mkdir -p "${COMPOSER_HOME}"; \ - # chown -R www-data:www-data "${COMPOSER_HOME}"; + \ + # Make composer cache directory + mkdir -p "${COMPOSER_HOME}"; \ + chown -R www-data:www-data "${COMPOSER_HOME}"; #################### # Go Image From f0e9ec01fc22fc34c8b2f5664e96f5123bb3e4b8 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 28 Oct 2025 16:24:20 -0500 Subject: [PATCH 121/170] Enhance file permission settings in Docker image by including /config and /data directories. This update ensures proper ownership is applied to these directories, improving security and consistency in the frankenphp variation. --- .../local/bin/docker-php-serversideup-set-file-permissions | 4 ++++ src/variations/frankenphp/Dockerfile | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/common/usr/local/bin/docker-php-serversideup-set-file-permissions b/src/common/usr/local/bin/docker-php-serversideup-set-file-permissions index 4d039889b..8762ef1bd 100644 --- a/src/common/usr/local/bin/docker-php-serversideup-set-file-permissions +++ b/src/common/usr/local/bin/docker-php-serversideup-set-file-permissions @@ -212,6 +212,8 @@ case "$OS" in /composer /var/www /etc/ssl/private + /config + /data $PHP_INI_DIR/conf.d/zzz-serversideup-docker-php-debug.ini" ;; *) @@ -276,6 +278,8 @@ case "$OS" in /composer /var/www /etc/ssl/private + /config + /data $PHP_INI_DIR/conf.d/zzz-serversideup-docker-php-debug.ini" ;; *) diff --git a/src/variations/frankenphp/Dockerfile b/src/variations/frankenphp/Dockerfile index 6d6bf82cb..bfaaa9b1f 100644 --- a/src/variations/frankenphp/Dockerfile +++ b/src/variations/frankenphp/Dockerfile @@ -40,7 +40,7 @@ RUN set -eux; \ \ # Make composer cache directory mkdir -p "${COMPOSER_HOME}"; \ - chown -R www-data:www-data "${COMPOSER_HOME}"; + docker-php-serversideup-set-file-permissions --owner www-data:www-data #################### # Go Image From 2c2cf78368809719d3f2ecb9911a0da2cdd984f8 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 28 Oct 2025 16:31:26 -0500 Subject: [PATCH 122/170] Fixed syntax error and removed redundant code --- src/variations/frankenphp/Dockerfile | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/variations/frankenphp/Dockerfile b/src/variations/frankenphp/Dockerfile index bfaaa9b1f..53dc0bdd5 100644 --- a/src/variations/frankenphp/Dockerfile +++ b/src/variations/frankenphp/Dockerfile @@ -36,11 +36,7 @@ RUN set -eux; \ \ # Set the image version echo "${REPOSITORY_BUILD_VERSION}" > /etc/serversideup-php-version; \ - echo "${FRANKENPHP_VERSION}" > /etc/serversideup-php-frankenphp-version; - \ - # Make composer cache directory - mkdir -p "${COMPOSER_HOME}"; \ - docker-php-serversideup-set-file-permissions --owner www-data:www-data + echo "${FRANKENPHP_VERSION}" > /etc/serversideup-php-frankenphp-version #################### # Go Image From d05acf70213972c7d6194a2ad2c88dbb8085d5c0 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 29 Oct 2025 10:48:27 -0500 Subject: [PATCH 123/170] Refactor Caddyfile configurations to replace 'app-common' with 'php-app-common' for improved clarity and consistency. Re-added 'auto-https-off' snippet for explicit TLS configuration and enhanced healthcheck handling for both HTTP and HTTPS modes. --- .../frankenphp/etc/frankenphp/Caddyfile | 6 +++++- .../etc/frankenphp/ssl-mode/full.caddyfile | 18 ++++++++++++++---- .../etc/frankenphp/ssl-mode/mixed.caddyfile | 4 ++-- .../etc/frankenphp/ssl-mode/off.caddyfile | 2 +- 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/variations/frankenphp/etc/frankenphp/Caddyfile b/src/variations/frankenphp/etc/frankenphp/Caddyfile index 3a31f4027..01bfceebf 100644 --- a/src/variations/frankenphp/etc/frankenphp/Caddyfile +++ b/src/variations/frankenphp/etc/frankenphp/Caddyfile @@ -61,12 +61,16 @@ fd00::/8 \ # Common snippets ######################################################## +(auto-https-off) { + tls {$SSL_CERTIFICATE_FILE} {$SSL_CERTIFICATE_KEY_FILE} +} + (auto-https-on) { # tls directive is not needed when auto_https is enabled } # Common app logic; reused across all modes -(app-common) { +(php-app-common) { root * {$CADDY_APP_PUBLIC_PATH:/var/www/html/public} encode zstd br gzip diff --git a/src/variations/frankenphp/etc/frankenphp/ssl-mode/full.caddyfile b/src/variations/frankenphp/etc/frankenphp/ssl-mode/full.caddyfile index c80eca611..eeef2801e 100644 --- a/src/variations/frankenphp/etc/frankenphp/ssl-mode/full.caddyfile +++ b/src/variations/frankenphp/etc/frankenphp/ssl-mode/full.caddyfile @@ -1,5 +1,5 @@ -{$CADDY_HTTP_SERVER_ADDRESS:http://} { - # Redirect localhost healthcheck requests to HTTPS with the correct port +# Healthcheck - HTTP: Redirect to HTTPS +http://localhost:{$CADDY_HTTP_PORT:8080} { @healthcheck { remote_ip 127.0.0.1/8 ::1 path /healthcheck # Caddy healthcheck endpoint @@ -7,13 +7,23 @@ } log_skip @healthcheck redir @healthcheck https://localhost:{$CADDY_HTTPS_PORT:8443}{uri} 308 +} + +# Healthcheck - HTTPS: Use self-signed certificate +https://localhost:{$CADDY_HTTPS_PORT:8443} { + tls {$HEALTHCHECK_SSL_CERTIFICATE_FILE:/etc/ssl/private/healthcheck-localhost.crt} {$HEALTHCHECK_SSL_PRIVATE_KEY_FILE:/etc/ssl/private/healthcheck-localhost.key} + import php-app-common + import security-https +} - # Redirect all other traffic to HTTPS (without explicit port) +# HTTP Traffic: Redirect to HTTPS (without explicit port) +{$CADDY_HTTP_SERVER_ADDRESS:http://} { redir https://{host}{uri} 308 } +# HTTPS Traffic {$CADDY_HTTPS_SERVER_ADDRESS:https://} { import auto-https-{$CADDY_AUTO_HTTPS:off} - import app-common + import php-app-common import security-https } diff --git a/src/variations/frankenphp/etc/frankenphp/ssl-mode/mixed.caddyfile b/src/variations/frankenphp/etc/frankenphp/ssl-mode/mixed.caddyfile index 5d4a8c395..9dedb439b 100644 --- a/src/variations/frankenphp/etc/frankenphp/ssl-mode/mixed.caddyfile +++ b/src/variations/frankenphp/etc/frankenphp/ssl-mode/mixed.caddyfile @@ -1,9 +1,9 @@ {$CADDY_HTTP_SERVER_ADDRESS:http://} { - import app-common + import php-app-common } {$CADDY_HTTPS_SERVER_ADDRESS:https://} { import auto-https-{$CADDY_AUTO_HTTPS:off} - import app-common + import php-app-common import security-https } diff --git a/src/variations/frankenphp/etc/frankenphp/ssl-mode/off.caddyfile b/src/variations/frankenphp/etc/frankenphp/ssl-mode/off.caddyfile index 8146ebe93..211c66ded 100644 --- a/src/variations/frankenphp/etc/frankenphp/ssl-mode/off.caddyfile +++ b/src/variations/frankenphp/etc/frankenphp/ssl-mode/off.caddyfile @@ -1,3 +1,3 @@ {$CADDY_HTTP_SERVER_ADDRESS:http://} { - import app-common + import php-app-common } From 73ab6eaee2cd28b2316610fec0698af2e50e3c7e Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 29 Oct 2025 10:48:41 -0500 Subject: [PATCH 124/170] Enhance SSL generation script to include healthcheck SSL keypair creation. This update adds support for generating a self-signed SSL certificate and private key specifically for healthchecks, while also refining the default SSL keypair generation process for improved clarity and functionality. --- .../etc/entrypoint.d/10-generate-ssl.sh | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/src/variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh b/src/variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh index 8f3525500..141a56a34 100644 --- a/src/variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh +++ b/src/variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh @@ -8,13 +8,12 @@ script_name="generate-ssl" SSL_CERTIFICATE_FILE=${SSL_CERTIFICATE_FILE:-"/etc/ssl/private/self-signed-web.crt"} SSL_PRIVATE_KEY_FILE=${SSL_PRIVATE_KEY_FILE:-"/etc/ssl/private/self-signed-web.key"} SSL_MODE=${SSL_MODE:-"off"} +HEALTHCHECK_SSL_CERTIFICATE_FILE=${HEALTHCHECK_SSL_CERTIFICATE_FILE:-"/etc/ssl/private/healthcheck-localhost.crt"} +HEALTHCHECK_SSL_PRIVATE_KEY_FILE=${HEALTHCHECK_SSL_PRIVATE_KEY_FILE:-"/etc/ssl/private/healthcheck-localhost.key"} if [ "$SSL_MODE" = "off" ]; then echo "ℹ️ NOTICE ($script_name): SSL mode is off, so we won't generate a self-signed SSL key pair." return 0 -elif [ "$CADDY_AUTO_HTTPS" != "off" ]; then - echo "ℹ️ NOTICE ($script_name): Caddy Auto HTTPS is enabled, so we won't generate a self-signed SSL key pair." - return 0 fi if [ -z "$SSL_CERTIFICATE_FILE" ] || [ -z "$SSL_PRIVATE_KEY_FILE" ]; then @@ -22,8 +21,8 @@ if [ -z "$SSL_CERTIFICATE_FILE" ] || [ -z "$SSL_PRIVATE_KEY_FILE" ]; then return 1 fi -if ([ -f "$SSL_CERTIFICATE_FILE" ] && [ ! -f "$SSL_PRIVATE_KEY_FILE" ]) || - ([ ! -f "$SSL_CERTIFICATE_FILE" ] && [ -f "$SSL_PRIVATE_KEY_FILE" ]); then +if [ -f "$SSL_CERTIFICATE_FILE" ] && [ ! -f "$SSL_PRIVATE_KEY_FILE" ] || + [ ! -f "$SSL_CERTIFICATE_FILE" ] && [ -f "$SSL_PRIVATE_KEY_FILE" ]; then echo "🛑 ERROR ($script_name): Only one of the SSL certificate or private key exists. Check the SSL_CERTIFICATE_FILE and SSL_PRIVATE_KEY_FILE variables and try again." echo "🛑 ERROR ($script_name): SSL_CERTIFICATE_FILE: $SSL_CERTIFICATE_FILE" echo "🛑 ERROR ($script_name): SSL_PRIVATE_KEY_FILE: $SSL_PRIVATE_KEY_FILE" @@ -35,7 +34,19 @@ if [ -f "$SSL_CERTIFICATE_FILE" ] && [ -f "$SSL_PRIVATE_KEY_FILE" ]; then return 0 fi -echo "🔐 SSL Keypair not found. Generating self-signed SSL keypair..." -openssl req -x509 -subj "/C=US/ST=Wisconsin/L=Milwaukee/O=IT/CN=*.dev.test,*.test,*.gitpod.io,*.ngrok.io,*.nip.io" -nodes -newkey rsa:2048 -keyout "$SSL_PRIVATE_KEY_FILE" -out "$SSL_CERTIFICATE_FILE" -days 365 >/dev/null 2>&1 +echo "🔐 Generating self-signed Healthcheck SSL keypair..." +openssl req -x509 \ + -subj "/CN=localhost" \ + -nodes -newkey rsa:2048 \ + -keyout "$HEALTHCHECK_SSL_PRIVATE_KEY_FILE" \ + -out "$HEALTHCHECK_SSL_CERTIFICATE_FILE" \ + -days 365 >/dev/null 2>&1 +echo "🔐 Default SSL Keypair not found. Generating self-signed SSL keypair..." +openssl req -x509 \ + -subj "/CN=localhost" \ + -nodes -newkey rsa:2048 \ + -keyout "$SSL_PRIVATE_KEY_FILE" \ + -out "$SSL_CERTIFICATE_FILE" \ + -days 365 >/dev/null 2>&1 exit 0 \ No newline at end of file From aec64b5a7af724b7de955e6dc013a92f602107ac Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 29 Oct 2025 10:53:47 -0500 Subject: [PATCH 125/170] Refactor SSL generation script to improve logic for existing certificate checks. This change moves the check for existing SSL certificate and private key files to a more logical position, enhancing clarity and ensuring proper handling of self-signed SSL keypair generation. --- .../frankenphp/etc/entrypoint.d/10-generate-ssl.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh b/src/variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh index 141a56a34..9cafd05a0 100644 --- a/src/variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh +++ b/src/variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh @@ -29,11 +29,6 @@ if [ -f "$SSL_CERTIFICATE_FILE" ] && [ ! -f "$SSL_PRIVATE_KEY_FILE" ] || return 1 fi -if [ -f "$SSL_CERTIFICATE_FILE" ] && [ -f "$SSL_PRIVATE_KEY_FILE" ]; then - echo "ℹ️ NOTICE ($script_name): SSL certificate and private key already exist, so we'll use the existing files." - return 0 -fi - echo "🔐 Generating self-signed Healthcheck SSL keypair..." openssl req -x509 \ -subj "/CN=localhost" \ @@ -42,6 +37,11 @@ openssl req -x509 \ -out "$HEALTHCHECK_SSL_CERTIFICATE_FILE" \ -days 365 >/dev/null 2>&1 +if [ -f "$SSL_CERTIFICATE_FILE" ] && [ -f "$SSL_PRIVATE_KEY_FILE" ]; then + echo "ℹ️ NOTICE ($script_name): SSL certificate and private key already exist, so we'll use the existing files." + return 0 +fi + echo "🔐 Default SSL Keypair not found. Generating self-signed SSL keypair..." openssl req -x509 \ -subj "/CN=localhost" \ From 84888cb8c66bc94a1cf0e875a9dd4faf4d679059 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 30 Oct 2025 14:23:57 -0500 Subject: [PATCH 126/170] Enhance Apache health check script to conditionally log HTTP status code based on debug output level. This change improves debugging capabilities by allowing detailed status information only when the LOG_OUTPUT_LEVEL is set to debug. --- .../fpm-apache/etc/s6-overlay/s6-rc.d/apache2/data/check | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/variations/fpm-apache/etc/s6-overlay/s6-rc.d/apache2/data/check b/src/variations/fpm-apache/etc/s6-overlay/s6-rc.d/apache2/data/check index 0ad09772d..f2c6b6fc4 100644 --- a/src/variations/fpm-apache/etc/s6-overlay/s6-rc.d/apache2/data/check +++ b/src/variations/fpm-apache/etc/s6-overlay/s6-rc.d/apache2/data/check @@ -11,7 +11,9 @@ if is_online; then exit 0 else echo "Health check waiting for Apache + PHP-FPM to start..." - status_code=$(curl $curl_options -w "%{http_code}" "$healthcheck_url") - echo "HTTP Status Code: $status_code" + if [ "$LOG_OUTPUT_LEVEL" = "debug" ]; then + status_code=$(curl $curl_options -w "%{http_code}" "$healthcheck_url") + echo "HTTP Status Code: $status_code" + fi exit 1 fi From 33a302e0d8a7ef678de36291c65dcea8e95ac163 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 30 Oct 2025 14:24:25 -0500 Subject: [PATCH 127/170] Refactor SSL handling by removing validation from webserver config scripts and introducing a dedicated SSL generation script. This change enhances clarity and modularity, allowing for better management of SSL certificates and keys, while ensuring proper handling of self-signed certificates for both general use and healthchecks. --- .../entrypoint.d/10-init-webserver-config.sh | 31 ------------------- .../etc/entrypoint.d/5-generate-ssl.sh} | 0 src/variations/fpm-apache/Dockerfile | 1 + src/variations/fpm-nginx/Dockerfile | 1 + src/variations/frankenphp/Dockerfile | 2 +- 5 files changed, 3 insertions(+), 32 deletions(-) rename src/{variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh => utilities-webservers/etc/entrypoint.d/5-generate-ssl.sh} (100%) diff --git a/src/s6/etc/entrypoint.d/10-init-webserver-config.sh b/src/s6/etc/entrypoint.d/10-init-webserver-config.sh index 9a5ed8225..a34608d75 100644 --- a/src/s6/etc/entrypoint.d/10-init-webserver-config.sh +++ b/src/s6/etc/entrypoint.d/10-init-webserver-config.sh @@ -99,10 +99,6 @@ enable_apache_site (){ # Transform to lowercase ssl_mode=$(echo "$ssl_mode" | tr '[:upper:]' '[:lower:]') - if [ "$ssl_mode" != "off" ]; then - validate_ssl - fi - # Enable the site if [ ! -e "$apache2_enabled_site_path/ssl-$ssl_mode.conf" ]; then echo "ℹ️ NOTICE ($script_name): Enabling Apache site with SSL '$ssl_mode'..." @@ -119,10 +115,6 @@ enable_nginx_site (){ # Transform to lowercase ssl_mode=$(echo "$ssl_mode" | tr '[:upper:]' '[:lower:]') - if [ "$ssl_mode" != "off" ]; then - validate_ssl - fi - # Link the site available to be the active site if [ -f "$default_nginx_site_config" ]; then echo "ℹ️ NOTICE ($script_name): $default_nginx_site_config already exists, so we'll use the provided configuration." @@ -135,29 +127,6 @@ enable_nginx_site (){ fi } -validate_ssl(){ - if [ -z "$SSL_CERTIFICATE_FILE" ] || [ -z "$SSL_PRIVATE_KEY_FILE" ]; then - echo "🛑 ERROR ($script_name): SSL_CERTIFICATE_FILE or SSL_PRIVATE_KEY_FILE is not set." - return 1 - fi - - if ([ -f "$SSL_CERTIFICATE_FILE" ] && [ ! -f "$SSL_PRIVATE_KEY_FILE" ]) || - ([ ! -f "$SSL_CERTIFICATE_FILE" ] && [ -f "$SSL_PRIVATE_KEY_FILE" ]); then - echo "🛑 ERROR ($script_name): Only one of the SSL certificate or private key exists. Check the SSL_CERTIFICATE_FILE and SSL_PRIVATE_KEY_FILE variables and try again." - echo "🛑 ERROR ($script_name): SSL_CERTIFICATE_FILE: $SSL_CERTIFICATE_FILE" - echo "🛑 ERROR ($script_name): SSL_PRIVATE_KEY_FILE: $SSL_PRIVATE_KEY_FILE" - return 1 - fi - - if [ -f "$SSL_CERTIFICATE_FILE" ] && [ -f "$SSL_PRIVATE_KEY_FILE" ]; then - echo "ℹ️ NOTICE ($script_name): SSL certificate and private key already exist, so we'll use the existing files." - return 0 - fi - - echo "🔐 SSL Keypair not found. Generating self-signed SSL keypair..." - openssl req -x509 -subj "/C=US/ST=Wisconsin/L=Milwaukee/O=IT/CN=*.dev.test,*.gitpod.io,*.ngrok.io,*.nip.io" -nodes -newkey rsa:2048 -keyout "$SSL_PRIVATE_KEY_FILE" -out "$SSL_CERTIFICATE_FILE" -days 365 >/dev/null 2>&1 -} - ########## # Main ########## diff --git a/src/variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh b/src/utilities-webservers/etc/entrypoint.d/5-generate-ssl.sh similarity index 100% rename from src/variations/frankenphp/etc/entrypoint.d/10-generate-ssl.sh rename to src/utilities-webservers/etc/entrypoint.d/5-generate-ssl.sh diff --git a/src/variations/fpm-apache/Dockerfile b/src/variations/fpm-apache/Dockerfile index 456458018..37c5854f9 100644 --- a/src/variations/fpm-apache/Dockerfile +++ b/src/variations/fpm-apache/Dockerfile @@ -104,6 +104,7 @@ ENV APACHE_DOCUMENT_ROOT=/var/www/html/public \ # copy our scripts COPY --chmod=755 src/common/ / COPY --chmod=755 src/s6/ / +COPY --chmod=755 src/utilities-webservers/ / # copy s6-overlay from s6-build COPY --from=s6-build /opt/s6/ / diff --git a/src/variations/fpm-nginx/Dockerfile b/src/variations/fpm-nginx/Dockerfile index 84081ea61..e2693a7b7 100644 --- a/src/variations/fpm-nginx/Dockerfile +++ b/src/variations/fpm-nginx/Dockerfile @@ -178,6 +178,7 @@ ENV APP_BASE_DIR=/var/www/html \ # copy our scripts COPY --chmod=755 src/common/ / COPY --chmod=755 src/s6/ / +COPY --chmod=755 src/utilities-webservers/ / # copy s6-overlay from s6-build COPY --from=s6-build /opt/s6/ / diff --git a/src/variations/frankenphp/Dockerfile b/src/variations/frankenphp/Dockerfile index 53dc0bdd5..8d69d3816 100644 --- a/src/variations/frankenphp/Dockerfile +++ b/src/variations/frankenphp/Dockerfile @@ -14,6 +14,7 @@ ARG FRANKENPHP_VERSION # copy our scripts COPY --chmod=755 src/common/ / +COPY --chmod=755 src/utilities-webservers/ / RUN set -eux; \ # Create directories @@ -184,7 +185,6 @@ COPY --from=frankenphp-build /usr/local/bin/frankenphp /usr/local/bin/frankenphp COPY --from=frankenphp-build /usr/local/lib/libwatcher* /usr/local/lib/ COPY src/variations/frankenphp/etc/frankenphp/ /etc/frankenphp/ -COPY src/variations/frankenphp/etc/entrypoint.d/ /etc/entrypoint.d/ RUN \ docker-php-serversideup-dep-install-alpine "${DEPENDENCY_PACKAGES_ALPINE}"; \ From 5037ba26eadc783ae1fdd328a012d3162175fe91 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 30 Oct 2025 14:34:50 -0500 Subject: [PATCH 128/170] Update healthcheck SSL configuration and paths in Docker setup. This change introduces dedicated SSL certificate and private key files for healthchecks, ensuring proper handling in the FrankenPHP variation. Additionally, it updates the Dockerfile and entrypoint scripts to reflect the new paths, enhancing security and modularity in SSL management. --- .../1.environment-variable-specification.md | 2 ++ ...cker-php-serversideup-set-file-permissions | 2 ++ .../etc/entrypoint.d/5-generate-ssl.sh | 21 +++++++++++-------- src/variations/frankenphp/Dockerfile | 1 + .../etc/frankenphp/ssl-mode/full.caddyfile | 2 +- 5 files changed, 18 insertions(+), 10 deletions(-) diff --git a/docs/content/docs/8.reference/1.environment-variable-specification.md b/docs/content/docs/8.reference/1.environment-variable-specification.md index e127d8362..760ecc17e 100644 --- a/docs/content/docs/8.reference/1.environment-variable-specification.md +++ b/docs/content/docs/8.reference/1.environment-variable-specification.md @@ -63,6 +63,8 @@ Setting environment variables all depends on what method you're using to run you `DISABLE_DEFAULT_CONFIG`
*Default: "false"*|Get full customization of the image and disable all default configurations and automations.| all `FRANKENPHP_CONFIG`
*Default: ""*|Set the configuration for FrankenPHP. (Official docs)|frankenphp `HEALTHCHECK_PATH`
*Default: "/healthcheck"*|Set the path for the health check endpoint. (Official docs)|all (except `cli` and `frankenphp`) +`HEALTHCHECK_SSL_CERTIFICATE_FILE`
*Default: "/etc/ssl/healthcheck/localhost.crt"*|Set the path to the SSL certificate for the health check endpoint.| fpm-apache, fpm-nginx, frankenphp +`HEALTHCHECK_SSL_PRIVATE_KEY_FILE`
*Default: "/etc/ssl/healthcheck/localhost.key"*|Set the path to the SSL private key for the health check endpoint.| fpm-apache, fpm-nginx, frankenphp `LOG_OUTPUT_LEVEL`
*Default: "warn"*|Set your container output different verbosity levels: debug, info, off |all `NGINX_ACCESS_LOG`
*Default: "/dev/stdout"*|Set the default output stream for access log.|fpm-nginx `NGINX_ERROR_LOG`
*Default: "/dev/stderr"*|Set the default output stream for error log.|fpm-nginx diff --git a/src/common/usr/local/bin/docker-php-serversideup-set-file-permissions b/src/common/usr/local/bin/docker-php-serversideup-set-file-permissions index 8762ef1bd..4a1de23a5 100644 --- a/src/common/usr/local/bin/docker-php-serversideup-set-file-permissions +++ b/src/common/usr/local/bin/docker-php-serversideup-set-file-permissions @@ -212,6 +212,7 @@ case "$OS" in /composer /var/www /etc/ssl/private + /etc/ssl/healthcheck /config /data $PHP_INI_DIR/conf.d/zzz-serversideup-docker-php-debug.ini" @@ -278,6 +279,7 @@ case "$OS" in /composer /var/www /etc/ssl/private + /etc/ssl/healthcheck /config /data $PHP_INI_DIR/conf.d/zzz-serversideup-docker-php-debug.ini" diff --git a/src/utilities-webservers/etc/entrypoint.d/5-generate-ssl.sh b/src/utilities-webservers/etc/entrypoint.d/5-generate-ssl.sh index 9cafd05a0..94369d171 100644 --- a/src/utilities-webservers/etc/entrypoint.d/5-generate-ssl.sh +++ b/src/utilities-webservers/etc/entrypoint.d/5-generate-ssl.sh @@ -8,8 +8,8 @@ script_name="generate-ssl" SSL_CERTIFICATE_FILE=${SSL_CERTIFICATE_FILE:-"/etc/ssl/private/self-signed-web.crt"} SSL_PRIVATE_KEY_FILE=${SSL_PRIVATE_KEY_FILE:-"/etc/ssl/private/self-signed-web.key"} SSL_MODE=${SSL_MODE:-"off"} -HEALTHCHECK_SSL_CERTIFICATE_FILE=${HEALTHCHECK_SSL_CERTIFICATE_FILE:-"/etc/ssl/private/healthcheck-localhost.crt"} -HEALTHCHECK_SSL_PRIVATE_KEY_FILE=${HEALTHCHECK_SSL_PRIVATE_KEY_FILE:-"/etc/ssl/private/healthcheck-localhost.key"} +HEALTHCHECK_SSL_CERTIFICATE_FILE=${HEALTHCHECK_SSL_CERTIFICATE_FILE:-"/etc/ssl/healthcheck/localhost.crt"} +HEALTHCHECK_SSL_PRIVATE_KEY_FILE=${HEALTHCHECK_SSL_PRIVATE_KEY_FILE:-"/etc/ssl/healthcheck/localhost.key"} if [ "$SSL_MODE" = "off" ]; then echo "ℹ️ NOTICE ($script_name): SSL mode is off, so we won't generate a self-signed SSL key pair." @@ -29,13 +29,16 @@ if [ -f "$SSL_CERTIFICATE_FILE" ] && [ ! -f "$SSL_PRIVATE_KEY_FILE" ] || return 1 fi -echo "🔐 Generating self-signed Healthcheck SSL keypair..." -openssl req -x509 \ - -subj "/CN=localhost" \ - -nodes -newkey rsa:2048 \ - -keyout "$HEALTHCHECK_SSL_PRIVATE_KEY_FILE" \ - -out "$HEALTHCHECK_SSL_CERTIFICATE_FILE" \ - -days 365 >/dev/null 2>&1 +# Generate self-signed Healthcheck SSL keypair for FrankenPHP only +if [ -d "/etc/frankenphp/" ]; then + echo "🔐 Generating self-signed Healthcheck SSL keypair..." + openssl req -x509 \ + -subj "/CN=localhost" \ + -nodes -newkey rsa:2048 \ + -keyout "$HEALTHCHECK_SSL_PRIVATE_KEY_FILE" \ + -out "$HEALTHCHECK_SSL_CERTIFICATE_FILE" \ + -days 365 >/dev/null 2>&1 +fi if [ -f "$SSL_CERTIFICATE_FILE" ] && [ -f "$SSL_PRIVATE_KEY_FILE" ]; then echo "ℹ️ NOTICE ($script_name): SSL certificate and private key already exist, so we'll use the existing files." diff --git a/src/variations/frankenphp/Dockerfile b/src/variations/frankenphp/Dockerfile index 8d69d3816..5e2b519f4 100644 --- a/src/variations/frankenphp/Dockerfile +++ b/src/variations/frankenphp/Dockerfile @@ -20,6 +20,7 @@ RUN set -eux; \ # Create directories mkdir -p \ /var/www/html/public \ + /etc/ssl/healthcheck \ /config/caddy \ /data/caddy \ /etc/caddy \ diff --git a/src/variations/frankenphp/etc/frankenphp/ssl-mode/full.caddyfile b/src/variations/frankenphp/etc/frankenphp/ssl-mode/full.caddyfile index eeef2801e..fd4b15b66 100644 --- a/src/variations/frankenphp/etc/frankenphp/ssl-mode/full.caddyfile +++ b/src/variations/frankenphp/etc/frankenphp/ssl-mode/full.caddyfile @@ -11,7 +11,7 @@ http://localhost:{$CADDY_HTTP_PORT:8080} { # Healthcheck - HTTPS: Use self-signed certificate https://localhost:{$CADDY_HTTPS_PORT:8443} { - tls {$HEALTHCHECK_SSL_CERTIFICATE_FILE:/etc/ssl/private/healthcheck-localhost.crt} {$HEALTHCHECK_SSL_PRIVATE_KEY_FILE:/etc/ssl/private/healthcheck-localhost.key} + tls {$HEALTHCHECK_SSL_CERTIFICATE_FILE:/etc/ssl/healthcheck/localhost.crt} {$HEALTHCHECK_SSL_PRIVATE_KEY_FILE:/etc/ssl/healthcheck/localhost.key} import php-app-common import security-https } From 50f630cb2b0bd845f0a5dbae7111318ea1d78136 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 30 Oct 2025 14:56:13 -0500 Subject: [PATCH 129/170] fix: Set SSL_PRIVATE_KEY_FILE to proper name on FrankenPHP --- src/variations/frankenphp/Dockerfile | 2 +- src/variations/frankenphp/etc/frankenphp/Caddyfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/variations/frankenphp/Dockerfile b/src/variations/frankenphp/Dockerfile index 5e2b519f4..b5ed10167 100644 --- a/src/variations/frankenphp/Dockerfile +++ b/src/variations/frankenphp/Dockerfile @@ -175,7 +175,7 @@ LABEL org.opencontainers.image.title="serversideup/php (frankenphp)" \ SHOW_WELCOME_MESSAGE=true \ SSL_MODE=off \ SSL_CERTIFICATE_FILE="/etc/ssl/private/self-signed-web.crt" \ - SSL_CERTIFICATE_KEY_FILE="/etc/ssl/private/self-signed-web.key" \ + SSL_PRIVATE_KEY_FILE="/etc/ssl/private/self-signed-web.key" \ XDG_CONFIG_HOME=/config \ XDG_DATA_HOME=/data diff --git a/src/variations/frankenphp/etc/frankenphp/Caddyfile b/src/variations/frankenphp/etc/frankenphp/Caddyfile index 01bfceebf..a785add5f 100644 --- a/src/variations/frankenphp/etc/frankenphp/Caddyfile +++ b/src/variations/frankenphp/etc/frankenphp/Caddyfile @@ -62,7 +62,7 @@ fd00::/8 \ ######################################################## (auto-https-off) { - tls {$SSL_CERTIFICATE_FILE} {$SSL_CERTIFICATE_KEY_FILE} + tls {$SSL_CERTIFICATE_FILE} {$SSL_PRIVATE_KEY_FILE} } (auto-https-on) { From 6af0abc574c3a197a944605b0bac6ff17781e843 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 30 Oct 2025 16:26:03 -0500 Subject: [PATCH 130/170] Add SSL configuration documentation for Docker PHP images --- .../4.configuring-ssl.md | 250 ++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 docs/content/docs/4.deployment-and-production/4.configuring-ssl.md diff --git a/docs/content/docs/4.deployment-and-production/4.configuring-ssl.md b/docs/content/docs/4.deployment-and-production/4.configuring-ssl.md new file mode 100644 index 000000000..6252314aa --- /dev/null +++ b/docs/content/docs/4.deployment-and-production/4.configuring-ssl.md @@ -0,0 +1,250 @@ +--- +head.title: 'Configuring SSL - Docker PHP - Server Side Up' +description: 'Learn how to use SSL with the serversideup/php images.' +layout: docs +title: Configuring SSL +--- + +::lead-p +SSL encryption is natively supported in our images. With FrankenPHP, a trusted certificate can automatically be generated by Let's Encrypt. You can also bring your own certificates or have a self-signed certificate generated for you. +:: + +## Supported Variations +SSL is natively supported in the following variations: + +| Variation | SSL Support | Automated, Signed Certificate Support (via Let's Encrypt) | +|-----------|---------------------|---------------------| +| `cli` | ❌ No | - | +| `fpm` | ❌ No | - | +| `fpm-nginx` | ✅ Yes | ❌ No
(requires a reverse proxy in front of the container) | +| `fpm-apache` | ✅ Yes | ❌ No
(requires a reverse proxy in front of the container) | +| `frankenphp` | ✅ Yes | ✅ Yes | + +## SSL Modes +You can control SSL behavior with the `SSL_MODE` environment variable: + +| SSL Mode | Description | +|----------|-------------| +| `off` (default) | HTTP only. | +| `mixed` | HTTP and HTTPS. | +| `full` | HTTPS only. HTTP requests will be redirected to HTTPS. | + +## Choose How to Run SSL in Production + +You have a few options for running SSL in production: + +| Approach | Certificate Type | Management Type | Zero-Downtime Deployments | Minimal Number of Containers | +|----------|----------------|-----------------|-----------------|--------------------------------| +| Reverse Proxy (like Traefik or Caddy) | ✅ Trusted Certificate (via Let's Encrypt) | ✅ Automatic | ✅ Yes | ⚠️ 2 | +| FrankenPHP's built-in automatic HTTPS | ✅ Trusted Certificate (via Let's Encrypt) | ✅ Automatic | ❌ No | ✅ 1 | +| Bring Your Own Certificate | ✅ Trusted Certificate (through any vendor) | ❌ Manual | ❌ No | ✅ 1 | +| Self-signed | ❌ Self-signed Certificate | ✅ Automatic | ❌ No | ✅ 1 | + +### Reverse Proxy (recommended) +::tip +Reverse proxies don't just terminate SSL—they also give you zero-downtime with rolling updates. +:: +![Reverse Proxy](images/docs/reverse-proxy-ssl-zerodowntime.png){:zoom=false} +Our recommended approach is to use a reverse proxy like [Traefik](https://traefik.io/traefik/){target="_blank"} or [Caddy](https://caddyserver.com/){target="_blank"} that listens on ports 80 (HTTP) and 443 (HTTPS). The reverse proxy will forward traffic to your container on the non-privileged ports of 8080 (HTTP) or 8443 (HTTPS). + +Using a reverse proxy unlocks two major benefits: +1. Automatic SSL certificate management (via Let's Encrypt) +2. Zero-downtime deployments + +When you're running updates on containers, the reverse proxy stays online while updates are deployed to your containers in the background. Configuring a reverse proxy is outside the scope of this documentation, but you can reference the links below to learn more: + +- [Traefik](https://traefik.io/traefik/){target="_blank"} +- [Caddy](https://caddyserver.com/){target="_blank"} + +#### Use a Reverse Proxy When You Want... +- Zero-downtime deployments +- Automatic SSL certificate management (via Let's Encrypt) +- Load balancing + +If you want a simple way to run your own reverse proxy with zero-downtime deployments, consider using [Spin](https://serversideup.net/open-source/spin/){target="_blank"}. + +:u-button{to="https://serversideup.net/open-source/spin/" label="Learn more about Spin" aria-label="Learn more about Spin" target="_blank" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +### FrankenPHP's Built-in Automatic HTTPS +::warning +Zero-downtime deployments are not possible with FrankenPHP's built-in automatic HTTPS. +:: + +FrankenPHP provides automated HTTPS through Caddy. To directly expose FrankenPHP to the internet, you'll need to configure the following: +1. Environment variables (for Caddy configuration) +2. Ports (for direct exposure of ports 80 and 443) +3. Volumes (for certificate files) + +#### Environment Variables +Configure the following environment variables: + +| Variable | Expected Value | Description | +|----------|----------------|----------------| +| `CADDY_AUTO_HTTPS`
*Default: "off"* | `on` | Turn on Caddy's [`auto_https`](https://caddyserver.com/docs/caddyfile/options#auto-https){target="_blank"} global directive.| +| `CADDY_HTTPS_SERVER_ADDRESS`
*Default: "https://"* | `example.com` or `https://example.com` | Set the [server address](https://caddyserver.com/docs/caddyfile/concepts#addresses){target="_blank"} for HTTPS. Pro tip: You can use `$APP_URL` from your `.env` file to set this value. | +| `SSL_MODE`
*Default: "off"* | `full` or `mixed` | Configure how Caddy handles HTTP and HTTPS requests.| + +#### Ports +Configure the following ports: + +| Ports to Publish | Description | +|----------------|----------------| +| `80` → `8080` | HTTP traffic will be proxied to the container on port 8080. | +| `443` → `8443` | HTTPS traffic will be proxied to the container on port 8443. | + +::note +Our port mapping remains `80:8080` and `443:8443` because our containers are **unprivileged** by default, meaning we cannot bind to ports less than 1024 (without additional modification). +:: + +#### Volumes +Configure the following volumes: + +| Container Directory to Mount | Description | +|--------------------------------|-------------| +| `/config` | Directory for Caddy's configuration files (such as Caddyfile or JSON) that must persist for settings to be retained. | +| `/data` | Directory where Caddy stores SSL/TLS certificates and CA information, required for automatic HTTPS to consistently function. | + +::note +The `config` and `data` volumes must have read/write permissions for the `www-data` user. Caddy will store its configuration and certificates in these volumes (and you want those to persist). +:: + +#### Example +Here's an example of directly exposing FrankenPHP to the internet with automatic HTTPS via Let's Encrypt: +::code-tree{defaultValue="compose.yml"} + +```yml [compose.yml] +services: + php: + image: serversideup/php:8.4-frankenphp + ports: + - 80:8080 + - 443:8443 + environment: + CADDY_AUTO_HTTPS: "on" + CADDY_HTTPS_SERVER_ADDRESS: "https://example.com" + SSL_MODE: "full" + # Mount the current directory to /var/www/html + volumes: + - .:/var/www/html + - config:/config + - data:/data + + volumes: + config: + data: +``` + +```php [public/index.php] + +``` +:: + +#### Use FrankenPHP's Built-in Automatic HTTPS When You Want... +- To run your application and handle SSL termination all in one container +- A simple setup without needing zero-downtime deployments + +::note +You can achieve zero-downtime deployments with FrankenPHP by placing a reverse proxy in front of the container. +:: + +### Bringing Your Own Certificate +If automatic HTTPS isn't an option, you can provide your own certificate from a vendor like [ssls.com](https://www.ssls.com/){target="_blank"}. Ensure your certificate issuer provides certificates compatible with your web server in [PEM format](https://en.wikipedia.org/wiki/Privacy-Enhanced_Mail){target="_blank"}. + +To add your own certificate, mount the certificate files to the container: + +::tip +Set your private key file permissions to `600` (read/write for owner only). Incorrect permissions will cause errors when loading the private key. +:: + +::code-tree{defaultValue="compose.yml"} + +```yml [compose.yml]{8-10,13} +services: + php: + image: serversideup/php:8.4-fpm-nginx + ports: + - 80:8080 + - 443:8443 + environment: + SSL_MODE: "mixed" + SSL_PRIVATE_KEY_FILE: "/etc/ssl/custom/test-key.pem" + SSL_CERTIFICATE_FILE: "/etc/ssl/custom/test.pem" + volumes: + - .:/var/www/html/ + - ./certs/:/etc/ssl/custom/ +``` + +```php [public/index.php] + +``` + +```pem [certs/test-key.pem] +-----BEGIN PRIVATE KEY----- +EXAMPLE_PRIVATE_KEY_DO_NOT_USE +MIIEvQIBADANBgkqhkiG9w0BAQEFASCBKwggSjAgEAAoIBAQDExampleKeyData +ThisIsNotARealPrivateKeyAndShouldNotBeUsedInProduction123456789 +ReplaceThisWithYourActualPrivateKeyFile +-----END PRIVATE KEY----- +``` + +```pem [certs/test.pem] +-----BEGIN CERTIFICATE----- +EXAMPLE_CERTIFICATE_DO_NOT_USE +MIIEIDCCAwigAwIBAgIQCqH+3yBp80lQ9OVmbNmbRzANBgkqhkiG9w0BAQsFADBh +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD +QTAeFw0yMTA0MjkwMDAwMDBaFw0zMjA0MjgyMzU5NTlaMFsxCzAJBgNVBAYTAlVT +MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j +b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG +9w0BAQEFAAOCAQ8AMIIBCgKCAQEAumQB+ILtbVLaKTeQeGviJLbfBxMIRZACMpbs +QFmylhSTSSpLc1bNPrRVWWVmv+Lt8i3HuLjPQF+3M2NzBWVYB7Gixgd13KZBquor +2W4Sj5SfR2onVzULfBy6SrwxfSTnnykA1NAzGLbGSukNkY4fO7N4V3C1mLGvL8H +-----END CERTIFICATE----- +``` +:: + +#### Use Your Own Certificates When You... +- Cannot use Let's Encrypt (corporate policy, network restrictions, etc.) +- Have a specific certificate vendor requirement +- Don't need zero-downtime deployments + +::note +You can also bring your own certificate and configure it with a reverse proxy to get zero-downtime deployments. +:: + +### Self-Signed Certificate +::warning +Self-signed certificates will display warnings in the browser. +:: + +While browsers will show warnings, self-signed certificates are useful for specific use cases, such as encrypting traffic between containers in a cluster. If you set `SSL_MODE` to `mixed` or `full` without providing a certificate at `$SSL_CERTIFICATE_FILE` and `$SSL_PRIVATE_KEY_FILE`, a self-signed certificate will be automatically generated. + +```yml [docker-compose.yml]{7-9} +services: + php: + image: serversideup/php:8.4-fpm-nginx + ports: + - 80:8080 + - 443:8443 + environment: + # Set SSL mode to "mixed" (HTTP + HTTPS) + SSL_MODE: "mixed" + volumes: + - .:/var/www/html +``` + +The above will generate a self-signed certificate and configure the server to listen on both HTTP (port 80) and HTTPS (port 443). + +#### Use a Self-Signed Certificate When You... +- Have a reverse proxy in front of the container handling SSL termination +- Need all traffic to be encrypted (even on the internal network between containers) + +::note +If you have a reverse proxy in front of the container handling SSL termination, you don't need to use `SSL_MODE` at all. You can configure your reverse proxy to communicate with your PHP container via HTTP (port 8080), eliminating the need to configure SSL within the container. +:: \ No newline at end of file From b4abf11c0a0349337426012ff79a45a4f1c3acf9 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Thu, 30 Oct 2025 16:26:08 -0500 Subject: [PATCH 131/170] Add reverse proxy SSL zero downtime image for documentation --- .../docs/reverse-proxy-ssl-zerodowntime.png | Bin 0 -> 175652 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/public/images/docs/reverse-proxy-ssl-zerodowntime.png diff --git a/docs/public/images/docs/reverse-proxy-ssl-zerodowntime.png b/docs/public/images/docs/reverse-proxy-ssl-zerodowntime.png new file mode 100644 index 0000000000000000000000000000000000000000..6ab2ce8a5b2457fc8a2067c18f3accbcb1b694de GIT binary patch literal 175652 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 literal 0 HcmV?d00001 From 644dd4f09d5ea47dde77ff5a748896f98e381d87 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 09:33:32 -0500 Subject: [PATCH 132/170] Revise documentation for 'serversideup/php' to highlight its advantages over traditional PHP deployment methods. The update includes a comprehensive feature comparison, security optimizations, and streamlined configuration processes, emphasizing the benefits of using environment variables for customization. Additionally, the content has been restructured for clarity and improved readability. --- .../2.these-images-vs-others.md | 345 ++++++++++++++++-- 1 file changed, 308 insertions(+), 37 deletions(-) diff --git a/docs/content/docs/1.getting-started/2.these-images-vs-others.md b/docs/content/docs/1.getting-started/2.these-images-vs-others.md index 350476607..652d1c945 100644 --- a/docs/content/docs/1.getting-started/2.these-images-vs-others.md +++ b/docs/content/docs/1.getting-started/2.these-images-vs-others.md @@ -1,56 +1,327 @@ --- -title: These images vs others -description: 'Learn the important differences between serversideup/php and other PHP images.' +title: These Images vs Others +description: 'Discover why thousands of developers trust serversideup/php for their production PHP applications.' --- -| | **Official PHP Images** |**serversideup/php** | -|-------------------------|-------------------------|---------------------| -| Base Operating System | Debian, Alpine | Debian, Alpine | -| PHP Compilation | PHP Source Code | PHP Source Code (based on official PHP images) | -| Run PHP, pinned to the minor version | ✅ | ✅ | -| Multi-arch support | ✅ | ✅ | -| Init System | Docker CMD | Docker CMD or [S6-Overlay](https://github.com/just-containers/s6-overlay) | -| Published Registry| DockerHub | [DockerHub](https://hub.docker.com/r/serversideup/php), [GitHub Packages](https://github.com/serversideup/docker-php/pkgs/container/php) | -| Unprivileged by default | ❌ | ✅ | -| Variable-first configuration | ❌ | ✅ | -| Includes `composer` | ❌ | ✅ | -| Includes [`install-php-extensions`](https://github.com/mlocati/docker-php-extension-installer) | ❌ | ✅ | -| Production-Ready by default| ❌ | ✅ | -| Built-in security optimizations | ❌ | ✅ | -| Optimized for Laravel & WordPress| ❌ | ✅ | -| NGINX + FPM variation| ❌ | ✅ | -| FrankenPHP variation| ❌ | ✅ | -| Native health checks | ❌ | ✅ | - -## Unprivileged by Default +## The Problem with Traditional PHP Deployment + +If you've ever deployed a PHP application to production, you've probably experienced one (or all) of these frustrations: + +- **"It works on my machine"** - Your local environment doesn't match production, leading to mysterious bugs that only appear after deployment +- **Configuration Hell** - Spending hours tweaking `php.ini`, `www.conf`, and web server configs across multiple servers +- **Security Vulnerabilities** - Running as root, outdated extensions, or misconfigured permissions exposing your application to attacks +- **Manual Server Management** - SSH-ing into servers to update PHP, install extensions, or troubleshoot issues +- **Inconsistent Environments** - Each server is slightly different, making debugging and scaling a nightmare +- **Framework-Specific Tweaks** - Researching and applying dozens of optimizations for Laravel or WordPress performance + +You're not alone. These are the exact problems that led us to create `serversideup/php`. + +## How serversideup/php Solves These Problems + +`serversideup/php` is built on the official PHP images but adds everything needed for real-world production use: + +- ✅ **Works Identically Everywhere** - Same container runs on your laptop, CI/CD, and production +- ✅ **Zero Configuration Required** - Production-ready defaults with simple environment variable customization +- ✅ **Secure by Default** - Runs as unprivileged user, hardened for the open internet +- ✅ **Batteries Included** - Composer, common extensions, and helpful utilities pre-installed +- ✅ **Framework Optimized** - Pre-configured for Laravel and WordPress best practices +- ✅ **Modern Architecture** - FrankenPHP, S6 Overlay, native health checks, and multi-process support + ::note -Running containers as `root` in the open internet is very dangerous. This is why we run our images as `www-data` by default. +**Trusted by the Community** - Over 1 million Docker image pulls and actively used by Laravel and PHP developers worldwide. +:: + +## Feature Comparison + +See how `serversideup/php` stacks up against other PHP deployment options: + +| Feature | **Traditional Server** | **Official PHP Images** | **serversideup/php** | +|---------|------------------------|-------------------------|----------------------| +| Consistent environments | ❌ | ✅ | ✅ | +| Easy to scale | ❌ | ✅ | ✅ | +| Base OS Options | Manual Setup | Debian, Alpine | Debian, Alpine | +| PHP Version Management | Manual Updates | Easy Upgrades | Easy Upgrades | +| Multi-arch support | ❌ | ✅ | ✅ | +| Production-ready defaults | ⚠️ Manual | ❌ | ✅ | +| Runs as non-root user | ⚠️ Manual | ❌ | ✅ | +| Variable-first configuration | ❌ | ❌ | ✅ | +| Includes `composer` | ⚠️ Manual | ❌ | ✅ | +| Includes `install-php-extensions` | ❌ | ❌ | ✅ | +| Built-in security hardening | ⚠️ Manual | ❌ | ✅ | +| Laravel & WordPress optimizations | ⚠️ Manual | ❌ | ✅ | +| NGINX + FPM variation | ⚠️ Manual | ❌ | ✅ | +| FrankenPHP support | ❌ | ❌ | ✅ | +| Native health checks | ⚠️ Manual | ❌ | ✅ | +| S6 Overlay init system | ❌ | ❌ | ✅ | +| Published Registries | N/A | DockerHub | [DockerHub](https://hub.docker.com/r/serversideup/php) + [GitHub Packages](https://github.com/serversideup/docker-php/pkgs/container/php) | + +## Key Advantages Explained + +### Security First: Unprivileged by Default + +::caution +Running containers as `root` in production is a critical security vulnerability. If your application is compromised, an attacker gains root access to your container which could lead to a full system compromise. :: -We believe in the principle of least privilege. Our images run as an unprivileged user by default. This means that if your application is compromised, the attacker will have a harder time escalating their privileges to the root user. +Our images run as the `www-data` user by default, following the principle of least privilege. This means: + +- **Limited Blast Radius** - If your application is compromised, don't have root privileges +- **Kubernetes Compatible** - Many Kubernetes clusters require non-root containers by policy +- **Production Best Practice** - Aligns with NIST and CIS security benchmarks + +We also include additional security hardening: +- Disabled dangerous PHP functions by default (but you control them) +- Proper file permissions out of the box +- CloudFlare trusted proxy support for accurate IP logging +- Regular security updates from official PHP base images + +### Performance Optimized + +Every image includes production-tuned defaults based on real-world PHP applications: + +**OPcache Configuration** +- Pre-configured for optimal memory usage and caching strategy +- Easily toggle between development and production modes +- Smart defaults that work for most applications + +**Process Management** +- PHP-FPM tuned for typical low resource usage for Laravel/WordPress workloads +- S6 Overlay for intelligent process supervision +- Graceful shutdown handling for zero-downtime deployments -Running unprivileged images also improves compatibility of running your containers in a Kubernetes environment, where running as root is not allowed. +**Modern Options** +- FrankenPHP support for incredible performance gains (2-3x faster than FPM in many claims made by developers) +- Native support for NGINX Unit +- HTTP/2 and HTTP/3 ready configurations -## Variable-first Configuration ::tip -Setting environment variables saves a ton of headache when customizing your container. View our [environment variable specification](/docs/reference/environment-variable-specification) for all the available variables. +Need to customize performance settings? Just set an environment variable like `PHP_OPCACHE_ENABLE=1` or `PHP_MEMORY_LIMIT=512M`. No config files needed. +:: + +### Developer Experience: Variable-First Configuration + +Stop editing config files. Stop rebuilding images for simple changes. Just set environment variables: + +```yml [compose.yml] {5-9,11-12} +services: + php: + image: serversideup/php:8.4-fpm-nginx + environment: + # Change any PHP setting with environment variables + PHP_MEMORY_LIMIT: "512M" + PHP_UPLOAD_MAX_FILE_SIZE: "100M" + PHP_MAX_EXECUTION_TIME: "180" + PHP_OPCACHE_ENABLE: "1" + + # Run Migrations, Storage Link, Caching, and more + AUTORUN_ENABLED: "true" +``` + +No Dockerfile modifications. No config file mounting. No image rebuilds. Just simple environment variables with production-ready defaults. + +:u-button{to="/docs/reference/environment-variable-specification" label="View all environment variables" aria-label="View all environment variables" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +### Production-Ready Out of the Box + +Our images are built for the wild internet: + +**Security Hardening** +- Unprivileged user execution +- Disabled dangerous PHP functions (you control which ones) +- Proper file permissions and ownership +- Regular security updates + +**Monitoring & Observability** +- Built-in health check endpoints +- All logs to STDOUT/STDERR for centralized logging +- Compatible with Prometheus, DataDog, and other monitoring tools + +**Deployment Features** +- Zero-downtime deployment support +- Graceful shutdown handling +- Queue worker and scheduler support for Laravel +- Automatic migration running on container start (optional) + +**Infrastructure as Code** +- Version your entire PHP stack in a `compose.yml` file +- Reproduce every environment with 100% consistency +- Easy rollbacks to previous versions + +### Framework Optimized for Laravel & WordPress + +We've done the hard work of optimizing for PHP's most popular frameworks: + +**Laravel Automations** +```yaml [compose.yml] +services: + php: + image: serversideup/php:8.3-fpm-nginx + environment: + # Run migrations, storage link, caching, and more + AUTORUN_ENABLED: "true" +``` + +:u-button{to="/docs/framework-guides/laravel/automations" label="Learn More About Laravel Automations" aria-label="Learn More About Laravel Automations" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +**WordPress Optimizations** +- Pre-installed PHP extensions WordPress needs +- Optimized PHP settings for WordPress performance +- Support for popular WordPress hosting patterns + +**All Frameworks Welcome** + +While we optimize for Laravel and WordPress, our images work great with: +- Symfony +- CodeIgniter +- Drupal +- Joomla +- Custom PHP applications + +### 🛠️ Batteries Included + +Unlike the official PHP images, we include tools you'll actually use: + +**Composer** +- Pre-installed and ready to use +- No need to install it in every Dockerfile +- Supports Composer v2 for lightning-fast installs + +**install-php-extensions** +- The popular [mlocati/docker-php-extension-installer](https://github.com/mlocati/docker-php-extension-installer) included +- Install any PHP extension with a single command +- Handles all dependencies automatically + +```dockerfile [Dockerfile] +FROM serversideup/php:8.4-cli + +# Switch to root to install extensions +USER root + +# Install any PHP extension easily +RUN install-php-extensions redis imagick mongodb + +# Switch back to unprivileged user +USER www-data +``` + +**Modern Init System** +- S6 Overlay for our FPM-Apache and FPM-NGINX variations +- Proper process supervision in containers +- Better than Supervisor for containerized workloads +- Graceful handling of signals for zero-downtime deployments + +**Multiple Variations** +Choose the right tool for your use case: +- [`cli`](/docs/image-variations/cli) - Command-line scripts, Composer, CI/CD +- [`fpm`](/docs/image-variations/fpm) - Just PHP-FPM (bring your own web server) +- [`fpm-nginx`](/docs/image-variations/fpm-nginx) - PHP-FPM + NGINX (most popular) +- [`fpm-apache`](/docs/image-variations/fpm-apache) - PHP-FPM + Apache +- [`frankenphp`](/docs/image-variations/frankenphp) - Modern, incredibly fast (2-3x FPM performance) +- [`unit`](/docs/image-variations/unit) - NGINX Unit for high-performance applications (deprecated) + +## Real-World Impact + +Don't just take our word for it. Here's what developers are experiencing: + +::note +**By the Numbers** +- **1,000,000+** Docker image pulls +- **2,000+** GitHub stars +- **Active Community** with regular updates and contributions +- **Production-Proven** across startups to enterprise applications :: -Our design philosophy is built all around simplicity. The process of customizing the behavior of PHP is as simple as setting an environment variable. We took every common configuration option and set it up so you can change these values in a simple method, defaulting every single option to production-ready values. +**Time Savings** +- ⏱️ **Minutes vs Hours** - Go from zero to production-ready PHP in minutes, not hours of server configuration +- 🔄 **Consistent Deployments** - Eliminate "works on my machine" debugging sessions +- 📦 **Pre-configured** - Stop researching optimal PHP settings for Laravel + +**Better Security** +- 🛡️ **Hardened by Default** - Security best practices built-in, not bolted on +- 🔒 **Regular Updates** - Based on official PHP images with security patches +- 📋 **Audit Trail** - Infrastructure as code means every change is tracked + +**Happier Developers** +- 😊 **Simple Configuration** - Environment variables instead of config file archaeology +- 🚀 **Modern Tools** - FrankenPHP, native health checks, and container-native features +- 🤝 **Community Support** - Active community and comprehensive documentation + +## Making the Switch + +### From Traditional Servers (LAMP/LEMP) + +If you're currently managing PHP on traditional servers, the switch to containers might seem daunting, but it's easier than you think: + +**Benefits You'll Gain** +- Identical environments from development to production +- Scale horizontally by adding more containers +- Roll back bad deployments in seconds +- Version control your entire infrastructure + +See our quick start guide to run your first PHP container. +:u-button{to="/docs/getting-started/installation" label="Quick Start Guide" aria-label="Quick Start Guide" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} -:u-button{to="/docs/reference/environment-variable-specification" label="Learn more about environment variables" aria-label="Learn more about environment variables" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} +### From Official PHP Images -## Optimized for Laravel & WordPress -We did the hard work of customizing the official PHP image and giving you everything to get started with running PHP's most popular frameworks in seconds. We also hardened the images to help protect your PHP application from common attacks. +Already using Docker with official PHP images? Switching is trivially easy. -## Production-ready -We believe images should be ready for production and able to live in the open and wild Internet. We took our years of experience and tweaked these images to be performant and secure as possible. Having these values published online allows others to review, contribute, and improve the images -- giving you the best security and performance possible. +:u-button{to="/docs/guide/migrating-from-official-php-images" label="Official PHP Migration Guide" aria-label="Official PHP Migration Guide" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +### From Other Docker Images + +Switching from Bitnami, custom images, or other PHP Docker images is straightforward: + +**Key Differences to Note** +- We run as `www-data` (UID 33) by default, not root +- Configuration via environment variables, not config file mounts +- Web root is `/var/www/html` by default +- All variations expose port `8080` (unprivileged port) + +**Migration Strategy** +1. Review our [environment variable specification](/docs/reference/environment-variable-specification) +2. Map your current config to environment variables +3. Test in development first +4. Switch image tag in production -## What is "S6 Overlay?" ::warning -Using **supervisor** to monitor multiple processes in a single container may lead to unintended consequences. This is why we use [S6 Overlay](/docs/guide/using-s6-overlay) to monitor multiple processes in a single container. +Always test in a development or staging environment first to ensure your application works correctly with the new image. +:: + +## Ready to Get Started? + +You're just minutes away from a better PHP deployment experience. + +::steps + +### Choose Your Path + +**Quick Start (New Projects)** +Follow our installation guide to create your first PHP app with Docker in under 5 minutes. + +:u-button{to="/docs/getting-started/installation" label="Quick Start Guide" aria-label="Quick Start Guide" size="md" color="primary" variant="solid" trailing-icon="i-lucide-rocket" class="font-bold"} + +**Migration Guide (Existing Apps)** +Already have a PHP application? Learn how to containerize it with serversideup/php. + +:u-button{to="/docs/guide/migrating-from-official-php-images" label="Migration Guides" aria-label="Migration Guides" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +### Choose an Image Variation + +Not sure which image variation is right for you? We have a guide for that. + +:u-button{to="/docs/getting-started/choosing-an-image" label="Choosing an Image" aria-label="Choosing an Image" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + :: -[S6 Overlay](https://github.com/just-containers/s6-overlay){target="_blank"} is a process supervisor designed for containerization from the ground up. It's a modern alternative to [Supervisor (aka Supervisord)](https://supervisord.org/){target="_blank"}. We only use this in our `serversideup/php:*-fpm-apache` and `serversideup/php:*-fpm-nginx` images, as they require two processes to run a service. +## Questions? + +We're here to help! Check out these resources: -:u-button{to="/docs/guide/using-s6-overlay" label="Learn more about S6 Overlay" aria-label="Learn more about S6 Overlay" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file +- 📚 [Full Documentation](/docs) - Comprehensive guides and references +- 💬 [GitHub Discussions](https://github.com/serversideup/docker-php/discussions) - Ask questions and share experiences +- 🐛 [GitHub Issues](https://github.com/serversideup/docker-php/issues) - Report bugs or request features +- 🗣️ [Discord](https://serversideup.net/discord) - Join our community and get help from the team and other developers. + +::tip +Join our community! Star us on [GitHub](https://github.com/serversideup/docker-php) and follow updates. +:: \ No newline at end of file From 4c922f2b00261c1a83203399bb6277d578a0a709 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 09:34:05 -0500 Subject: [PATCH 133/170] Cleaned up title --- docs/content/docs/1.getting-started/2.these-images-vs-others.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/1.getting-started/2.these-images-vs-others.md b/docs/content/docs/1.getting-started/2.these-images-vs-others.md index 652d1c945..d3f44097d 100644 --- a/docs/content/docs/1.getting-started/2.these-images-vs-others.md +++ b/docs/content/docs/1.getting-started/2.these-images-vs-others.md @@ -177,7 +177,7 @@ While we optimize for Laravel and WordPress, our images work great with: - Joomla - Custom PHP applications -### 🛠️ Batteries Included +### Batteries Included Unlike the official PHP images, we include tools you'll actually use: From ab7363cff9f99c3939e909f6a947b8cba10029fa Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 09:56:37 -0500 Subject: [PATCH 134/170] Add 'Getting Help' documentation to provide users with resources for community and professional support options. The guide includes sections on GitHub Discussions, Discord Community, GitHub Issues, and professional consulting services, aimed at helping users troubleshoot and seek assistance effectively. --- .../docs/7.troubleshooting/2.getting-help.md | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 docs/content/docs/7.troubleshooting/2.getting-help.md diff --git a/docs/content/docs/7.troubleshooting/2.getting-help.md b/docs/content/docs/7.troubleshooting/2.getting-help.md new file mode 100644 index 000000000..adaa0b78a --- /dev/null +++ b/docs/content/docs/7.troubleshooting/2.getting-help.md @@ -0,0 +1,123 @@ +--- +title: Getting Help +description: 'Find the support you need - from free community resources to professional consulting services.' +--- + +## You're Not Alone + +Getting stuck is a normal part of development. Whether you're troubleshooting a configuration issue, planning a complex deployment, or need help with a custom implementation, there are support options available to help you succeed. + +This guide will help you find the right resource to get unblocked quickly. + +## Free Community Support +::note +Want guaranteed response times from the maintainers? View our [Professional Support](#professional-support) options. +:: +Our community is active, helpful, and welcoming. Most questions can be answered through these free resources: + +### GitHub Discussions + +**Best for:** General questions, feature requests, and community discussions + +Our GitHub Discussions is the most popular place to get help from both the maintainers and the community. It's searchable, so your question might help others in the future. + +:u-button{to="https://github.com/serversideup/docker-php/discussions" target="_blank" label="Browse GitHub Discussions" aria-label="Browse GitHub Discussions" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +::tip +Before posting, search existing discussions - your question might already be answered! +:: + +### Discord Community + +**Best for:** Quick questions, real-time chat, and community interaction + +Join over 3,000+ developers in our Discord server. It's a great place for quick questions, real-time troubleshooting, and connecting with other developers using serversideup/php. + +:u-button{to="https://serversideup.net/discord" label="Join Our Discord" aria-label="Join Our Discord" size="md" color="primary" variant="outline" trailing-icon="i-lucide-message-circle" class="font-bold" target="_blank"} + +::note +Discord is great for quick questions, but GitHub Discussions is better for complex issues that need detailed troubleshooting or permanent documentation. +:: + +### GitHub Issues + +**Best for:** Bug reports and specific technical issues with the images + +Found a bug or experiencing unexpected behavior? Open a GitHub issue with detailed reproduction steps. + +:u-button{to="https://github.com/serversideup/docker-php/issues/new" label="Report an Issue" aria-label="Report an Issue" size="md" color="primary" variant="outline" trailing-icon="i-lucide-bug" class="font-bold" target="_blank"} + +**When to use GitHub Issues:** +- The Docker images aren't behaving as documented +- You've found a security vulnerability +- You have a specific, reproducible bug + +::warning +Please don't use GitHub Issues for general questions or support requests. Use GitHub Discussions or Discord instead. +:: + + +## How to Ask for Help Effectively + +We've compile and entire guide on how to get answers quickly from the community. + +:u-button{to="https://serversideup.net/ask-for-help/" label="How to Ask for Help Effectively" aria-label="How to Ask for Help Effectively" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold" target="_blank"} + +## Professional Support + +Need guaranteed response times, direct access to the maintainers, or help with your specific implementation? We offer professional support options. + +### One-Time Questions + +**Perfect for:** Specific technical questions or getting unstuck on a particular issue + +Schedule a focused session to get expert help with: +- Docker-specific implementation questions +- Complex deployment scenarios +- Performance optimization guidance +- Security configuration review +- Custom implementation planning + +:u-button{to="https://schedule.serversideup.net/team/serversideup/quick-chat-with-jay" label="Schedule a Session" aria-label="Schedule a Session" size="md" color="primary" variant="solid" trailing-icon="i-lucide-calendar" class="font-bold" target="_blank"} + +**What you get:** +- Direct access to serversideup/php maintainers +- 1-hour focused troubleshooting or consulting +- Screen sharing and hands-on help +- Clear next steps and recommendations + +### Ongoing Development & Support + +**Perfect for:** Teams needing continuous development support or complex projects + +Get dedicated access to senior engineers for ongoing development, deployment assistance, and technical support. + +:u-button{to="https://serversideup.net/hire-us/" label="Learn About Retainer Services" aria-label="Learn About Retainer Services" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold" target="_blank"} + +**What's included:** +- 🎨 **Full-Stack Development** - Frontend, backend, and everything in between +- 🏗️ **Application Architecture** - Design scalable, maintainable solutions +- 🎯 **UI/UX Design** - Beautiful, functional interfaces using Figma +- 🐳 **Docker & DevOps** - Container orchestration, CI/CD pipelines, and automation +- 🖥️ **Managed Hosting** - Deploy anywhere (self-hosted or cloud) +- 📊 **Database Design** - Optimize for performance and scale +- 🔒 **Security Hardening** - Production-ready security configurations +- 📱 **Mobile App Development** - iOS & Android using modern frameworks + +**Key advantages:** +- **Run Anywhere** - We specialize in both self-hosted infrastructure and cloud deployments (AWS, Google Cloud, DigitalOcean, etc.) +- **No Vendor Lock-In** - Your infrastructure, your control +- **Fixed Monthly Pricing** - Predictable costs, no hourly billing surprises +- **Development-First** - 90%+ of time spent on actual development, not meetings +- **Complete Stack** - One team handling design, development, deployment, and maintenance + +::note +**Why choose us?** We built serversideup/php and maintain it in production for our own clients. We know these images inside and out because we use them every day for real-world applications. +:: + +## We're Here to Help + +Whether you choose free community support or professional services, we're committed to your success with serversideup/php. Don't hesitate to reach out - we were all beginners once, and there's no such thing as a "stupid question." + +Happy coding! 🚀 + From 25d10e67389c64dd4a26bde72e07be27f6189ded Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 10:09:34 -0500 Subject: [PATCH 135/170] Update installation documentation to clarify definitions of 'Image' and 'Tag' with specific examples, enhancing user understanding of container terminology. --- docs/content/docs/1.getting-started/3.installation.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/docs/1.getting-started/3.installation.md b/docs/content/docs/1.getting-started/3.installation.md index 566549504..e45ed6dac 100644 --- a/docs/content/docs/1.getting-started/3.installation.md +++ b/docs/content/docs/1.getting-started/3.installation.md @@ -28,8 +28,8 @@ There are some important terms to understand when working with containers: | Term | Definition | |------|------------| | Container | A running instance of an image. | -| Image | A template for a container to start with (like serversideup/php). | -| Tag | A specific version of an image. | +| Image | A template for a container to start with (ie. `serversideup/php:8.4-frankenphp`). | +| Tag | A specific version of an image (ie. `8.4-frankenphp`). | | Registry | A repository of images. This is where users can pull images from to start a container. This can be places like [Docker Hub](https://hub.docker.com/r/serversideup/php) or [GitHub Packages](https://github.com/serversideup/docker-php/pkgs/container/php). | If you'd like to learn more about containers, you can learn more following the guide below. From 15f68b4b07009a1d5a7ba3f637403bd7e7351a93 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 10:12:10 -0500 Subject: [PATCH 136/170] Add target="_blank" attribute to external link in app.vue for improved user experience. --- docs/app/app.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/app/app.vue b/docs/app/app.vue index 1f09b7b3b..4e643de29 100644 --- a/docs/app/app.vue +++ b/docs/app/app.vue @@ -10,6 +10,7 @@ to="https://getspin.pro/?ref=docker-php" color="primary" class="text-white" + target="_blank" /> From c56a4e4712b1d10acf723361b85fd73d1b958d42 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 10:14:48 -0500 Subject: [PATCH 137/170] Update code block syntax in documentation from 'yaml' to 'yml' for consistency across various Docker Compose examples. --- .../docs/1.getting-started/2.these-images-vs-others.md | 2 +- docs/content/docs/2.image-variations/fpm.md | 6 +++--- .../docs/3.framework-guides/1.laravel/2.task-scheduler.md | 2 +- docs/content/docs/3.framework-guides/1.laravel/3.queue.md | 2 +- docs/content/docs/3.framework-guides/1.laravel/4.horizon.md | 2 +- docs/content/docs/3.framework-guides/1.laravel/4.reverb.md | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/content/docs/1.getting-started/2.these-images-vs-others.md b/docs/content/docs/1.getting-started/2.these-images-vs-others.md index d3f44097d..672bb5afa 100644 --- a/docs/content/docs/1.getting-started/2.these-images-vs-others.md +++ b/docs/content/docs/1.getting-started/2.these-images-vs-others.md @@ -152,7 +152,7 @@ Our images are built for the wild internet: We've done the hard work of optimizing for PHP's most popular frameworks: **Laravel Automations** -```yaml [compose.yml] +```yml [compose.yml] services: php: image: serversideup/php:8.3-fpm-nginx diff --git a/docs/content/docs/2.image-variations/fpm.md b/docs/content/docs/2.image-variations/fpm.md index 74e6989b4..7fbd392c9 100644 --- a/docs/content/docs/2.image-variations/fpm.md +++ b/docs/content/docs/2.image-variations/fpm.md @@ -157,7 +157,7 @@ spec: ### Health Check The FPM variation includes [`php-fpm-healthcheck`](https://github.com/renatomefi/php-fpm-healthcheck){target="_blank"}, a POSIX-compliant script that monitors PHP-FPM's `/status` endpoint to verify the service is healthy. -```yaml [compose.yml]{7-10} +```yml [compose.yml]{7-10} services: php: image: serversideup/php:8.4-fpm @@ -196,7 +196,7 @@ For a complete list of available environment variables, see the [Environment Var The FPM variation gives you fine-grained control over PHP process management. Here are some tuning tips: ### For High-Traffic Applications -```yaml [compose.yml] +```yml [compose.yml] services: php: image: serversideup/php:8.4-fpm @@ -207,7 +207,7 @@ services: ``` ### For Low-Memory Environments -```yaml [compose.yml] +```yml [compose.yml] services: php: image: serversideup/php:8.4-fpm diff --git a/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md b/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md index 7c36a08ea..0fa52d62c 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md +++ b/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md @@ -31,7 +31,7 @@ Notice we're calling the artisan command explicitly with the full path (`/var/ww :: #### Example & Simplified Docker Compose File -```yaml [docker-compose.yml] +```yml [docker-compose.yml] services: php: image: my/laravel-app diff --git a/docs/content/docs/3.framework-guides/1.laravel/3.queue.md b/docs/content/docs/3.framework-guides/1.laravel/3.queue.md index 26548b114..5067c5de9 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/3.queue.md +++ b/docs/content/docs/3.framework-guides/1.laravel/3.queue.md @@ -28,7 +28,7 @@ Notice we're calling the artisan command explicitly with the full path (`/var/ww :: #### Example & Simplified Docker Compose File -```yaml [docker-compose.yml] +```yml [docker-compose.yml] services: php: image: my/laravel-app diff --git a/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md b/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md index 1cd773482..3a8140b42 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md +++ b/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md @@ -29,7 +29,7 @@ Notice we're calling the artisan command explicitly with the full path (`/var/ww :: #### Example & Simplified Docker Compose File -```yaml [docker-compose.yml] +```yml [docker-compose.yml] services: php: image: my/laravel-app diff --git a/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md b/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md index 1c8613928..b11a52fe6 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md +++ b/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md @@ -29,7 +29,7 @@ Notice Laravel Reverb is running on port `8000`, where as Laravel is running on :: #### Example & Simplified Docker Compose File -```yaml [docker-compose.yml] +```yml [docker-compose.yml] services: php: image: my/laravel-app From c1399e4fc78ce1b46edffda6022c6c335709884d Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 10:26:34 -0500 Subject: [PATCH 138/170] Add common issues troubleshooting guide for Docker images, covering permission issues, port conflicts, and support resources. This documentation aims to assist users in resolving frequent problems encountered while using serversideup/php images. --- .../docs/7.troubleshooting/1.common-issues.md | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 docs/content/docs/7.troubleshooting/1.common-issues.md diff --git a/docs/content/docs/7.troubleshooting/1.common-issues.md b/docs/content/docs/7.troubleshooting/1.common-issues.md new file mode 100644 index 000000000..b6e9002c3 --- /dev/null +++ b/docs/content/docs/7.troubleshooting/1.common-issues.md @@ -0,0 +1,88 @@ +--- +title: Common Issues +description: 'Solutions to frequently encountered problems when using serversideup/php Docker images.' +--- + +## Overview + +This guide covers the most common issues users encounter and their solutions. If you don't find your issue here, check out our [Getting Help](/docs/troubleshooting/getting-help) guide for community and professional support options. + +## Permission Issues + +Permission problems are one of the most common issues when working with Docker containers. They typically manifest as "Permission denied" errors when trying to write files. + +### Understanding the Problem + +By default, these images run as a non-root user (`www-data`) for security. When your host machine uses a different user ID (UID) or group ID (GID), file permission conflicts can occur. + +If your command is failing during build, then you likely need to switch to root to perform root tasks. + +```dockerfile [Dockerfile] +FROM serversideup/php:8.4-fpm-nginx + +USER root + +# Install system packages +RUN install-php-extensions intl bcmath + +# Switch back to www-data +USER www-data +``` + +::warning +Always switch back to a non-root user after completing privileged operations. Running containers as root is a security risk. +:: + +If your container is failing to run during runtime, then you may have a more advanced permissions issue. See our guide on understanding file permissions. + +:u-button{to="/docs/guide/understanding-file-permissions" label="Understanding File Permissions" aria-label="Understanding File Permissions" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## Port Already in Use + +### Error Message + +``` +Error starting userland proxy: listen tcp 0.0.0.0:80: bind: address already in use +``` + +### Solution + +Another process is using the port. Find and stop it, or use a different port: + +**Find what's using the port:** + +```bash +# On Linux/macOS +sudo lsof -i :80 + +# On Windows +netstat -ano | findstr :80 +``` + +**If you must use a different port:** + +```yaml [compose.yml] {4-6} +services: + php: + image: serversideup/php:8.4-fpm-nginx + ports: + - "8080:8080" # Use port 8080 instead + - "8443:8443" +``` + +Access your application at `http://localhost:8080`. + +## Getting More Help + +If your issue isn't covered here: + +1. **Search GitHub Discussions** - Someone may have encountered the same problem +2. **Check the Documentation** - Review guides specific to your setup +3. **Ask the Community** - Post in GitHub Discussions or Discord +4. **Review Container Logs** - Most issues show helpful error messages + +:u-button{to="/docs/troubleshooting/getting-help" label="View All Support Options" aria-label="View All Support Options" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +::tip +When asking for help, always include your image version, `compose.yml`, relevant error messages, and what you've already tried. This helps others help you faster! +:: From 8c59bb8ab02151a0f8267b9baa4cefd43d9f914a Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 10:26:53 -0500 Subject: [PATCH 139/170] Update PHP image version in documentation from 8.3 to 8.4 for Docker Compose example, ensuring users have the latest configuration details. --- docs/content/docs/1.getting-started/2.these-images-vs-others.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/1.getting-started/2.these-images-vs-others.md b/docs/content/docs/1.getting-started/2.these-images-vs-others.md index 672bb5afa..f1d42394e 100644 --- a/docs/content/docs/1.getting-started/2.these-images-vs-others.md +++ b/docs/content/docs/1.getting-started/2.these-images-vs-others.md @@ -155,7 +155,7 @@ We've done the hard work of optimizing for PHP's most popular frameworks: ```yml [compose.yml] services: php: - image: serversideup/php:8.3-fpm-nginx + image: serversideup/php:8.4-fpm-nginx environment: # Run migrations, storage link, caching, and more AUTORUN_ENABLED: "true" From ebe579f4b1a24ff3b5713943c8b62489da043811 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 10:28:29 -0500 Subject: [PATCH 140/170] Add documentation for using S6 Overlay with Docker PHP images, explaining its benefits, process management, and comparison with Supervisor. The guide covers initialization, health reporting, and customization options to enhance user understanding of multi-process containerization. --- .../docs/5.guide/2.using-s6-overlay.md | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 docs/content/docs/5.guide/2.using-s6-overlay.md diff --git a/docs/content/docs/5.guide/2.using-s6-overlay.md b/docs/content/docs/5.guide/2.using-s6-overlay.md new file mode 100644 index 000000000..b14a1f35b --- /dev/null +++ b/docs/content/docs/5.guide/2.using-s6-overlay.md @@ -0,0 +1,96 @@ +--- +head.title: 'Using S6 Overlay - Docker PHP - Server Side Up' +description: 'Learn about S6 Overlay and how it is used in this project.' +layout: docs +--- + +## What's S6 Overlay? +[S6 Overlay](https://github.com/just-containers/s6-overlay) is a process supervisor designed for containerization from the ground up. It's a modern alternative to [Supervisor (aka Supervisord)](https://supervisord.org/). + +S6 Overlay is a perfect match for running PHP because it usually requires running multiple processes together. + +## What images do you use S6 Overlay with? +We only use S6 Overlay for images that need two processes to run a service. This includes: +- `serversideup/php:*-fpm-apache` +- `serversideup/php:*-fpm-nginx` + +## Why does PHP need multiple processes? +Serving a PHP application can be broken down into two different components: +1. The PHP Application Itself +2. The static files that go with it (JavaScript, images, etc) + +There are ways to have these components served together with Apache modules like "mod_php". As time moved on, we found this to be very resource inefficient. + +Running "mod_php" with Apache meant that even when a JavaScript file needs to be loaded, Apache would load PHP to serve that file. This caused a lot of unnecessary memory and CPU usage for files that didn't need PHP to be served. + +### PHP-FPM +PHP-FPM was the answer to make this serving a PHP application more efficient. This allowed PHP apps to be served with a lot less memory and CPU overhead. + +Although this method was more efficient, it meant we still need something to serve our static content. This is where we turned to "reverse proxies". + +### Reverse proxy +Reverse proxies are servers that route traffic based on the request. To make things more confusing, you can have a web server be a reverse proxy and a web server at the same time (this is how we run NGINX). You can even configure Apache to run as a web server and a reverse proxy too (we run our `php:*-fpm-apache` images like this). + +![Reverse Proxy Diagram](images/docs/reverse-proxy.svg) + +In the example above, you can see the web request coming in from the top. NGINX is our first stop where it inspects the request. + +#### Static Files +If the request is for a static file (jpeg, js, png, etc), NGINX will also serve that file for us without loading PHP-FPM. This makes the request very fast and efficient. + +#### PHP Files +If the request ends in `.php`, then it will send the request over to PHP-FPM. PHP-FPM will then execute the PHP file and return a response to the original client, all passed through NGINX. + +## Shouldn't containers only have one process? +In a perfect world, that would be ideal -- but this isn't always realistic. You can see in the example above we need two things running: +1. NGINX: To serve static files +1. PHP-FPM: To serve PHP application + +If you want to replicate your application without the added complexity of multiple physical servers, etc -- you need something like S6 Overlay to properly bring up the processes and ensure your application service health is accurately reported. + +[S6 Overlay's philosophy](https://github.com/just-containers/s6-overlay#the-docker-way){target="_blank"} is a perfect match when it comes to running PHP: + +- A container should do ***one thing*** (which may contain multiple processes). When that one thing stops, the container should also stop. + +## The advantages of S6 Overlay +When we configure PHP to run with the S6 Overlay system, we get a number of advantages: + +- ✅ S6 Overlay was designed from the ground up to run within containers +- ✅ We get explicit control to run small scripts or configurations before/after the main processes start +- ✅ We get a better confidence on answering "Is my container actually healthy?" + +## This disadvantage of S6 Overlay + +- ❌ S6 Overlay may not be compatible with all PaaS providers, depending on how they run their containers ([see this comment from the S6 Overlay creator](https://github.com/just-containers/s6-overlay/issues/535#issuecomment-1597680218){target="_blank"}) + +## S6 Overlay vs. Supervisor +Many people flock to Supervisor, which was a very popular option before containerization. Here's some examples why you may want to trade Supervisor for S6 Overlay: + +### How Supervisor reports container health +![Supervisor Container Health Example](images/docs/supervisor-container.svg) + +When you bring up Supervisord within a container, it will be assigned `PID 1`. Then Supervisor will bring up child processes with it. + +During a failure, Supervisor can be configured to restart the child process to attempt recovery, but the container orchestrator thinks the container is still healthy because `supervisord` is occupying `PID 1` which is still healthy. + +**👉 This design can lead to inaccurate container health statuses during a failure.** + +### How S6 Overlay reports container health +![S6 Overlay Container Health Example](images/docs/s6-overlay-container.svg) +S6 Overlay was designed to be run in containers from the ground up. S6 Overlay can also attempt recovery, but it is more accurate on determining container health compared to Supervisor. + +**👍 By design, S6 Overlay can accurately detect a failure and exit (which is what we want when our app fails).** + +## Customizing the initialization process +![Container Initialization Example with S6 Overlay](images/docs/container-init.svg) +Since S6 Overlay was designed around the idea of containerization, there are also a number of other advantages to properly time your customizations during container startup. + +S6 Overlay has a number of options to [write our own service script](https://github.com/just-containers/s6-overlay/tree/master#writing-a-service-script){target="_blank"} and properly time everything. + +In the example above, you can see we have a `runas-user` script which helps us customize and set custom UIDs and GIDs for our file permissions. At the same time, `laravel-automations` executes to see if there are any automated migrations to run. + +Both scripts must finish successfully before S6 Overlay starts our main `php-fpm` process, which has both scripts listed as a dependency. + +As you can see this structure can be very powerful in making your own customizations. This is great for giving you full control of how you'd like your application to behave. + +:u-button{to="/docs/customizing-the-image/changing-common-php-settings" label="Changing Common PHP Settings" aria-label="Changing Common PHP Settings" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file From 41537a0720c1d5b9f38dfab9b882a17e1bb6fb72 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 10:33:03 -0500 Subject: [PATCH 141/170] Add documentation for native Docker health checks in Laravel, detailing health check commands, default settings, and usage examples for Laravel services like Horizon, Reverb, Scheduler, and Queue. This guide aims to enhance application reliability and facilitate zero-downtime deployments. --- .../2.using-healthchecks-with-laravel.md | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 docs/content/docs/5.guide/2.using-healthchecks-with-laravel.md diff --git a/docs/content/docs/5.guide/2.using-healthchecks-with-laravel.md b/docs/content/docs/5.guide/2.using-healthchecks-with-laravel.md new file mode 100644 index 000000000..15b7b8d68 --- /dev/null +++ b/docs/content/docs/5.guide/2.using-healthchecks-with-laravel.md @@ -0,0 +1,111 @@ +--- +head.title: 'Native Docker Health Checks for Laravel - Docker PHP - Server Side Up' +description: 'Stop guessing if Laravel is up and running. Our health checks have you covered to ensure Laravel is running properly. It supports HTTP checks, Laravel Horizon, Reverb, Scheduler, and Queue.' +layout: docs +--- + +## Native Docker Health Checks for Laravel +::lead-p +Dialing in health checks are very important for ensuring your application is running smoothly and that you're able to deploy updates without any downtime. This guide will explain how our health checks work and how you can use them to your advantage. +:: + +:iframe{src="https://www.youtube-nocookie.com/embed/cuYIB5VrH1Q?si=75VBCKAe5x2Hmckd" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen style="aspect-ratio: 16/9;"} + +## What are Health Checks? + +Health checks are a way to check the status of your application. Whenever a container is started, a health check is performed. If the health check fails, the container will be restarted or marked as unhealthy. Health checks are very important for rolling updates and ensuring your application can start up in order if you have services that depend on each other. + +## Our Health Checks +We offer a number of health check commands, specifically for Laravel. You can find these commands are prefixed with `healthcheck-` and are located in [`/usr/local/bin`](https://github.com/serversideup/docker-php/tree/main/src/common/usr/local/bin){target="_blank"}. The examples below show how to use these health checks in your `docker-compose.yml` file, but you can also use them in other environments. + +## Default Health Check Settings +By default, our Dockerfiles ship with the following health check commands: + +| Variation | Health Check Command | +| --------- | -------------------- | +| `cli` | (none) | +| `fpm` | [`php-fpm-healthcheck`](https://github.com/renatomefi/php-fpm-healthcheck){target="_blank"} | +| `fpm-apache` | `curl --insecure --silent --location --show-error --fail http://localhost:8080$HEALTHCHECK_PATH` | +| `fpm-nginx` | `curl --insecure --silent --location --show-error --fail http://localhost:8080$HEALTHCHECK_PATH` | +| `frankenphp` | `curl --insecure --silent --location --show-error --fail http://localhost:8080$HEALTHCHECK_PATH` | + +::note +Notice how `fpm-apache`, `fpm-nginx`, and `frankenphp` have a `$HEALTHCHECK_PATH` variable? This is because you can specify a path for the health check to validate. +:: + +## Changing the Health Check Path +By default, you can see our [Environment Variable Specification](/docs/reference/environment-variable-specification) shows the `HEALTHCHECK_PATH` variable is set to `/healthcheck`. + +::tip +This only validates that FPM-NGINX or FPM-APACHE are running and ready to accept connections. It does not validate that Laravel is running or healthy. +:: + +If you are using Laravel, [modern versions of Laravel will ship with a `/up` route](https://laravel.com/docs/12.x/deployment#the-health-route){target="_blank"} that you can use to validate that Laravel is running and healthy. + +You can even create your own custom path in your application if you want. As long as the path returns a 200 status code, the health check will be successful. + +## Advanced Laravel Services +Since it is good practice to use the same Docker image for all our services, we also make additional health checks for Laravel's advanced services. If you're looking for rolling updates with zero downtime, it's very important to use these health checks. + +### Laravel Horizon +We utilize the `artisan horizon:status` command to check the status of Laravel Horizon. This is a command native to Laravel Horizon and is used to determine if the Horizon process is running. + +To run this command automatically, you can call our health check command in your `docker-compose.yml` file. + +```yml +healthcheck: + test: ["CMD", "healthcheck-horizon"] +``` + +[See a full example of configuring Laravel Horizon →](/docs/framework-guides/laravel/horizon) + +### Laravel Reverb +We use `pgrep` to check if the `reverb:start` command is running. This ensures the Reverb process is running and ready to accept connections. + +To run this command automatically, you can call our health check command in your `docker-compose.yml` file. + +::code-panel +--- +label: Using Healthcheck with Laravel Reverb +--- +```yml +healthcheck: + test: ["CMD", "healthcheck-reverb"] +``` +:: + +[See a full example of configuring Laravel Reverb →](/docs/framework-guides/laravel/reverb) + +### Laravel Scheduler +We use `pgrep` to check if the `schedule:work` command is running. This ensures the scheduler process is running. + +To run this command automatically, you can call our health check command in your `docker-compose.yml` file. + +::code-panel +--- +label: Using Healthcheck with Laravel Scheduler +--- +```yml +healthcheck: + test: ["CMD", "healthcheck-schedule"] +``` +:: + +[See a full example of configuring Laravel Scheduler →](/docs/framework-guides/laravel/task-scheduler) + +### Laravel Queue +We use `pgrep` to check if the `queue:work` command is running. This ensures the queue process is running. + +To run this command automatically, you can call our health check command in your `docker-compose.yml` file. + +::code-panel +--- +label: Using Healthcheck with Laravel Queue +--- +```yml +healthcheck: + test: ["CMD", "healthcheck-queue"] +``` +:: + +[See a full example of configuring Laravel Queue →](/docs/framework-guides/laravel/queue) From 3bd3cf7dcd630ace2545cd125d726ed402204d45 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 10:35:32 -0500 Subject: [PATCH 142/170] Add migration guide from v2 to v3 for serversideup/php images, detailing new features, breaking changes, and a comprehensive migration checklist. This documentation aims to assist users in transitioning smoothly to the latest version while highlighting important updates and configuration adjustments. --- .../5.guide/99.migrating-from-v2-to-v3.md | 170 ++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 docs/content/docs/5.guide/99.migrating-from-v2-to-v3.md diff --git a/docs/content/docs/5.guide/99.migrating-from-v2-to-v3.md b/docs/content/docs/5.guide/99.migrating-from-v2-to-v3.md new file mode 100644 index 000000000..60d1a559f --- /dev/null +++ b/docs/content/docs/5.guide/99.migrating-from-v2-to-v3.md @@ -0,0 +1,170 @@ +--- +head.title: 'Migrating from v2 - Server Side Up' +description: 'Learn how to migrate from serversideup/php v2 images to v3.' +layout: docs +title: Migrating from v2 +--- +::lead-p +If you're moving from v2 of serversideup/php to the latest version, there are a number of changes you should be aware of. We've tried to keep these to a minimum, but some of these changes were necessary to make the project more maintainable and easier to use. +:: + +## Preparing for the migration +If you're an existing user of our v2 images, be sure that your current configurations are NOT set to use the latest images. To do this, you can lock your images into the `v2.2.1` tag. This will ensure that you're not automatically upgraded to the v3 images. + +For example, if you are using `8.2-fpm-nginx`, you would change your `docker-compose.yml` file to use the [`v2.2.1`](https://hub.docker.com/r/serversideup/php/tags?page=1&name=2.2.1){target="_blank"} tag: + +```yml [docker-compose.yml] {3} +services: + php: + image: serversideup/php:8.2-fpm-nginx + ports: + - 80:80 + volumes: + - .:/var/www/html +``` + +```yml [docker-compose.yml] {3} +services: + php: + image: serversideup/php:8.2-fpm-nginx-v2.2.1 + ports: + - 80:80 + volumes: + - .:/var/www/html +``` + +All you need to do is add `-v2.2.1` to the end of the image tag. This will ensure that you're not automatically upgraded to the v3 images. + +## New Features +We've been busy overhauling our PHP Docker Images to make them more production-ready and easier to use. Here are some of the new features we've added: +- **Based on official PHP Images** - We're now building an improved developer experience on top of the official PHP Docker images. +- **Unprivileged by default** - We're now running our images as an unprivileged user by default. This is a huge step forward in security and compatibility. +- **PHP 8.4 support** - We're now shipping the latest and greatest. +- **Pin to the exact minor version** - Pin your app to the exact minor version of PHP that you want to use. This means you can pin to `8.2.12` instead of `8.2`. +- **Easier start up script customization** - We now have a folder called `/etc/entrypoint.d` that allows you to easily customize your container with scripts. Just put them in numerical order and we'll execute any shell script you want. No S6 Overlay knowledge required. +- **Expanded Laravel Automations** - We added automations to run `config:cache`, `route:cache`, `view:cache`, `event:cache`, `migrate --force --isolated`, and `storage:link` +- **NGINX Unit Support** - We're offering NGINX Unit as a variation as an alternative to PHP-FPM. This allows you to run PHP applications without the need for a webserver like NGINX or Apache to run with PHP-FPM. +- **Available on GitHub Packages** - We're now publishing our images to GitHub Packages. This means you can use our images without needing to authenticate with Docker Hub. + +## Breaking changes +::caution +The following changes are considered to be "breaking changes" and will require you to make changes to your application. +:: + +### Ubuntu is no longer used as a base image +We now use Debian or Alpine as our base OS (because we're using the official PHP images as a base). This is a huge change, but we're confident this will be the best direction moving forward. + +### `ppa:ondrej/php` is no longer used +Since we're using PHP.net as the "official source of truth" for getting our PHP versions, this means we're also dropping support for the `ppa:ondrej/php` repository. If you're using things like `apt-get install php-redis` you will need to change your method of installing PHP extensions. + +[Learn how to install your own PHP extension →](/docs/customizing-the-image/installing-additional-php-extensions) + +### `webuser` is no longer being used +We used to add a user called `webuser` with the UID of `9999` with shell permissions. To increase security, we're now using the `www-data` user and group that is built into the official PHP images. If you have mounted volumes, you will need to `chown` the files to match the ID of the `www-data` user and groups. For Debian, this is `33:33` and for Alpine, this is `82:82`. + +### NGINX and Apache listen on 8080 (HTTP) and 8443 (HTTPS) by default +Our images are now unprivileged by default. This is a major step forward in security and compatibility. Since we are unprivileged by default, we lose the ability to mount on ports less than 1024. If you're using NGINX or Apache, you will need to update your port mappings to use `8080` and `8443` instead of `80` and `443`. + +[Learn more about this change →](/docs/getting-started/default-configurations#unprivileged-by-default) + +### S6 Overlay is only used in `*-fpm-apache` and `*-fpm-nginx` images +Due to compatibility issues, we only use S6 Overlay in our `*-fpm-apache` and `*-fpm-nginx` images. If you were using S6 Overlay for our other variations (cli, fpm, etc), you will need to migrate your scripts to use the new `/etc/entrypoint.d` folder. + +### `SSL_MODE` is now set to `off` by default (HTTP only) +Running end-to-end SSL by default created more problems than good. By default, we're now shipping HTTP-only by default with the option for people to turn this on. + +### `AUTORUN_ENABLED` is now set to `false` by default. +Having this set to "true" by default also created more problems than good. If you want to use any of the Laravel Automation Scripts, be sure to set this to `true`. + +### MSMTP is no longer included in the images +For security and image size reasons, we removed MSMTP from the images. If you need to send emails, use an external SMTP service like Postmark/Sendgrid/Mailgun. You can also extend the image yourself to include MSMTP specifically for your use case. + +### Variable deprecations +- `WEB_APP_DIRECTORY` has now been renamed to `APP_BASE_DIR` +- `DEBUG_OUTPUT` has been removed for in favor of `LOG_OUTPUT_LEVEL=debug` +- `PUID` & `PGID` are no longer used because it requires root privileges. See the [new way to set the UID and GID →](/docs/guide/understanding-file-permissions) +- `MSMTP_RELAY_SERVER_HOSTNAME` & `MSMTP_RELAY_SERVER_PORT` are no longer used because MSMTP is no longer included in the images. +- `PHP_POOL_NAME` has been renamed to `PHP_FPM_POOL_NAME` + +## Migration Checklist +Here is a good list to perform the migration + +#### Repository +- Ensure you're committing to a test environment + +#### Docker Compose +- Update the image name (if applicable) +- Check each environment variable exists and is set to a proper value [See the full list of environment variables →](/docs/reference/environment-variable-specification) +- Ensure you updated the ports to `8080` and `8443` for NGINX, Apache, and Unit +- Consider adding `PHP_OPCACHE_ENABLE=1` to your production environment for increased performance + +#### Dockerfile +- Update the base image name (if applicable) +- Remove any `ppa:ondrej/php` references +- Remove any Ubuntu specific commands +- Ensure all extensions are installed with the `install-php-extensions` command [Learn how to install your own PHP extension →](/docs/customizing-the-image/installing-additional-php-extensions) +- Ensure your `COPY` commands are copying with the correct permissions (i.e. `--chown=www-data:www-data`) + +#### CI/CD +If you're running `fpm-nginx` (or similar) on a runner that's running as your builds as `root`, you may need to add `user = www-data` and `group = www-data` to your `php-fpm.conf` file so you can bring FPM up correctly. + +If you have to run things as root in CI, you can do this with a multi stage build and set the targets: + + +```dockerfile [Dockerfile] +############################################ +# Base Image +############################################ + +# Learn more about the Server Side Up PHP Docker Images at: +# https://serversideup.net/open-source/docker-php/ +FROM serversideup/php:8.4-fpm-nginx AS base + +## Uncomment if you need to install additional PHP extensions +# USER root +# RUN install-php-extensions bcmath gd + +############################################ +# Development Image +############################################ +FROM base AS development + +# We can pass USER_ID and GROUP_ID as build arguments +# to ensure the www-data user has the same UID and GID +# as the user running Docker. +ARG USER_ID +ARG GROUP_ID + +# Switch to root so we can set the user ID and group ID +USER root +RUN docker-php-serversideup-set-id www-data $USER_ID:$GROUP_ID && \ + docker-php-serversideup-set-file-permissions --owner $USER_ID:$GROUP_ID +USER www-data + +############################################ +# CI image +############################################ +FROM base AS ci + +# Sometimes CI images need to run as root +# so we set the ROOT user and configure +# the PHP-FPM pool to run as www-data +USER root +RUN echo "user = www-data" >> /usr/local/etc/php-fpm.d/docker-php-serversideup-pool.conf && \ + echo "group = www-data" >> /usr/local/etc/php-fpm.d/docker-php-serversideup-pool.conf + +############################################ +# Production Image +############################################ +FROM base AS deploy +COPY --chown=www-data:www-data . /var/www/html +USER www-data +``` + +#### Production/Staging Servers +- Update all host volume file permissions to match the `www-data` UID/GID (`33:33` for Debian, `82:82` for Alpine) [Learn how to manage file permissions](/docs/guide/understanding-file-permissions) +- If you're running Docker Swarm with host volume mounts, we created a script that could potentially help ([change-volume-permissions.sh](https://github.com/serversideup/docker-volume-change-permission-script)) + +#### Deployment +- CI/CD with valid tests is always encouraged +- After completing all steps above, you're now ready to deploy the new images From 7fdf21b0e62ccb84345e8f06790abc599f891b07 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 10:39:14 -0500 Subject: [PATCH 143/170] Refactor health check documentation for Laravel in Docker Compose examples, enhancing clarity by adding service configuration comments and standardizing code block syntax. --- .../2.using-healthchecks-with-laravel.md | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/docs/content/docs/5.guide/2.using-healthchecks-with-laravel.md b/docs/content/docs/5.guide/2.using-healthchecks-with-laravel.md index 15b7b8d68..9645f4a03 100644 --- a/docs/content/docs/5.guide/2.using-healthchecks-with-laravel.md +++ b/docs/content/docs/5.guide/2.using-healthchecks-with-laravel.md @@ -52,7 +52,8 @@ We utilize the `artisan horizon:status` command to check the status of Laravel H To run this command automatically, you can call our health check command in your `docker-compose.yml` file. -```yml +```yml [docker-compose.yml] +## Rest of your service configuration... healthcheck: test: ["CMD", "healthcheck-horizon"] ``` @@ -64,15 +65,11 @@ We use `pgrep` to check if the `reverb:start` command is running. This ensures t To run this command automatically, you can call our health check command in your `docker-compose.yml` file. -::code-panel ---- -label: Using Healthcheck with Laravel Reverb ---- -```yml +```yml [docker-compose.yml] +## Rest of your service configuration... healthcheck: test: ["CMD", "healthcheck-reverb"] ``` -:: [See a full example of configuring Laravel Reverb →](/docs/framework-guides/laravel/reverb) @@ -81,15 +78,11 @@ We use `pgrep` to check if the `schedule:work` command is running. This ensures To run this command automatically, you can call our health check command in your `docker-compose.yml` file. -::code-panel ---- -label: Using Healthcheck with Laravel Scheduler ---- -```yml +```yml [docker-compose.yml] +## Rest of your service configuration... healthcheck: test: ["CMD", "healthcheck-schedule"] ``` -:: [See a full example of configuring Laravel Scheduler →](/docs/framework-guides/laravel/task-scheduler) @@ -98,14 +91,10 @@ We use `pgrep` to check if the `queue:work` command is running. This ensures the To run this command automatically, you can call our health check command in your `docker-compose.yml` file. -::code-panel ---- -label: Using Healthcheck with Laravel Queue ---- -```yml +```yml [docker-compose.yml] +## Rest of your service configuration... healthcheck: test: ["CMD", "healthcheck-queue"] ``` -:: [See a full example of configuring Laravel Queue →](/docs/framework-guides/laravel/queue) From 170de94c31aaa1f74729c0103b8e5b785647ea11 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 14:04:06 -0500 Subject: [PATCH 144/170] Add comprehensive documentation on container fundamentals, including concepts of images vs containers, image layers, volumes, ports, environment variables, and the container lifecycle. This update enhances user understanding of Docker and prepares them for deploying applications from development to production. --- .../1.container-basics.md | 127 ++++++++++++++++-- 1 file changed, 119 insertions(+), 8 deletions(-) diff --git a/docs/content/docs/4.deployment-and-production/1.container-basics.md b/docs/content/docs/4.deployment-and-production/1.container-basics.md index a7c72d0cb..14b9956b3 100644 --- a/docs/content/docs/4.deployment-and-production/1.container-basics.md +++ b/docs/content/docs/4.deployment-and-production/1.container-basics.md @@ -31,18 +31,129 @@ Although you may see us reference things as "Docker containers", we're actually So although we're going to show you best practices with Docker, this means you'll maintain your freedom and flexibility to choose how you want to run your containers. -## How to get started with Docker -At first, Docker may seem a little intimidating, but don't let that stop you. Docker is one of the most powerful skill-sets that we've learned in our career. +## How containers work +If you followed our [installation guide](/docs/getting-started/installation), you've already run containers and seen them in action. Let's break down what actually happened when you ran `docker compose up`. -Although teaching you how to use Docker is beyond the scope of serversideup/php, we've actually created another open source project called [Spin](https://serversideup.net/open-source/spin/) that dramatically reduces the learning curve for getting started and self-hosting with Docker on any VPS provider. +### Images vs Containers +Think of an **image** as a blueprint and a **container** as the actual running instance of that blueprint. When you specified `image: serversideup/php:8.3-fpm-nginx` in your `compose.yml`, you told Docker to: -::callout -These images work with any Docker setup — Docker Compose, Docker Swarm, Kubernetes, and more. In the demo below, we're using Spin to quickly demonstrate running Docker from development to production on any VPS provider. **Spin is NOT required** to use these images, but it's a great tool to help you get started with Docker. +1. Download the `serversideup/php:8.3-fpm-nginx` image (the blueprint) +2. Create a container from that image (the running instance) +3. Start the container with your specified configuration + +You can create multiple containers from the same image — just like you can build multiple houses from the same blueprint. Each container runs independently with its own isolated filesystem and processes. + +### Understanding image layers +Container images are built in layers, like a stack of pancakes. Each layer adds something new: the operating system, PHP, web servers, and configurations. When you pull an image, Docker downloads only the layers you don't already have, making updates incredibly efficient. + +This is why switching from PHP 8.3 to 8.4 in the installation guide was so fast — most of the layers were already on your machine, and Docker only downloaded the differences. + +::tip +Image tags like `8.3-fpm-nginx` and `8.4-frankenphp` aren't just version numbers — they describe the entire stack that's included in that image. The tag tells you the PHP version and which variation (web server stack) you're getting. +:: + +## Key container concepts + +### Volumes: Sharing files with containers +When you added this to your `compose.yml`: + +```yml +volumes: + - ./:/var/www/html +``` + +You created a **bind mount** that connects your local project directory to the container's `/var/www/html` directory. This means: + +- Changes you make on your computer are instantly visible inside the container +- The container serves your actual project files, not a copy +- When the container stops, your files remain on your computer + +This is perfect for development because you can edit files with your favorite editor and see changes immediately without rebuilding the container. + +::note +In production, you'll typically build your application files directly into the image instead of using volumes. We cover this in our [packaging guide](/docs/deployment-and-production/packaging-your-app-for-deployment). :: +### Ports: Accessing your container +The `ports` configuration maps ports between your computer and the container: + +```yml +ports: + - 80:8080 +``` + +This means "take port 8080 inside the container and make it available on port 80 on my computer." When you visited `http://localhost` in your browser, you were actually connecting to port 80 on your computer, which Docker forwarded to port 8080 inside the container where NGINX or FrankenPHP was listening. + +::warning +Only one service can use a port at a time. If you get a "port already in use" error, another service on your computer is already using that port. Try using a different port like `8000:8080`. +:: + +### Environment variables: Configuring your container +Environment variables let you configure your container without modifying the image. When you set: + +```yml +environment: + PHP_UPLOAD_MAX_FILE_SIZE: "500M" + PHP_OPCACHE_ENABLE: "1" +``` -:iframe{src="https://www.youtube-nocookie.com/embed/5z2JoEt5XIk?si=u5v-bDN-cMv0OE-C" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen style="aspect-ratio: 16/9; width: 100%;"} +You're telling our PHP images to adjust PHP's configuration. Our images read these variables at startup and automatically configure PHP accordingly. This means the same image can be configured differently for development, staging, and production — just by changing environment variables. + +::tip +Check out our [Environment Variable Specification](/docs/reference/environment-variable-specification) to see all available configuration options. +:: + +## The container lifecycle +Understanding the lifecycle helps you work more effectively with containers: + +1. **Create & Start** - `docker compose up` creates and starts containers +2. **Running** - Your application is active and serving requests +3. **Stop** - `docker compose down` stops containers (but keeps configurations) +4. **Remove** - Containers are deleted (but images remain for faster restarts) + +Important to know: +- Stopping a container doesn't delete it — it's just paused +- Restarting is fast because the image is already downloaded +- Any data stored inside the container (not in volumes) is lost when the container is removed +- Your images remain on your machine until you explicitly remove them + +## Common Docker commands +Here are the essential commands you'll use regularly: + +```bash [Terminal] +# Start containers (creates if they don't exist) +docker compose up + +# Start in background (detached mode) +docker compose up -d + +# Stop and remove containers +docker compose down + +# View running containers +docker compose ps + +# View container logs +docker compose logs + +# Follow logs in real-time +docker compose logs -f + +# Execute a command in a running container +docker compose exec php php -v + +# Rebuild containers after image changes +docker compose up --build + +# Remove images to force fresh download +docker compose down --rmi all +``` + +::tip +The `-f` flag in `docker compose logs -f` means "follow" — it keeps showing new log entries as they happen. Press :kbd{value="ctrl"} + :kbd{value="C"} to stop following. +:: -Spin is free and open source, and it's a great way to get started with Docker if you're looking for a free method to deploy to any VPS provider. +## What's next? +Now that you understand the fundamentals of containers, you're ready to learn how to take your application from development to production. Our next guide walks you through the entire journey, showing you how to package your application properly and deploy it with confidence. -:u-button{to="https://serversideup.net/open-source/spin/" label="Learn more about Spin" aria-label="Learn more about Spin" target="_blank" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file +:u-button{to="/docs/deployment-and-production/development-to-production" label="Development to Production Guide" aria-label="Development to Production Guide" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} From cc5c1ea3643908d6f5cf460b0aec0e995d645780 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 14:22:34 -0500 Subject: [PATCH 145/170] Update container basics documentation to reflect the change from PHP image version 8.3 to 8.4, and clarify the container stopping behavior. Additionally, enhance the environment variable tip with a direct link to the specification for better user guidance. --- .../docs/4.deployment-and-production/1.container-basics.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content/docs/4.deployment-and-production/1.container-basics.md b/docs/content/docs/4.deployment-and-production/1.container-basics.md index 14b9956b3..364b87024 100644 --- a/docs/content/docs/4.deployment-and-production/1.container-basics.md +++ b/docs/content/docs/4.deployment-and-production/1.container-basics.md @@ -37,7 +37,7 @@ If you followed our [installation guide](/docs/getting-started/installation), yo ### Images vs Containers Think of an **image** as a blueprint and a **container** as the actual running instance of that blueprint. When you specified `image: serversideup/php:8.3-fpm-nginx` in your `compose.yml`, you told Docker to: -1. Download the `serversideup/php:8.3-fpm-nginx` image (the blueprint) +1. Download the `serversideup/php:8.4-fpm-nginx` image (the blueprint) 2. Create a container from that image (the running instance) 3. Start the container with your specified configuration @@ -99,7 +99,7 @@ environment: You're telling our PHP images to adjust PHP's configuration. Our images read these variables at startup and automatically configure PHP accordingly. This means the same image can be configured differently for development, staging, and production — just by changing environment variables. -::tip +::tip{to="/docs/reference/environment-variable-specification"} Check out our [Environment Variable Specification](/docs/reference/environment-variable-specification) to see all available configuration options. :: @@ -112,7 +112,7 @@ Understanding the lifecycle helps you work more effectively with containers: 4. **Remove** - Containers are deleted (but images remain for faster restarts) Important to know: -- Stopping a container doesn't delete it — it's just paused +- Stopping a container doesn't always delete it - Restarting is fast because the image is already downloaded - Any data stored inside the container (not in volumes) is lost when the container is removed - Your images remain on your machine until you explicitly remove them From 4867bf767df55b0ff3f35dde6b54bc011210f869 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 14:30:57 -0500 Subject: [PATCH 146/170] Add documentation for packaging PHP applications for deployment, detailing the transition from development to production images, creating Dockerfiles, best practices, and image versioning strategies. This guide aims to enhance user understanding of building secure and reliable Docker images for production environments. --- .../3.packaging-your-app-for-deployment.md | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 docs/content/docs/4.deployment-and-production/3.packaging-your-app-for-deployment.md diff --git a/docs/content/docs/4.deployment-and-production/3.packaging-your-app-for-deployment.md b/docs/content/docs/4.deployment-and-production/3.packaging-your-app-for-deployment.md new file mode 100644 index 000000000..1c0d20b62 --- /dev/null +++ b/docs/content/docs/4.deployment-and-production/3.packaging-your-app-for-deployment.md @@ -0,0 +1,167 @@ +--- +title: Packaging Your App for Deployment +description: 'Learn how to properly package your PHP application into production-ready Docker images.' +layout: docs +--- + +::lead-p +In development, you mount your code as a volume for instant changes. In production, you build your code directly into the image for security, reliability, and portability. This guide shows you how to make that transition. +:: + +## Development vs production images +Let's revisit what you've been doing in development and why it changes for production. + +### What you've been doing (development) +In the [installation guide](/docs/getting-started/installation), your `compose.yml` looked like this: + +```yml [compose.yml] +services: + php: + image: serversideup/php:8.4-fpm-nginx + ports: + - 80:8080 + volumes: + - ./:/var/www/html # Your code mounted as a volume +``` + +This works great for development because: +- You edit files on your computer and see changes instantly +- No rebuild needed between changes +- Fast iteration and debugging + +### What you need for production +For production, you'll create a **custom image** that includes your application code: + +```dockerfile [Dockerfile] +FROM serversideup/php:8.4-fpm-nginx + +# Copy your application code into the image +COPY --chown=www-data:www-data . /var/www/html +``` + +This is better for production because: +- Your code can't be accidentally modified or deleted +- The image is completely portable and self-contained +- You can version and tag each release +- Deployments are atomic — the new version either works or it doesn't + +## Creating your first production Dockerfile +Let's create a proper production Dockerfile step by step. Start by creating a file called `Dockerfile` in your project root. + +::tip +The `Dockerfile` should live at the root of your project, in the same directory as your `compose.yml`. +:: + +### Basic PHP application +For a simple PHP application, your Dockerfile might look like this: + +```dockerfile [Dockerfile] +FROM serversideup/php:8.4-fpm-nginx + +# Switch to root to install dependencies and copy files +USER root + +# Install PHP dependencies +RUN install-php-extensions intl bcmath + +# Switch back to non-root user for security +USER www-data + +# Copy application files with correct ownership +COPY --chown=www-data:www-data . /var/www/html +``` + +That's it! This takes your application code and bakes it into the image. + +::note +Notice we use `--chown=www-data:www-data` when copying files. This ensures the web server can read your files. Learn more in our [file permissions guide](/docs/guide/understanding-file-permissions). +:: + +## Building your image +Once you have your Dockerfile, build your image with: + +```bash [Terminal] +docker build -t my-app:latest . +``` + +This creates an image tagged as `my-app:latest` that contains your application code. + +### Testing your production image +Before deploying, test your production image locally: + +```yml [compose.prod.yml] +services: + php: + # Use your custom image instead of the base image + image: my-app:latest + ports: + - 80:8080 +``` + +Then run: + +```bash [Terminal] +docker compose -f compose.prod.yml up +``` + +This lets you verify your production image works correctly before deploying to real servers. + +## Best practices for production images + +### 1.`Use specific image tags +Don't use `latest` tags in production. Use specific versions: + +```dockerfile +# Bad - version can change unexpectedly +FROM serversideup/php:latest + +# Good - explicitly versioned +FROM serversideup/php:8.4-fpm-nginx +``` + +### 2. Run as non-root user +Always run your application as a non-root user for security: + +```dockerfile +# Our images default to www-data, but explicitly switch back if you use root +USER www-data +``` + +All `serversideup/php` images default to running as the `www-data` user for security. + +### 3. Keep secrets out of images +Never bake secrets into your images: + +```dockerfile +# ❌ Never do this +ENV APP_KEY=base64:your-secret-key + +# ✅ Provide secrets at runtime via environment variables +``` + +Secrets should be provided when the container starts, not built into the image. + +## Image versioning strategy +When building images for deployment, tag them with meaningful versions: + +```bash [Terminal] +# Tag with git commit SHA +docker build -t my-app:$(git rev-parse --short HEAD) . + +# Tag with semantic version +docker build -t my-app:1.2.3 . + +# Tag with date and build number +docker build -t my-app:2024-10-31-build-42 . +``` + +Good versioning lets you: +- Track which code is running in each environment +- Roll back to previous versions quickly +- Debug issues by knowing exactly what's deployed + +## What's next? +Now that you know how to package your application, you're ready to learn about SSL configuration and choosing the right hosting provider for your containerized application. + +:u-button{to="/docs/deployment-and-production/configuring-ssl" label="Configure SSL for your application" aria-label="Configure SSL for your application" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + From dfea2cdd4d96826416da6d781d3ba67bc2927097 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 14:31:33 -0500 Subject: [PATCH 147/170] Update Docker Compose code block syntax in Laravel documentation to use 'compose.yml' for consistency across task scheduler, queue, horizon, and reverb guides. --- .../docs/3.framework-guides/1.laravel/2.task-scheduler.md | 2 +- docs/content/docs/3.framework-guides/1.laravel/3.queue.md | 2 +- docs/content/docs/3.framework-guides/1.laravel/4.horizon.md | 2 +- docs/content/docs/3.framework-guides/1.laravel/4.reverb.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md b/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md index 0fa52d62c..734a5ae98 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md +++ b/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md @@ -31,7 +31,7 @@ Notice we're calling the artisan command explicitly with the full path (`/var/ww :: #### Example & Simplified Docker Compose File -```yml [docker-compose.yml] +```yml [compose.yml] services: php: image: my/laravel-app diff --git a/docs/content/docs/3.framework-guides/1.laravel/3.queue.md b/docs/content/docs/3.framework-guides/1.laravel/3.queue.md index 5067c5de9..2907dfd0d 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/3.queue.md +++ b/docs/content/docs/3.framework-guides/1.laravel/3.queue.md @@ -28,7 +28,7 @@ Notice we're calling the artisan command explicitly with the full path (`/var/ww :: #### Example & Simplified Docker Compose File -```yml [docker-compose.yml] +```yml [compose.yml] services: php: image: my/laravel-app diff --git a/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md b/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md index 3a8140b42..502b9fb77 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md +++ b/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md @@ -29,7 +29,7 @@ Notice we're calling the artisan command explicitly with the full path (`/var/ww :: #### Example & Simplified Docker Compose File -```yml [docker-compose.yml] +```yml [compose.yml] services: php: image: my/laravel-app diff --git a/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md b/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md index b11a52fe6..b1bcc105c 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md +++ b/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md @@ -29,7 +29,7 @@ Notice Laravel Reverb is running on port `8000`, where as Laravel is running on :: #### Example & Simplified Docker Compose File -```yml [docker-compose.yml] +```yml [compose.yml] services: php: image: my/laravel-app From 3652933a01177232ca2504258ab8ad548a5fad4a Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 15:07:02 -0500 Subject: [PATCH 148/170] Update migration guide to reflect the change from 'docker-compose.yml' to 'compose.yml' for consistency in configuration examples. --- docs/content/docs/5.guide/99.migrating-from-v2-to-v3.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content/docs/5.guide/99.migrating-from-v2-to-v3.md b/docs/content/docs/5.guide/99.migrating-from-v2-to-v3.md index 60d1a559f..c9abaa482 100644 --- a/docs/content/docs/5.guide/99.migrating-from-v2-to-v3.md +++ b/docs/content/docs/5.guide/99.migrating-from-v2-to-v3.md @@ -11,9 +11,9 @@ If you're moving from v2 of serversideup/php to the latest version, there are a ## Preparing for the migration If you're an existing user of our v2 images, be sure that your current configurations are NOT set to use the latest images. To do this, you can lock your images into the `v2.2.1` tag. This will ensure that you're not automatically upgraded to the v3 images. -For example, if you are using `8.2-fpm-nginx`, you would change your `docker-compose.yml` file to use the [`v2.2.1`](https://hub.docker.com/r/serversideup/php/tags?page=1&name=2.2.1){target="_blank"} tag: +For example, if you are using `8.2-fpm-nginx`, you would change your `compose.yml` file to use the [`v2.2.1`](https://hub.docker.com/r/serversideup/php/tags?page=1&name=2.2.1){target="_blank"} tag: -```yml [docker-compose.yml] {3} +```yml [compose.yml] {3} services: php: image: serversideup/php:8.2-fpm-nginx @@ -23,7 +23,7 @@ services: - .:/var/www/html ``` -```yml [docker-compose.yml] {3} +```yml [compose.yml] {3} services: php: image: serversideup/php:8.2-fpm-nginx-v2.2.1 From 0085c82793cf702e72c134e072a531ac99ce5894 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 15:07:34 -0500 Subject: [PATCH 149/170] Update health check documentation for Laravel to consistently use 'compose.yml' instead of 'docker-compose.yml' across all examples. --- .../2.using-healthchecks-with-laravel.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/content/docs/5.guide/2.using-healthchecks-with-laravel.md b/docs/content/docs/5.guide/2.using-healthchecks-with-laravel.md index 9645f4a03..245b50dfc 100644 --- a/docs/content/docs/5.guide/2.using-healthchecks-with-laravel.md +++ b/docs/content/docs/5.guide/2.using-healthchecks-with-laravel.md @@ -16,7 +16,7 @@ Dialing in health checks are very important for ensuring your application is run Health checks are a way to check the status of your application. Whenever a container is started, a health check is performed. If the health check fails, the container will be restarted or marked as unhealthy. Health checks are very important for rolling updates and ensuring your application can start up in order if you have services that depend on each other. ## Our Health Checks -We offer a number of health check commands, specifically for Laravel. You can find these commands are prefixed with `healthcheck-` and are located in [`/usr/local/bin`](https://github.com/serversideup/docker-php/tree/main/src/common/usr/local/bin){target="_blank"}. The examples below show how to use these health checks in your `docker-compose.yml` file, but you can also use them in other environments. +We offer a number of health check commands, specifically for Laravel. You can find these commands are prefixed with `healthcheck-` and are located in [`/usr/local/bin`](https://github.com/serversideup/docker-php/tree/main/src/common/usr/local/bin){target="_blank"}. The examples below show how to use these health checks in your `compose.yml` file, but you can also use them in other environments. ## Default Health Check Settings By default, our Dockerfiles ship with the following health check commands: @@ -50,9 +50,9 @@ Since it is good practice to use the same Docker image for all our services, we ### Laravel Horizon We utilize the `artisan horizon:status` command to check the status of Laravel Horizon. This is a command native to Laravel Horizon and is used to determine if the Horizon process is running. -To run this command automatically, you can call our health check command in your `docker-compose.yml` file. +To run this command automatically, you can call our health check command in your `compose.yml` file. -```yml [docker-compose.yml] +```yml [compose.yml] ## Rest of your service configuration... healthcheck: test: ["CMD", "healthcheck-horizon"] @@ -63,9 +63,9 @@ healthcheck: ### Laravel Reverb We use `pgrep` to check if the `reverb:start` command is running. This ensures the Reverb process is running and ready to accept connections. -To run this command automatically, you can call our health check command in your `docker-compose.yml` file. +To run this command automatically, you can call our health check command in your `compose.yml` file. -```yml [docker-compose.yml] +```yml [compose.yml] ## Rest of your service configuration... healthcheck: test: ["CMD", "healthcheck-reverb"] @@ -76,9 +76,9 @@ healthcheck: ### Laravel Scheduler We use `pgrep` to check if the `schedule:work` command is running. This ensures the scheduler process is running. -To run this command automatically, you can call our health check command in your `docker-compose.yml` file. +To run this command automatically, you can call our health check command in your `compose.yml` file. -```yml [docker-compose.yml] +```yml [compose.yml] ## Rest of your service configuration... healthcheck: test: ["CMD", "healthcheck-schedule"] @@ -89,9 +89,9 @@ healthcheck: ### Laravel Queue We use `pgrep` to check if the `queue:work` command is running. This ensures the queue process is running. -To run this command automatically, you can call our health check command in your `docker-compose.yml` file. +To run this command automatically, you can call our health check command in your `compose.yml` file. -```yml [docker-compose.yml] +```yml [compose.yml] ## Rest of your service configuration... healthcheck: test: ["CMD", "healthcheck-queue"] From 2423c651d9953c98b93af93f206b27d20d11f80f Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 15:08:25 -0500 Subject: [PATCH 150/170] Add documentation on understanding file permissions in PHP + Docker, addressing common challenges and providing solutions for managing UID/GID alignment between host and container environments. This guide includes examples for development and production setups to enhance user experience and security. --- .../3.understanding-file-permissions.md | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) create mode 100644 docs/content/docs/5.guide/3.understanding-file-permissions.md diff --git a/docs/content/docs/5.guide/3.understanding-file-permissions.md b/docs/content/docs/5.guide/3.understanding-file-permissions.md new file mode 100644 index 000000000..627c12e3d --- /dev/null +++ b/docs/content/docs/5.guide/3.understanding-file-permissions.md @@ -0,0 +1,107 @@ +--- +head.title: 'Understanding file permissions - Docker PHP - Server Side Up' +description: 'Eliminate the headache of file permissions when working with PHP + Docker.' +layout: docs +--- + +# Understanding File Permissions +::lead-p +Working with file permissions is one of the biggest headaches when working with PHP + Docker. This generally is because the PHP server also requires a web server to serve static files. By default, this means multiple users are created in the container, and permissions can get out of hand quickly. +:: + +![Traditional PHP File Permissions Configuration](/images/docs/permissions-privileged.png) + +## Even more frustrating: Development Environments +Even if someone configured a single user in the container to run both the PHP server and the web server, things get even more complicated in development environments. For example, if you have Alice running her Windows Machine with WSL2, she might have a user ID of `1001`. Then you have Bob running his Ubuntu workstation with a user ID of `1002`. Meanwhile, Charlie is running his Docker on his macOS machine (that runs a tiny VM) that has a totally different file permission experience compared to Windows and Linux because of the file system differences. + +If a volume is mounted from the container to the host, the container will write files to the host as `33:33`, which will require sudo/root permissions to edit and delete files. + +## Our industry attempted workarounds +We've seen experiences that allow users to provide an environment variable of `PUID` and `PGID`. Although this is a great user experience, it requires the container user to be privileged, which is a major "no-no" in the security world. It also had downstream file permission errors if the container failed on initialization where logs would be created by the root user and no longer writable by the `www-data` user. + +## Our solution +We focus on providing the tools to give sysadmins the ability to: +- Keep their containers unprivileged by default +- Allow the dynamic reconfiguration of the container user and group ID (at build time only) + +It's a bummer that we can only set the user and group ID at build time, but it's a small price to pay for the security benefits of running unprivileged containers. + +#### How it works +- By default, all our images run `www-data` as the user (`33:33` for Debian and `82:82` for Alpine) +- We provide a script that can be called at build time to change the UID and GID of `www-data` (called `docker-php-serversideup-set-id`) +- If you need to update permissions of service files (example: NGINX, Apache, Unit, etc), you can run the `docker-php-serversideup-set-file-permissions` at build. This will automatically detect the service and update the file permissions accordingly. +- We will use a multi-stage build to ensure that the `docker-php-serversideup-set-id` script is not executed in the construction of the final image + +## Example +Here's an example of ensuring our UID/GID of `www-data` will match the development UID/GID of the host machine, while preserving the default UID/GID of `33:33` for the final image: + + +```dockerfile [Dockerfile] +############################################ +# Base Image +############################################ +FROM serversideup/php:8.4-fpm-nginx-bookworm AS base + +############################################ +# Development Image +############################################ +FROM base AS development + +# Switch to root so we can do root things +USER root + +# Save the build arguments as a variable +ARG USER_ID +ARG GROUP_ID + +# Use the build arguments to change the UID +# and GID of www-data while also changing +# the file permissions for NGINX +RUN docker-php-serversideup-set-id www-data $USER_ID:$GROUP_ID && \ + \ + # Update the file permissions to match the new UID/GID + docker-php-serversideup-set-file-permissions --owner $USER_ID:$GROUP_ID + +# Drop back to our unprivileged user +USER www-data + +############################################ +# Production Image +############################################ + +# Since we're calling "base", production isn't +# calling any of that permission stuff +FROM base AS production + +# Copy our app files as www-data (33:33) +COPY --chown=www-data:www-data . /var/www/html +``` + +To show a simple Docker Compose file example for development, we could use: + +```yml [compose.yml] +services: + php: + build: + context: . + target: development + args: + # UID and GID must be set as environment variables on the host machine + USER_ID: $UID + GROUP_ID: $GID + ports: + - 80:8080 + volumes: + - .:/var/www/html +``` + +When we run `docker compose up`, our compose file directs us to build the `development` target. This target will run the `docker-php-serversideup-set-id` script to change the UID and GID of `www-data` to match the host machine (assuming `$UID` and `$GID` are set in a zsh/bash profile or something similar). This will allow us to run the container as an unprivileged user while still having the correct permissions to read and write files. + +The best thing is the user can delete files off of their machine without being prompted for sudo permissions. This is because we're aligning the UID/GID of the container with the host machine. + +When it comes to building our image for production, we just use the `production` target, which will copy the files as `www-data` with the default UID/GID of `33:33`. + +## An optimized experience from development to production +If you like the concepts above and you're looking for an optimized experience for developers (especially when it comes simplifying the setting of UID/GID), we recommend checking out our other open source project Spin. Spin is a lightweight wrapper for Docker Compose that allows you to manage your environment from development to production. + +:u-button{to="https://serversideup.net/open-source/spin/" label="Learn more about Spin" aria-label="Learn more about Spin" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file From 2732741bb4b710d25ec83e51344769d8753a6e73 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 15:09:42 -0500 Subject: [PATCH 151/170] Refactor file permissions documentation for PHP + Docker, improving clarity on user and permission management in development environments. Updated image path syntax for consistency and enhanced user understanding of file permission challenges across different operating systems. --- docs/content/docs/5.guide/3.understanding-file-permissions.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/content/docs/5.guide/3.understanding-file-permissions.md b/docs/content/docs/5.guide/3.understanding-file-permissions.md index 627c12e3d..4f8fcbeec 100644 --- a/docs/content/docs/5.guide/3.understanding-file-permissions.md +++ b/docs/content/docs/5.guide/3.understanding-file-permissions.md @@ -3,13 +3,11 @@ head.title: 'Understanding file permissions - Docker PHP - Server Side Up' description: 'Eliminate the headache of file permissions when working with PHP + Docker.' layout: docs --- - -# Understanding File Permissions ::lead-p Working with file permissions is one of the biggest headaches when working with PHP + Docker. This generally is because the PHP server also requires a web server to serve static files. By default, this means multiple users are created in the container, and permissions can get out of hand quickly. :: -![Traditional PHP File Permissions Configuration](/images/docs/permissions-privileged.png) +![Traditional PHP File Permissions Configuration](images/docs/permissions-privileged.png){:zoom=false} ## Even more frustrating: Development Environments Even if someone configured a single user in the container to run both the PHP server and the web server, things get even more complicated in development environments. For example, if you have Alice running her Windows Machine with WSL2, she might have a user ID of `1001`. Then you have Bob running his Ubuntu workstation with a user ID of `1002`. Meanwhile, Charlie is running his Docker on his macOS machine (that runs a tiny VM) that has a totally different file permission experience compared to Windows and Linux because of the file system differences. From 2be9f012a6c3c6d60051f2dd3516421c8dcc183f Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 15:10:35 -0500 Subject: [PATCH 152/170] Update SSL configuration documentation to replace 'docker-compose.yml' with 'compose.yml' for consistency across examples. --- .../docs/4.deployment-and-production/4.configuring-ssl.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/4.deployment-and-production/4.configuring-ssl.md b/docs/content/docs/4.deployment-and-production/4.configuring-ssl.md index 6252314aa..f402e45ae 100644 --- a/docs/content/docs/4.deployment-and-production/4.configuring-ssl.md +++ b/docs/content/docs/4.deployment-and-production/4.configuring-ssl.md @@ -225,7 +225,7 @@ Self-signed certificates will display warnings in the browser. While browsers will show warnings, self-signed certificates are useful for specific use cases, such as encrypting traffic between containers in a cluster. If you set `SSL_MODE` to `mixed` or `full` without providing a certificate at `$SSL_CERTIFICATE_FILE` and `$SSL_PRIVATE_KEY_FILE`, a self-signed certificate will be automatically generated. -```yml [docker-compose.yml]{7-9} +```yml [compose.yml]{7-9} services: php: image: serversideup/php:8.4-fpm-nginx From 2191083edf3ef17f8bd0264972972f379d25fdf7 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 15:16:06 -0500 Subject: [PATCH 153/170] Add comprehensive guide on transitioning from development to production using Docker. Covers deployment challenges, Docker benefits, production image building, deployment strategies, automation, and introduces Spin for simplified workflows. Aims to enhance user confidence in deploying PHP applications. --- .../2.development-to-production.md | 153 ++++++++++++++++++ 1 file changed, 153 insertions(+) create mode 100644 docs/content/docs/4.deployment-and-production/2.development-to-production.md diff --git a/docs/content/docs/4.deployment-and-production/2.development-to-production.md b/docs/content/docs/4.deployment-and-production/2.development-to-production.md new file mode 100644 index 000000000..3b341a475 --- /dev/null +++ b/docs/content/docs/4.deployment-and-production/2.development-to-production.md @@ -0,0 +1,153 @@ +--- +title: Development to Production +description: 'Learn how to take your PHP application from development to production with confidence using Docker.' +layout: docs +--- + +::lead-p +The real power of Docker isn't just running containers locally — it's running the **exact same environment** from your laptop to production. This guide shows you how to achieve 100% environment replication and deploy with confidence. +:: + +## The traditional deployment problem +If you've deployed applications before, you've probably experienced these frustrations: + +- **"It works on my machine"** - Something breaks in production that worked perfectly locally +- **Environment drift** - Your development, staging, and production environments slowly become different +- **Deployment anxiety** - Every deployment feels risky because you can't be sure what will happen +- **Vendor lock-in** - You're stuck with a PaaS provider because migrating is too painful +- **Downtime** - Users experience interruptions during deployments +- **Configuration chaos** - Infrastructure settings scattered across multiple places + +These problems share a common root cause: **your environments aren't the same**. + +## How Docker solves this +When you containerize your application properly, you package everything your app needs into a single, reproducible unit. This means: + +### 100% environment replication +The container that runs on your MacBook is **identical** to the one running in production. Same PHP version, same extensions, same web server, same configurations. No surprises. + +### Version-controlled infrastructure +Your `compose.yml` and Dockerfiles live in Git alongside your application code. Need to change PHP settings? Update a file, commit it, and deploy. Need to roll back? Just deploy the previous commit. Your infrastructure is now as manageable as your application code. + +### Freedom to choose your host +Because your application is containerized, you can run it anywhere that supports Docker — DigitalOcean, Hetzner, Vultr, AWS, your own hardware, anywhere. If a host raises prices or doesn't meet your needs anymore, migration becomes straightforward instead of a massive project. + +### Simplified scaling +Once you have one container running, scaling to multiple containers becomes much simpler. Add more resources by deploying more containers, not by re-configuring servers. + +## The development to production journey +Let's walk through what this journey actually looks like when you use containers properly. + +### 1. Development (where you are now) +You've already experienced this in our [installation guide](/docs/getting-started/installation). You're running containers locally with Docker Compose, your files are mounted as volumes, and changes appear instantly. This is perfect for development because: + +- You can edit files with your favorite tools +- Changes appear immediately without rebuilding +- You can experiment freely +- Multiple developers work with identical environments + +### 2. Building production images +For production, you'll create optimized images that have your application code **built into the image** instead of mounted as volumes. This ensures: + +- Your code can't be accidentally modified in production +- Images are portable and can run anywhere +- Deployments are atomic — either the new version runs or the old one does +- You can roll back by deploying a previous image + +We cover this in detail in our [packaging guide](/docs/deployment-and-production/packaging-your-app-for-deployment). + +### 3. Choosing a deployment strategy +You have several options for running containers in production: + +**Docker Compose** - Simple and effective for single-server deployments. Great for getting started. + +**Docker Swarm** - Built into Docker, provides zero-downtime deployments, automatic SSL with Let's Encrypt, load balancing, and easy scaling across multiple servers. + +**Kubernetes** - The most powerful option for large-scale deployments. More complex but extremely capable. + +Each option uses the same OCI-compliant container images, so you can start simple and graduate to more sophisticated setups as you grow. + +::tip +We recommend starting with Docker Compose for development environments and Docker Swarm for production. Swarm gives you zero-downtime deployments without the complexity of Kubernetes. +:: + +### 4. Automated deployments +The final piece is automation. Instead of manually SSHing into servers, you'll set up CI/CD pipelines (usually with GitHub Actions) that: + +1. Run your tests on every commit +2. Build production images +3. Deploy automatically to staging or production +4. Roll back automatically if health checks fail + +This means you can deploy with a simple `git push` and have confidence that your application will deploy safely. + +## Simplifying the journey with Spin +While everything described above is achievable with standard Docker tools, there's a learning curve. We've experienced these challenges ourselves, which is why we created [Spin](https://serversideup.net/open-source/spin/). + +::note +**Spin is NOT required** to use these Docker images. They work with any Docker setup. But if you're looking for a simpler path to production, Spin can help significantly. +:: + +### What is Spin? +Spin is a free and open source tool that simplifies Docker workflows from development to production. It helps you: + +- Set up local development environments with a single command +- Provision and deploy to any VPS provider (DigitalOcean, Hetzner, Vultr, etc.) +- Configure Docker Swarm for zero-downtime deployments +- Set up automated SSL with Let's Encrypt +- Deploy with GitHub Actions +- Manage multiple environments (dev, staging, production) + +Think of Spin as a helpful wrapper around Docker that handles the complex bits while teaching you Docker best practices. + +### See it in action +This video demonstrates the complete journey from creating a Laravel project to deploying it to production with zero-downtime deployments: + +:iframe{src="https://www.youtube-nocookie.com/embed/5z2JoEt5XIk?si=u5v-bDN-cMv0OE-C" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen style="aspect-ratio: 16/9; width: 100%;"} + +The best part? It uses these same `serversideup/php` images you're already familiar with. + +:u-button{to="https://serversideup.net/open-source/spin/" label="Learn more about Spin" aria-label="Learn more about Spin" target="_blank" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +### Advanced Laravel features with Spin Pro +For teams running advanced Laravel features (Horizon, Reverb, scheduled tasks, multiple databases), we offer [Spin Pro](https://getspin.pro/) — a paid starter kit that includes pre-configured templates for these services. + +It's a one-time purchase that gives you: +- Project templates with Horizon, Reverb, queues, and more +- Pre-configured GitHub Actions workflows +- Zero-downtime deployment configurations +- Support for multiple database engines (MySQL, PostgreSQL, MariaDB, SQLite) + +Spin Pro exists because we've deployed dozens of Laravel applications ourselves and kept running into the same setup challenges. We built the solution we wished existed, and we're sharing it with the community. + +::note +All Spin Pro templates use the same open source `serversideup/php` images and Spin CLI you're already using. You're buying the templates and automation, not proprietary technology. +:: + +## Alternative approaches +Spin is one tool among many. Here are other common approaches: + +**Manual Docker Compose** - Use Docker Compose directly. More hands-on but gives you complete control. Great for learning. + +**Kubernetes** - Use tools like Helm or Kustomize to deploy to Kubernetes clusters. More complex but extremely powerful for large-scale applications. + +**PaaS Providers** - Services like Laravel Forge, Ploi, or platform providers can deploy containers for you. More expensive but less hands-on management. + +**CI/CD Tools** - GitLab CI, GitHub Actions, or Jenkins can orchestrate your deployments without additional tools. + +Choose whatever works best for your team's skills, budget, and requirements. The important part is that you're using containers, which means you maintain flexibility to change strategies later. + +## Key principles for success +Regardless of which tools you choose, follow these principles: + +1. **Keep development and production similar** - Use the same base images and configurations in both environments +2. **Store infrastructure in Git** - Version control your Docker configurations alongside your code +3. **Automate everything** - Manual deployments lead to mistakes and inconsistency +4. **Use health checks** - Let your orchestrator verify deployments succeed before switching traffic +5. **Practice deployments** - Deploy to staging frequently to catch issues before production +6. **Monitor your containers** - Use logging and monitoring to understand what's happening in production + +## What's next? +Now that you understand the journey from development to production, you're ready to learn how to properly package your application for deployment. + +:u-button{to="/docs/deployment-and-production/packaging-your-app-for-deployment" label="Learn how to package your app for deployment" aria-label="Learn how to package your app for deployment" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file From a97c210f42cd4a10931abf4b0579c9ab61d15d3b Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 15:19:01 -0500 Subject: [PATCH 154/170] Update migration guide to replace 'docker-compose.yml' with 'compose.yml' for consistency in configuration examples and improve clarity in Docker setup instructions. --- .../docs/5.guide/1.migrating-from-official-php-images.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/content/docs/5.guide/1.migrating-from-official-php-images.md b/docs/content/docs/5.guide/1.migrating-from-official-php-images.md index ce8a897ae..d7b91c2b7 100644 --- a/docs/content/docs/5.guide/1.migrating-from-official-php-images.md +++ b/docs/content/docs/5.guide/1.migrating-from-official-php-images.md @@ -43,7 +43,7 @@ Making the change will literally take you two seconds. #### Figure out which image you'd like to use Review our [choosing an image](/docs/getting-started/choosing-an-image) guide to help you decide which image you'd like to use. Also, make sure our [default configurations](/docs/getting-started/default-configurations) satisfy your requirements. -#### Update your `Dockerfile` or `docker-compose.yml` file +#### Update your `Dockerfile` or `compose.yml` file :::tip We simply change `php:8.4-apache` to `serversideup/php:8.4-fpm-apache` ::: @@ -61,9 +61,9 @@ FROM serversideup/php:8.4-fpm-apache ``` ::: -**docker-compose.yml** +**compose.yml** :::code-group -```yml [ORIGINAL: docker-compose.yml]{3,5-6} +```yml [ORIGINAL: compose.yml]{3,5-6} services: php: image: php:8.4-apache @@ -71,7 +71,7 @@ services: - 80:80 - 443:443 ``` -```yml [UPDATED: docker-compose.yml]{3,5-6} +```yml [UPDATED: compose.yml]{3,5-6} services: php: image: serversideup/php:8.4-fpm-apache From bd65f8bff1cdfcada7fb7f377341768e493d1d7d Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Fri, 31 Oct 2025 15:20:09 -0500 Subject: [PATCH 155/170] Fix formatting in packaging documentation by adding a space after the section title for better readability. --- .../3.packaging-your-app-for-deployment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/4.deployment-and-production/3.packaging-your-app-for-deployment.md b/docs/content/docs/4.deployment-and-production/3.packaging-your-app-for-deployment.md index 1c0d20b62..800f8cff0 100644 --- a/docs/content/docs/4.deployment-and-production/3.packaging-your-app-for-deployment.md +++ b/docs/content/docs/4.deployment-and-production/3.packaging-your-app-for-deployment.md @@ -108,7 +108,7 @@ This lets you verify your production image works correctly before deploying to r ## Best practices for production images -### 1.`Use specific image tags +### 1. Use specific image tags Don't use `latest` tags in production. Use specific versions: ```dockerfile From 464c25ff0b26b195c4617688a936238ea8629683 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Mon, 3 Nov 2025 13:39:08 -0600 Subject: [PATCH 156/170] Add documentation on adding custom start-up scripts in Docker PHP. Includes requirements, execution order, and examples for integrating scripts into the entrypoint.d directory, as well as guidance on using S6 Overlay for long-running services. --- .../3.adding-your-own-start-up-scripts.md | 130 ++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 docs/content/docs/6.customizing-the-image/3.adding-your-own-start-up-scripts.md diff --git a/docs/content/docs/6.customizing-the-image/3.adding-your-own-start-up-scripts.md b/docs/content/docs/6.customizing-the-image/3.adding-your-own-start-up-scripts.md new file mode 100644 index 000000000..e9fa7848e --- /dev/null +++ b/docs/content/docs/6.customizing-the-image/3.adding-your-own-start-up-scripts.md @@ -0,0 +1,130 @@ +--- +head.title: 'Adding your own start up scripts - Docker PHP - Server Side Up' +description: 'Learn how to use our entrypoint.d directory to customize your container start up experience.' +layout: docs +title: Adding Start Up Scripts +--- +::lead-p +We provide a few [default entrypoint scripts](/docs/getting-started/default-configurations#default-entrypoint-scripts) to get you going, but sometimes you want to just add your own. We've made it easy to do that with our `entrypoint.d` directory. +:: + +## Entrypoint Script Requirements +::note +Before you write your entry point script, be aware of the following requirements. Your script should: +- Be executable (755 permissions) +- Located in the `/etc/entrypoint.d` directory +- Have the file extension ending in `.sh` +:: +::tip +We recommend writing your script in `/bin/sh` for the best compatibility between Alpine and Debian. If you choose to use `/bin/bash`, your script will only be able to run on Debian-based images. +:: + +## Choose your execution order +Since [we provide default entrypoint scripts](/docs/getting-started/default-configurations#default-entrypoint-scripts), you may want to choose the order in which your scripts are executed. We've made it easy to do that by prefixing your script with a number. The lower the number, the earlier it will be executed. + +::tip +If you want to disable our entrypoint scripts, you can set `DISABLE_DEFAULT_CONFIG` to `true` in your environment variables. +:: + +## Long running services +::note +Don't use entrypoint scripts for long-running services. You want your services to be monitored and restarted if they crash. +:: + +Anything in the `/etc/entrypoint.d` directory are scripts that are intended to run quickly and then move on. If you run a service as an entrypoint script, that service may crash and not be restarted. + +Instead, learn about [using S6 overlay](/docs/guide/using-s6-overlay) so your services can be properly initialized and monitored. See the [S6 Overylay project](https://github.com/just-containers/s6-overlay) for more details on how to write your own S6 service. + +## Example: Create a custom entrypoint script +In this example, let's create a `99-my-script.sh` so it executes after all the other default scripts. + +::code-tree{defaultValue="Dockerfile"} + +```bash [entrypoint.d/99-my-script.sh] +#!/bin/sh +echo "👋 Hello, world!" +``` + +```dockerfile [Dockerfile] +FROM serversideup/php:8.4-fpm-nginx + +# Copy our scripts as executable +COPY --chmod=755 ./entrypoint.d/ /etc/entrypoint.d/ +``` + +```yml [compose.yml] +services: + php: + build: + context: . + dockerfile: Dockerfile + ports: + - 80:8080 + volumes: + - .:/var/www/html +``` + +```php [public/index.php] + +``` + +:: + + +In the example above, you can see in the `Dockerfile` we are copying our `entrypoint.d` directory to `/etc/entrypoint.d/` in the container. We're also setting the permissions to `755` so our scripts are executable. + +## Running our example +When we run `docker compose up`, we can confirm our script is executing by checking the logs: + +::code-panel +--- +label: "Output of \"docker compose up\"" +--- +```txt +php-1 | 👉 [NOTICE]: Improve PHP performance by setting PHP_OPCACHE_ENABLE=1 (recommended for production). +php-1 | (init-webserver-config): Processing /etc/nginx/nginx.conf.template → /etc/nginx/nginx.conf... +php-1 | (init-webserver-config): Processing /etc/nginx/site-opts.d/http.conf.template → /etc/nginx/site-opts.d/http.conf... +php-1 | (init-webserver-config): Processing /etc/nginx/site-opts.d/https.conf.template → /etc/nginx/site-opts.d/https.conf... +php-1 | ℹ️ NOTICE (init-webserver-config): Enabling NGINX site with SSL "off"... +php-1 | 👋 Hello, world! +php-1 | [03-Nov-2025 19:35:29] NOTICE: fpm is running, pid 93 +php-1 | [03-Nov-2025 19:35:29] NOTICE: ready to handle connections +php-1 | HTTP Status Code: 200 +php-1 | ✅ NGINX + PHP-FPM is running correctly. +``` +:: + +You can see our `👋 Hello, world!` is executing *after* the initialization of `10-init-unit.sh`. + +## Advanced Scenarios: S6 Overlay dependencies +If you want to customize an image that uses S6 Overlay (`fpm-nginx` or `fpm-apache`), you may have an advanced scenario where you have a custom S6 service that needs to be executed after one of our entrypoint scripts. In order to do this, you'll need to move all our scripts from the `/etc/entrypoint.d` directory to the `/etc/s6-overlay/scripts` directory. This would be a very time consuming scenario if you did this manually, but thankfully you can use our `docker-php-serversideup-s6-init` script to do this for you. + +```dockerfile [Dockerfile] +FROM serversideup/php:8.4-fpm-nginx + +# Set the user to root for our build steps +USER root + +# If you have your own one-shot scripts, copy them to the entrypoint.d directory +COPY --chmod=755 ./entrypoint.d/ /etc/entrypoint.d/ + +# Copy our entrypoint scripts into the S6 Overlay scripts directory +RUN docker-php-serversideup-s6-init + +# If you have your own long running services, copy them to the s6 directory +COPY --chmod=755 ./my-s6-service/ /etc/s6-overlay/s6-rc.d/my-s6-service/ + +# Drop back to the non-root user +USER www-data +``` + +In the above file, we're copying our "one-shot" scripts to the `/etc/entrypoint.d` directory and our long running services to the `/etc/s6-overlay` directory. One-shot scripts are scripts that are intended to run quickly and then move on. Long running services are services that are intended to run for a long time and need to be monitored and restarted if they crash. + +The magic happens when we run `docker-php-serversideup-s6-init`. This script will move all our scripts from the `/etc/entrypoint.d` directory to the `/etc/s6-overlay/scripts` directory and set the correct dependencies for our S6 services. + +You can now reference our script names as dependencies in your own S6 service. + +:u-button{to="https://github.com/just-containers/s6-overlay" label="Learn more about S6 Overlay" aria-label="Learn more about S6 Overlay" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold" target="_blank"} From c73cd4b7d9ca281b41175bb9a3a77bb8c9f2fc75 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Mon, 3 Nov 2025 13:40:47 -0600 Subject: [PATCH 157/170] Add documentation for changing common PHP settings in Docker. Includes examples for using environment variables and custom php.ini files, along with validation methods to ensure changes are applied correctly. --- .../1.changing-common-php-settings.md | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 docs/content/docs/6.customizing-the-image/1.changing-common-php-settings.md diff --git a/docs/content/docs/6.customizing-the-image/1.changing-common-php-settings.md b/docs/content/docs/6.customizing-the-image/1.changing-common-php-settings.md new file mode 100644 index 000000000..7aa8cb08c --- /dev/null +++ b/docs/content/docs/6.customizing-the-image/1.changing-common-php-settings.md @@ -0,0 +1,71 @@ +--- +head.title: 'Changing common PHP settings - Docker PHP - Server Side Up' +description: 'Learn how to change common PHP settings with environment variables or your own php.ini file.' +layout: docs +title: Changing php.ini settings +--- + +::lead-p +Instead of going through the effort of writing custom scripts or mounting files to change PHP settings, have the power to change common settings with the simplicity of an environment variable. +:: + +## Common Examples +All our environment variables are documented and can be found in our environment variable specification documentation. + +:u-button{to="/docs/reference/environment-variable-specification" label="Environment Variable Specification" aria-label="Environment Variable Specification" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +Here are a few examples on how you can change common PHP settings. + +```yml [compose.yml] {4-6} +services: + php: + image: serversideup/php:8.2.12-unit-bookworm + environment: + PHP_POST_MAX_SIZE: "500M" + PHP_UPLOAD_MAX_FILE_SIZE: "500M" + SSL_MODE: "mixed" + ports: + - 80:8080 + - 443:8443 + volumes: + - .:/var/www/html/ +``` + +You can also adjust environment variables using the Docker CLI. + +```bash [Terminal] +docker run -d \ + -p 80:8080 \ + -v $(pwd):/var/www/html \ + -e PHP_DATE_TIMEZONE="America/New_York" \ + serversideup/php:8.2.12-fpm-nginx-bookworm +``` + +## Setting your own php.ini +PHP will read the `php.ini` file from the `/usr/local/etc/php/conf.d/` directory in alphabetical order. This means you can create your own `php.ini` file and mount it to the container to override the default settings. + +For example, we can create this file in our project directory: +```ini [zzz-custom-php.ini] +mysqli.max_persistent = 300 +opcache.max_file_size = 10M +opcache.log_verbosity_level = 3 +``` + +Then in our Dockerfile, we can copy this file to the `/usr/local/etc/php/conf.d/` directory: +```dockerfile [Dockerfile] +FROM serversideup/php:8.4-fpm-nginx-bookworm + +COPY zzz-custom-php.ini /usr/local/etc/php/conf.d/ +``` + +If you prefer to remove the default `php.ini` file, you can do so by adding the following line to your Dockerfile: + +```dockerfile [Dockerfile] +FROM serversideup/php:8.4-fpm-nginx-bookworm + +RUN rm /usr/local/etc/php/conf.d/serversideup-docker-php.ini +COPY zzz-custom-php.ini /usr/local/etc/php/conf.d/ +``` + +## Validating changes +It's always best to validate your changes by running `php -i` via the command line or using [`phpinfo()`](https://www.php.net/manual/en/function.phpinfo.php){target="_blank"}. \ No newline at end of file From 147c0eb49a1fcaa5a4b6e46a48aa14c0bc38f8f7 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 4 Nov 2025 09:16:42 -0600 Subject: [PATCH 158/170] Add new host icons and update Nuxt configuration to include them. Introduced icons for DigitalOcean, Hetzner, Vultr, and Sevalla, enhancing visual representation of hosting options in the application. --- .../icons/hosts/digitalocean-square.svg | 6 ++++++ docs/app/assets/icons/hosts/digitalocean.svg | 20 +++++++++++++++++++ .../app/assets/icons/hosts/hetzner-square.svg | 3 +++ docs/app/assets/icons/hosts/hetzner.svg | 9 +++++++++ .../app/assets/icons/hosts/sevalla-square.svg | 6 ++++++ docs/app/assets/icons/hosts/sevalla.svg | 8 ++++++++ docs/app/assets/icons/hosts/vultr-square.svg | 6 ++++++ docs/app/assets/icons/hosts/vultr.svg | 11 ++++++++++ docs/nuxt.config.ts | 4 ++++ 9 files changed, 73 insertions(+) create mode 100644 docs/app/assets/icons/hosts/digitalocean-square.svg create mode 100644 docs/app/assets/icons/hosts/digitalocean.svg create mode 100644 docs/app/assets/icons/hosts/hetzner-square.svg create mode 100644 docs/app/assets/icons/hosts/hetzner.svg create mode 100644 docs/app/assets/icons/hosts/sevalla-square.svg create mode 100644 docs/app/assets/icons/hosts/sevalla.svg create mode 100644 docs/app/assets/icons/hosts/vultr-square.svg create mode 100644 docs/app/assets/icons/hosts/vultr.svg diff --git a/docs/app/assets/icons/hosts/digitalocean-square.svg b/docs/app/assets/icons/hosts/digitalocean-square.svg new file mode 100644 index 000000000..ef70db6f7 --- /dev/null +++ b/docs/app/assets/icons/hosts/digitalocean-square.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/docs/app/assets/icons/hosts/digitalocean.svg b/docs/app/assets/icons/hosts/digitalocean.svg new file mode 100644 index 000000000..79ba1c65b --- /dev/null +++ b/docs/app/assets/icons/hosts/digitalocean.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/docs/app/assets/icons/hosts/hetzner-square.svg b/docs/app/assets/icons/hosts/hetzner-square.svg new file mode 100644 index 000000000..a91dce2f6 --- /dev/null +++ b/docs/app/assets/icons/hosts/hetzner-square.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/app/assets/icons/hosts/hetzner.svg b/docs/app/assets/icons/hosts/hetzner.svg new file mode 100644 index 000000000..f291a5f91 --- /dev/null +++ b/docs/app/assets/icons/hosts/hetzner.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/docs/app/assets/icons/hosts/sevalla-square.svg b/docs/app/assets/icons/hosts/sevalla-square.svg new file mode 100644 index 000000000..f431d5332 --- /dev/null +++ b/docs/app/assets/icons/hosts/sevalla-square.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/docs/app/assets/icons/hosts/sevalla.svg b/docs/app/assets/icons/hosts/sevalla.svg new file mode 100644 index 000000000..618233fe3 --- /dev/null +++ b/docs/app/assets/icons/hosts/sevalla.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/docs/app/assets/icons/hosts/vultr-square.svg b/docs/app/assets/icons/hosts/vultr-square.svg new file mode 100644 index 000000000..8f4866d9b --- /dev/null +++ b/docs/app/assets/icons/hosts/vultr-square.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/docs/app/assets/icons/hosts/vultr.svg b/docs/app/assets/icons/hosts/vultr.svg new file mode 100644 index 000000000..ee7dda82a --- /dev/null +++ b/docs/app/assets/icons/hosts/vultr.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/docs/nuxt.config.ts b/docs/nuxt.config.ts index 265d6043b..438972bea 100644 --- a/docs/nuxt.config.ts +++ b/docs/nuxt.config.ts @@ -68,6 +68,10 @@ export default defineNuxtConfig({ prefix: 'features', dir: './app/assets/icons/features' }, + { + prefix: 'hosts', + dir: './app/assets/icons/hosts' + }, { prefix: 'services', dir: './app/assets/icons/services' From ef0a0fba3d9b9acde8abcbbfa5cc9b156f73e3ed Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 4 Nov 2025 09:26:09 -0600 Subject: [PATCH 159/170] Add comprehensive documentation on choosing a hosting provider for containerized PHP applications. The guide covers portability, hosting options, recommended hosts, and key considerations for selecting the right host, enhancing user understanding of deployment strategies. --- .../5.choosing-a-host.md | 158 ++++++++++++++++++ 1 file changed, 158 insertions(+) create mode 100644 docs/content/docs/4.deployment-and-production/5.choosing-a-host.md diff --git a/docs/content/docs/4.deployment-and-production/5.choosing-a-host.md b/docs/content/docs/4.deployment-and-production/5.choosing-a-host.md new file mode 100644 index 000000000..9c9aa7c69 --- /dev/null +++ b/docs/content/docs/4.deployment-and-production/5.choosing-a-host.md @@ -0,0 +1,158 @@ +--- +title: Choosing a Host +description: 'Learn how to choose the right hosting provider for your containerized PHP application.' +layout: docs +--- + +::lead-p +One of the biggest advantages of containerizing your application is the ability to run your application anywhere. This gives you the freedom to choose the best host for your needs. Here's a guide to help you choose the right host for your needs. +:: + +## The beauty of portability +Because your application runs in a container, you're no longer tied to a specific hosting provider. The same container that runs on your laptop will run on: + +- Any VPS provider (DigitalOcean, Hetzner, Vultr, Linode, etc.) +- Cloud platforms (AWS, Google Cloud, Azure) +- Managed Kubernetes services +- Your own hardware in a data center +- Even a Raspberry Pi in your closet + +This portability means: +- **No vendor lock-in** - Switch hosts without rebuilding your application +- **Price shopping** - Move to cheaper providers if prices increase +- **Multi-cloud strategies** - Run on multiple providers for redundancy +- **Freedom to experiment** - Try different hosts without risk + +## Hosting options + +Choose your hosting based on your team's experience, budget, and application scale. Here's a quick comparison: + +| Hosting Type | Best For | Monthly Cost | Management Level | When to Choose | +|-------------|----------|--------------|------------------|----------------| +| **VPS** | Most PHP apps | $5-20 | Self-managed | You want control and best value | +| **Managed Kubernetes** | Enterprise/high-traffic | $70-100+ | Moderate | You need advanced orchestration | +| **Cloud Platforms** | Variable workloads | $20-50+ | Low | You want integrated cloud services | +| **PaaS** | Quick deployment | $25-100+ | Minimal | You want zero infrastructure hassle | + +::tip +**Our recommendation:** Start with a VPS unless you have specific needs. A $10/month VPS can handle what costs $50-100/month on PaaS, and you'll have full control over your infrastructure. +:: + +## Recommended Hosts +Below are our recommended hosts from our experience. Some links may contain referral codes, but these codes give you free credits to help you get started. These referral programs do not influence our recommendations. + +### VPS Hosts +::card-group + +::card +--- +title: Hetzner +icon: i-hosts-hetzner-square +to: https://hetzner.cloud/?ref=lhLUIrkdUPhl +target: _blank +--- +Hetzner is infamously known for its low prices and high performance. They are a great choice for small to medium-sized applications. +:: + +::card +--- +title: Vultr +icon: i-hosts-vultr-square +to: https://www.vultr.com/?ref=7093917 +target: _blank +--- +Vultr has great performance and and over 32 global data centers. +:: + +::card +--- +title: DigitalOcean +icon: i-hosts-digitalocean-square +to: https://m.do.co/c/f3bad4b927ca +target: _blank +--- +DigitalOcean is most known for it's simple user experience and vast support of many developer tools. +:: + +:: + +### PaaS Hosts +::card-group + +::card +--- +title: Sevalla +icon: i-hosts-sevalla-square +to: https://sevalla.com/ +target: _blank +--- +Sevalla is a modern PaaS with transparent usage-based pricing and no artificial limits. **Full disclosure:** Sevalla sponsors this project, but we genuinely recommend them for their refreshingly honest approach to PaaS pricing. +:: + +:: + +## Simplifying VPS setup with Spin +::tip{to="https://serversideup.net/open-source/spin/" target="_blank"} +[Spin](https://serversideup.net/open-source/spin/) is a free and open source tool that simplifies Docker workflows from development to production. +:: + + +Spin can automatically provision and configure servers on Hetzner, DigitalOcean, and Vultr, setting up Docker Swarm for zero-downtime deployments. It handles the infrastructure complexity while you maintain full control of your server. Here's a quick example with Laravel: + +:iframe{src="https://www.youtube-nocookie.com/embed/5z2JoEt5XIk?si=u5v-bDN-cMv0OE-C" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen style="aspect-ratio: 16/9; width: 100%;"} + +Spin is *not required* to run these Docker images, but it can help simplify the setup process. Spin was designed to have native integration with these images, but it can be used with any Docker setup. + +:u-button{to="https://serversideup.net/open-source/spin/" label="Learn more about Spin" aria-label="Learn more about Spin" target="_blank" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## What to consider when choosing a host + +- **Budget** - VPS offers best value ($10-20/mo), PaaS most expensive ($25-100+/mo) +- **Technical expertise** - VPS requires Linux knowledge, PaaS abstracts complexity +- **Scale** - Small/medium apps thrive on VPS, very large apps benefit from Kubernetes +- **Time investment** - PaaS saves time but costs more, VPS costs less but needs more hands-on +- **Data sovereignty** - Choose providers with data centers in your required regions +- **Growth trajectory** - VPS and Kubernetes scale cost-effectively, PaaS gets expensive + +#### Specifically for PaaS providers +- **Pricing** - Is the pricing transparent and upfront? Are there alerts if you're approaching your limits? +- **Debugging** - Are you able to access logs easily and debug issues? +- **Vendor lock-in** - Are you building around a proprietary platform, or can you easily migrate to another provider if needed? + +## Our recommendation for most projects + +If you're running a typical PHP application (Laravel, WordPress, custom app), here's our suggested progression: + +::steps{level="4"} + +#### Starting out: VPS provider like Hetzner or DigitalOcean ($5-10/month) +- Use Docker Swarm for single-server deployment +- Simple, affordable, and plenty of room to grow + +#### Growing: Performance tuning and hardware upgrades ($20-40/month) +- Focus on fine tuning your application for performance +- Upgrade your server hardware if needed (simple as a few clicks) + +#### At scale: Managed Kubernetes or multiple VPS servers (>$100/month) +- Move to Kubernetes when you need sophisticated orchestration +- Only consider if you *must* exceed [99.999% of uptime](https://uptime.is/99.999){target="_blank"} + +:: + +Most PHP applications never need to move beyond a well-configured VPS. A $20/month server can serve thousands of requests per second when properly optimized. + +::note +Don't let fancy infrastructure distract you from building your application. Pick what works for you. Start simple, prove your concept, then scale up as needed. +:: + +## Key requirements for any host +Regardless of which provider you choose, ensure they support: + +- **Docker installation** - Ability to install and run Docker (most Linux VPS hosts support this) +- **Adequate resources** - At minimum 1GB RAM, 1 CPU core (2GB+ recommended for most applications) +- **Security** - Strong security policies and practices to protect your application and data +- **Performance** - Good performance and quality hardware to handle your application's traffic +- **Network reliability** - Good uptime SLA and network performance +- **Responsive support team** - Quality and responsive support team to help you out when you need it +- **Data center location** - Close to your users for better performance +- **Backup options** - Either provided by host or easily implemented yourself (and we strongly recommend the [3-2-1 backup rule](https://en.wikipedia.org/wiki/Backup){target="_blank"}) From e3ccdb04acb8657b230dca59ece63bd68eb4b3d4 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 4 Nov 2025 09:31:51 -0600 Subject: [PATCH 160/170] Simplified examples on FPM --- docs/content/docs/2.image-variations/fpm.md | 67 ++++----------------- 1 file changed, 11 insertions(+), 56 deletions(-) diff --git a/docs/content/docs/2.image-variations/fpm.md b/docs/content/docs/2.image-variations/fpm.md index 7fbd392c9..6896e6466 100644 --- a/docs/content/docs/2.image-variations/fpm.md +++ b/docs/content/docs/2.image-variations/fpm.md @@ -45,11 +45,13 @@ Use the FPM variation when you need to: Unlike variations that include a web server, the FPM variation only runs PHP-FPM, which listens on port 9000 for FastCGI requests. You'll need a separate web server (like NGINX, Apache, or Caddy) to: -1. Accept HTTP requests from clients -2. Serve static files directly (CSS, JavaScript, images) -3. Forward PHP requests to the FPM container on port 9000 -4. Return the PHP-FPM response back to the client +::steps{level="4"} +#### Accept HTTP requests from clients +#### Serve static files directly (CSS, JavaScript, images) +#### Forward PHP requests to the FPM container on port 9000 +#### Return the PHP-FPM response back to the client +:: This architecture gives you maximum flexibility but requires more configuration than the all-in-one variations. ::note @@ -100,10 +102,6 @@ server { fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } - - location ~ /\.(?!well-known).* { - deny all; - } } ``` @@ -111,52 +109,13 @@ server { Notice how the `fastcgi_pass` directive points to `php:9000`. This is the service name from your Docker Compose file. Docker's networking allows services to communicate using their service names. :: -### Kubernetes Example -The FPM variation is particularly well-suited for Kubernetes deployments where you might have separate containers in the same pod. - -```yml [deployment.yaml] -apiVersion: apps/v1 -kind: Deployment -metadata: - name: my-app -spec: - replicas: 3 - selector: - matchLabels: - app: my-app - template: - metadata: - labels: - app: my-app - spec: - containers: - - name: nginx - image: nginx:alpine - ports: - - containerPort: 80 - volumeMounts: - - name: app-code - mountPath: /var/www/html - - name: nginx-config - mountPath: /etc/nginx/conf.d - - - name: php-fpm - image: serversideup/php:8.4-fpm - volumeMounts: - - name: app-code - mountPath: /var/www/html - - volumes: - - name: app-code - emptyDir: {} - - name: nginx-config - configMap: - name: nginx-config -``` - ### Health Check The FPM variation includes [`php-fpm-healthcheck`](https://github.com/renatomefi/php-fpm-healthcheck){target="_blank"}, a POSIX-compliant script that monitors PHP-FPM's `/status` endpoint to verify the service is healthy. +::tip +The `php-fpm-healthcheck` script can also monitor specific metrics like accepted connections or queue length. For example, you could fail the health check if the listen queue exceeds 10 processes: `php-fpm-healthcheck --listen-queue=10` +:: + ```yml [compose.yml]{7-10} services: php: @@ -164,16 +123,12 @@ services: volumes: - ./:/var/www/html healthcheck: - test: ["CMD", "php-fpm-healthcheck"] + test: ["CMD", "php-fpm-healthcheck", "--listen-queue=10"] interval: 10s timeout: 3s retries: 3 ``` -::tip -The `php-fpm-healthcheck` script can also monitor specific metrics like accepted connections or queue length. For example, you could fail the health check if the listen queue exceeds 10 processes: `php-fpm-healthcheck --listen-queue=10` -:: - ## Environment Variables The FPM variation supports extensive customization through environment variables. Here are some common ones: From 8395ba3350ab0ec850e4c72d1a24b93136232b5a Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 4 Nov 2025 09:41:45 -0600 Subject: [PATCH 161/170] Add health check information for Laravel in FPM-Apache and FPM-NGINX documentation. Include a link to the guide on using healthchecks with Laravel for better user guidance. --- docs/content/docs/2.image-variations/fpm-apache.md | 7 +++++++ docs/content/docs/2.image-variations/fpm-nginx.md | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/docs/content/docs/2.image-variations/fpm-apache.md b/docs/content/docs/2.image-variations/fpm-apache.md index 07dfd4184..a39183fc8 100644 --- a/docs/content/docs/2.image-variations/fpm-apache.md +++ b/docs/content/docs/2.image-variations/fpm-apache.md @@ -149,7 +149,14 @@ The FPM-Apache variation includes a built-in health check that verifies Apache i The health check endpoint is configurable via the `HEALTHCHECK_PATH` environment variable, which defaults to `/healthcheck`. :: +If you are using Laravel, you can use the `/up` route to validate that Laravel is running and healthy. + +:u-button{to="/docs/guide/using-healthchecks-with-laravel" label="Learn more about using healthchecks with Laravel" aria-label="Learn more about using healthchecks with Laravel" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + ## SSL/TLS Support +::tip{to="/docs/deployment-and-production/configuring-ssl"} +For more information on SSL, see the [Configuring SSL](/docs/deployment-and-production/configuring-ssl) guide. +:: The FPM-Apache variation includes built-in SSL support with self-signed certificates for development. ### Enabling SSL diff --git a/docs/content/docs/2.image-variations/fpm-nginx.md b/docs/content/docs/2.image-variations/fpm-nginx.md index 6b5785f37..f4ace3da7 100644 --- a/docs/content/docs/2.image-variations/fpm-nginx.md +++ b/docs/content/docs/2.image-variations/fpm-nginx.md @@ -152,6 +152,10 @@ The FPM-NGINX variation includes a built-in health check that verifies NGINX is The health check endpoint is configurable via the `HEALTHCHECK_PATH` environment variable, which defaults to `/healthcheck`. :: +If you are using Laravel, you can use the `/up` route to validate that Laravel is running and healthy. + +:u-button{to="/docs/guide/using-healthchecks-with-laravel" label="Learn more about using healthchecks with Laravel" aria-label="Learn more about using healthchecks with Laravel" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + ## SSL/TLS Support The FPM-NGINX variation includes built-in SSL support with self-signed certificates for development. From d163b132726ba3761546d415d3618a3215c9e6c7 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 4 Nov 2025 10:27:54 -0600 Subject: [PATCH 162/170] Update environment variable documentation to replace `CADDY_APP_PUBLIC_PATH` with `CADDY_SERVER_ROOT` for clarity and consistency. Adjust Caddyfile configuration to reflect the new variable, ensuring accurate root directory settings for the Caddy server. --- .../docs/8.reference/1.environment-variable-specification.md | 2 +- src/variations/frankenphp/etc/frankenphp/Caddyfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/docs/8.reference/1.environment-variable-specification.md b/docs/content/docs/8.reference/1.environment-variable-specification.md index 760ecc17e..3fbbd126d 100644 --- a/docs/content/docs/8.reference/1.environment-variable-specification.md +++ b/docs/content/docs/8.reference/1.environment-variable-specification.md @@ -45,7 +45,6 @@ Setting environment variables all depends on what method you're using to run you `AUTORUN_LARAVEL_STORAGE_LINK`
*Default: "true"*|Automatically run "php artisan storage:link" on container start.
ℹ️ Requires `AUTORUN_ENABLED = true` to run.| all `AUTORUN_LARAVEL_VIEW_CACHE`
*Default: "true"*|Automatically run "php artisan view:cache" on container start.
ℹ️ Requires `AUTORUN_ENABLED = true` to run.| all `CADDY_ADMIN`
*Default: "off"*|Enable Caddy admin interface. (Official docs)|frankenphp -`CADDY_APP_PUBLIC_PATH`
*Default: "/var/www/html/public"*|The path to your public directory for your app. (Official docs)|frankenphp `CADDY_AUTO_HTTPS`
*Default: "off"*|Enable automatic HTTPS. (Official docs)|frankenphp `CADDY_GLOBAL_OPTIONS`
*Default: ""*|Set global options for the Caddy server. (Official docs)|frankenphp `CADDY_HTTP_PORT`
*Default: "8080"*|Set the port for HTTP. (Official docs)|frankenphp @@ -57,6 +56,7 @@ Setting environment variables all depends on what method you're using to run you `CADDY_LOG_OUTPUT`
*Default: "stdout"*|Set the output for the Caddy log. (Official docs)|frankenphp `CADDY_PHP_SERVER_OPTIONS`
*Default: ""*|Set PHP server options for the Caddy server. (Official docs)|frankenphp `CADDY_SERVER_EXTRA_DIRECTIVES`
*Default: ""*|Set extra directives for the Caddy server. (Official docs)|frankenphp +`CADDY_SERVER_ROOT`
*Default: "/var/www/html/public"*|Set the root directory for the Caddy server. (Official docs)|frankenphp `COMPOSER_ALLOW_SUPERUSER`
*Default: "1"*|Disable warning about running as super-user|all `COMPOSER_HOME`
*Default: "/composer"*|The COMPOSER_HOME variable allows you to change the Composer home directory. This is a hidden, global (per-user on the machine) directory that is shared between all projects.|all `COMPOSER_MAX_PARALLEL_HTTP`
*Default: "24"*|Set to an integer to configure how many files can be downloaded in parallel. Composer ships with 12 by default and must be between 1 and 50. If your proxy has issues with concurrency maybe you want to lower this. Increasing it should generally not result in performance gains.|all diff --git a/src/variations/frankenphp/etc/frankenphp/Caddyfile b/src/variations/frankenphp/etc/frankenphp/Caddyfile index a785add5f..566911126 100644 --- a/src/variations/frankenphp/etc/frankenphp/Caddyfile +++ b/src/variations/frankenphp/etc/frankenphp/Caddyfile @@ -71,7 +71,7 @@ fd00::/8 \ # Common app logic; reused across all modes (php-app-common) { - root * {$CADDY_APP_PUBLIC_PATH:/var/www/html/public} + root * {$CADDY_SERVER_ROOT:/var/www/html/public} encode zstd br gzip From 8a7603748f9b1cab2f35bac2482ab3ca580300c0 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 4 Nov 2025 10:28:25 -0600 Subject: [PATCH 163/170] Update Dockerfile to replace `CADDY_APP_PUBLIC_PATH` with `CADDY_SERVER_ROOT` for improved clarity in server configuration. --- src/variations/frankenphp/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/variations/frankenphp/Dockerfile b/src/variations/frankenphp/Dockerfile index b5ed10167..05f6cb3e3 100644 --- a/src/variations/frankenphp/Dockerfile +++ b/src/variations/frankenphp/Dockerfile @@ -127,7 +127,6 @@ LABEL org.opencontainers.image.title="serversideup/php (frankenphp)" \ ENV APP_BASE_DIR=/var/www/html \ CADDY_ADMIN="off" \ - CADDY_APP_PUBLIC_PATH="/var/www/html/public" \ CADDY_AUTO_HTTPS="off" \ CADDY_GLOBAL_OPTIONS="" \ CADDY_HTTP_PORT="8080" \ @@ -138,6 +137,7 @@ LABEL org.opencontainers.image.title="serversideup/php (frankenphp)" \ CADDY_LOG_OUTPUT="stdout" \ CADDY_PHP_SERVER_OPTIONS="" \ CADDY_SERVER_EXTRA_DIRECTIVES="" \ + CADDY_SERVER_ROOT="/var/www/html/public" \ COMPOSER_ALLOW_SUPERUSER=1 \ COMPOSER_HOME=/composer \ COMPOSER_MAX_PARALLEL_HTTP=24 \ From 5151886812a73263aec7510b3b85a7aab0e696e7 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 4 Nov 2025 10:48:46 -0600 Subject: [PATCH 164/170] A-Z the caddy variables --- .../docs/8.reference/1.environment-variable-specification.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/docs/8.reference/1.environment-variable-specification.md b/docs/content/docs/8.reference/1.environment-variable-specification.md index 3fbbd126d..9587b4675 100644 --- a/docs/content/docs/8.reference/1.environment-variable-specification.md +++ b/docs/content/docs/8.reference/1.environment-variable-specification.md @@ -48,14 +48,14 @@ Setting environment variables all depends on what method you're using to run you `CADDY_AUTO_HTTPS`
*Default: "off"*|Enable automatic HTTPS. (Official docs)|frankenphp `CADDY_GLOBAL_OPTIONS`
*Default: ""*|Set global options for the Caddy server. (Official docs)|frankenphp `CADDY_HTTP_PORT`
*Default: "8080"*|Set the port for HTTP. (Official docs)|frankenphp -`CADDY_HTTPS_PORT`
*Default: "8443"*|Set the port for HTTPS. (Official docs)|frankenphp `CADDY_HTTP_SERVER_ADDRESS`
*Default: "http://"*|Set the server address for HTTP. (Official docs)|frankenphp +`CADDY_HTTPS_PORT`
*Default: "8443"*|Set the port for HTTPS. (Official docs)|frankenphp `CADDY_HTTPS_SERVER_ADDRESS`
*Default: "https://"*|Set the server address for HTTPS. (Official docs)|frankenphp `CADDY_LOG_FORMAT`
*Default: "console"*|Set the format for the Caddy log. (Official docs)|frankenphp -`CADDY_SERVER_LOG_LEVEL`
*Default: "warn"*|Set the server log level for the Caddy server. This can also be changed with `LOG_OUTPUT_LEVEL`, but `CADDY_SERVER_LOG_LEVEL` takes precedence. (Official docs)|frankenphp `CADDY_LOG_OUTPUT`
*Default: "stdout"*|Set the output for the Caddy log. (Official docs)|frankenphp `CADDY_PHP_SERVER_OPTIONS`
*Default: ""*|Set PHP server options for the Caddy server. (Official docs)|frankenphp `CADDY_SERVER_EXTRA_DIRECTIVES`
*Default: ""*|Set extra directives for the Caddy server. (Official docs)|frankenphp +`CADDY_SERVER_LOG_LEVEL`
*Default: "warn"*|Set the server log level for the Caddy server. This can also be changed with `LOG_OUTPUT_LEVEL`, but `CADDY_SERVER_LOG_LEVEL` takes precedence. (Official docs)|frankenphp `CADDY_SERVER_ROOT`
*Default: "/var/www/html/public"*|Set the root directory for the Caddy server. (Official docs)|frankenphp `COMPOSER_ALLOW_SUPERUSER`
*Default: "1"*|Disable warning about running as super-user|all `COMPOSER_HOME`
*Default: "/composer"*|The COMPOSER_HOME variable allows you to change the Composer home directory. This is a hidden, global (per-user on the machine) directory that is shared between all projects.|all From 60d4a790e4d5ebc89edd851bfb46efe13dee2361 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 4 Nov 2025 10:49:00 -0600 Subject: [PATCH 165/170] Add comprehensive documentation for the FrankenPHP variation of the serversideup/php image. This includes usage guidelines, feature comparisons, setup instructions, and environment variable configurations, aimed at enhancing user understanding and adoption of this modern PHP application server. --- .../docs/2.image-variations/frankenphp.md | 308 ++++++++++++++++++ 1 file changed, 308 insertions(+) create mode 100644 docs/content/docs/2.image-variations/frankenphp.md diff --git a/docs/content/docs/2.image-variations/frankenphp.md b/docs/content/docs/2.image-variations/frankenphp.md new file mode 100644 index 000000000..2a7a414c7 --- /dev/null +++ b/docs/content/docs/2.image-variations/frankenphp.md @@ -0,0 +1,308 @@ +--- +title: FrankenPHP +description: 'Learn how to use the FrankenPHP variation of the serversideup/php image.' +--- + +::lead-p +The FrankenPHP variation is a modern application server built on top of the Caddy web server. It runs PHP and the web server in a single process, eliminating the complexity of managing PHP-FPM and a separate web server. + +This is the cutting-edge variation that offers worker mode, automatic HTTPS, and modern protocols like HTTP/2 and HTTP/3. It's the recommended variation for new Laravel projects seeking maximum performance. +:: + +## When to Use FrankenPHP +Use the FrankenPHP variation when you need to: + +- Run Laravel Octane with maximum performance +- Use worker mode to keep your application in memory +- Get automatic HTTPS with zero configuration +- Support modern protocols like HTTP/2 and HTTP/3 +- Simplify your container architecture (single process) +- Deploy Symfony applications with the Runtime component + +#### Perfect for +- Laravel Octane applications +- Symfony applications using the Runtime component +- Modern PHP applications that can benefit from worker mode +- Projects requiring automatic HTTPS +- High-performance APIs that benefit from persistent connections +- Teams wanting the latest and greatest in PHP application servers +- Apps that need PHP 8.3 or newer + +## Comparing FrankenPHP to Other Variations + +| Feature | FrankenPHP | FPM-NGINX | FPM-Apache | +|---------|-----------|-----------|------------| +| Performance | ⚡️ Excellent (worker mode) | ✅ Very Good | ✅ Good | +| Setup Complexity | ✅ Simple | ✅ Simple | ✅ Simple | +| Worker Mode | ✅ Yes | ❌ No | ❌ No | +| Automatic HTTPS | ✅ Yes | ❌ No | ❌ No | +| HTTP/3 Support | ✅ Yes | ❌ No | ❌ No | +| Laravel Octane | ✅ Native support | ⚠️ Use Swoole | ⚠️ Use Swoole | +| .htaccess Support | ❌ No | ❌ No | ✅ Yes | +| Maturity | ⚠️ New | ✅ Mature | ✅ Mature | + +::tip +FrankenPHP is the newest variation and represents the future of PHP application servers. If you're starting a new project and can commit to modern practices, this is the variation to choose. +:: + + +#### Known Issues +::warning{to="https://frankenphp.dev/docs/known-issues/#standalone-binary-and-alpine-based-docker-images" target="_blank"} +Some people are reporting performance issues on the `alpine` version of FrankenPHP. If you're experiencing this, consider using the `debian` version. +:: + +FrankenPHP is cutting edge and is a very active project. Be sure to understand FrankenPHP's known issues before using it in production. If you're looking for better compatibility, consider using the [FPM-NGINX](/docs/image-variations/fpm-nginx) image. + +:u-button{to="https://frankenphp.dev/docs/known-issues/" target="_blank" label="View FrankenPHP's known issues" aria-label="FrankenPHP known issues" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +#### What's Inside + +| Item | Status | +|------|--------| +| FrankenPHP application server | ✅ | +| Caddy web server | ✅ (built-in) | +| PHP CLI binary | ✅ | +| Common PHP extensions | ✅ | +| `composer` executable | ✅ | +| `install-php-extensions` script | ✅ | +| Essential system utilities | ✅ | +| Worker mode support | ✅ | +| Automatic HTTPS | ✅ | +| HTTP/2 support | ✅ | +| HTTP/3 support | ✅ | +| Mercure (real-time) | ✅ | +| Native health checks | ✅ (via HTTP endpoint) | +| SSL/TLS support | ✅ (automatic + self-signed) | +| Process management | Single process (no supervisor needed) | +| Exposed Ports | `8080` (HTTP), `8443` (HTTPS + HTTP/3), `2019` (Caddy admin) | +| Stop Signal | `SIGTERM` | + +## Classic Mode vs Worker Mode +Unlike traditional setups that require a separate web server and PHP-FPM, FrankenPHP runs everything in a single process. It also operates in two modes: + +#### Classic Mode (Default) +- FrankenPHP functions like a traditional PHP server (similar to PHP-FPM) +- Each request bootstraps your application fresh +- No additional configuration needed +- Safe for any existing PHP applications + +#### Worker Mode (Advanced) +Worker mode is FrankenPHP's killer feature. Instead of bootstrapping your application for every request, it stays loaded in memory: + +- **Traditional**: Bootstrap app → Handle request → Teardown → Repeat +- **Worker Mode**: Bootstrap app once → Handle requests indefinitely + +This can result in dramatic performance improvements for Laravel applications. + +::tip +Worker mode is perfect for Laravel Octane. Your application boots once and handles thousands of requests without reloading, dramatically improving response times. +:: + +## How FrankenPHP Works + +::steps{level="4"} + +#### Client sends request +The client sends an HTTP request to port 8080 (or 8443 for HTTPS). + +#### FrankenPHP receives and processes the request +FrankenPHP receives and processes the request directly in a single process. This includes: + +1. Static files +2. PHP requests + +#### Send response back to client +The response is sent back to the client. + +:: + +## Quick Start +Here are a few examples to help you get started with the FrankenPHP variation. + +### Docker CLI + +```bash [Terminal] +docker run -p 80:8080 -v $(pwd):/var/www/html/public serversideup/php:8.4-frankenphp +``` + +Your application will be available at `http://localhost`. The default webroot is `/var/www/html/public`. + +### Docker Compose +Here's a basic example getting FrankenPHP up and running with Docker Compose. + +::warning +Don't forget to create a `public` directory and put your PHP code in there. +:: + +::code-tree{defaultValue="compose.yml"} + +```yml [compose.yml] +services: + php: + # Choose our PHP version and variation + image: serversideup/php:8.4-frankenphp + # Expose and map HTTP and HTTPS ports + ports: + - 80:8080 + - 443:8443 + # Mount current directory to /var/www/html + volumes: + - ./:/var/www/html + # Support both HTTP and HTTPS + environment: + SSL_MODE: mixed +``` + +```php [public/index.php] + +``` +:: + +::tip +The FrankenPHP variation uses ports 8080 and 8443 (instead of 80 and 443) to allow the container to run as a non-root user for better security. +:: + +### Laravel Octane +Laravel Octane natively supports FrankenPHP. Use our guide below to learn more. + +:u-button{to="/docs/framework-guides/laravel/octane" label="Learn more about Laravel Octane" aria-label="Learn more about Laravel Octane" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +### Health Check +The FrankenPHP variation includes a built-in health check that verifies the server is responding: + +::note +The health check endpoint is configurable via the `HEALTHCHECK_PATH` environment variable, which defaults to `/healthcheck`. +:: + +If you are using Laravel, you can use the `/up` route to validate that Laravel is running and healthy. + +:u-button{to="/docs/guide/using-healthchecks-with-laravel" label="Learn more about using healthchecks with Laravel" aria-label="Learn more about using healthchecks with Laravel" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## Automatic HTTPS +One of FrankenPHP's standout features is automatic HTTPS powered by Caddy. It can automatically obtain and renew SSL certificates from Let's Encrypt. + +::tip{to="/docs/deployment-and-production/configuring-ssl"} +See our [Configuring SSL](/docs/deployment-and-production/configuring-ssl) guide for more information on the best strategies for running SSL in production. +:: + +### Enabling Automatic HTTPS +```yml [compose.yml] +services: + php: + image: serversideup/php:8.4-frankenphp + ports: + - "80:8080" + - "443:8443" + volumes: + - ./:/var/www/html + environment: + CADDY_AUTO_HTTPS: "on" + # Your domain for automatic certificate + SERVER_NAME: "example.com" + SSL_MODE: "full" +``` + +::warning +Automatic HTTPS requires a public domain name and ports 80/443 accessible from the internet for Let's Encrypt validation. For local development, use self-signed certificates with `SSL_MODE`. +:: + +### SSL Modes for Development +For local development, use the `SSL_MODE` environment variable: + +```yml [compose.yml] +services: + php: + image: serversideup/php:8.4-frankenphp + ports: + - "80:8080" + - "443:8443" + volumes: + - ./:/var/www/html + environment: + SSL_MODE: "full" +``` + +Available SSL modes: +- `off` - SSL disabled (default) +- `mixed` - Both HTTP (8080) and HTTPS (8443) enabled +- `full` - HTTPS only on port 8443 + +Learn more about SSL modes in the [Configuring SSL](/docs/deployment-and-production/configuring-ssl) guide. + +:u-button{to="/docs/deployment-and-production/configuring-ssl" label="Learn more about SSL modes" aria-label="Learn more about SSL modes" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## Environment Variables +The FrankenPHP variation supports extensive customization through environment variables. + +### FrankenPHP/Caddy Configuration + +| Variable | Default | Description | +|----------|---------|-------------| +| `FRANKENPHP_CONFIG` | `""` | FrankenPHP-specific configuration (e.g., worker mode) | +| `CADDY_SERVER_ROOT` | `/var/www/html/public` | Document root for the application | +| `CADDY_AUTO_HTTPS` | `off` | Enable automatic HTTPS (`on`/`off`) | +| `CADDY_HTTP_PORT` | `8080` | HTTP port | +| `CADDY_HTTPS_PORT` | `8443` | HTTPS port | +| `CADDY_ADMIN` | `off` | Caddy admin API endpoint | +| `CADDY_LOG_FORMAT` | `console` | Log format (`console`/`json`) | +| `CADDY_LOG_OUTPUT` | `stdout` | Log output destination | +| `CADDY_GLOBAL_OPTIONS` | `""` | Additional Caddy global options | +| `CADDY_SERVER_EXTRA_DIRECTIVES` | `""` | Additional Caddy server directives | +| `SSL_MODE` | `off` | SSL mode: `off`, `mixed`, or `full` | +| `SSL_CERTIFICATE_FILE` | `/etc/ssl/private/self-signed-web.crt` | Path to SSL certificate | +| `SSL_PRIVATE_KEY_FILE` | `/etc/ssl/private/self-signed-web.key` | Path to SSL private key | +| `HEALTHCHECK_PATH` | `/healthcheck` | Path for health check endpoint | +| `SERVER_NAME` | `""` | Domain name for automatic HTTPS | + +::tip{to="/docs/reference/environment-variable-specification"} +For a complete list of available environment variables, see the [Environment Variable Specification →](/docs/reference/environment-variable-specification). +:: + +### PHP Configuration + +| Variable | Default | Description | +|----------|---------|-------------| +| `PHP_MEMORY_LIMIT` | `256M` | Maximum memory a script can use | +| `PHP_MAX_EXECUTION_TIME` | `99` | Maximum time a script can run (seconds) | +| `PHP_UPLOAD_MAX_FILE_SIZE` | `100M` | Maximum upload file size | +| `PHP_POST_MAX_SIZE` | `100M` | Maximum POST request size | +| `PHP_OPCACHE_ENABLE` | `0` | Enable OPcache (`0`/`1`) | +| `PHP_OPCACHE_REVALIDATE_FREQ` | `2` | How often to check for file changes (seconds) | +| `PHP_OPCACHE_VALIDATE_TIMESTAMPS` | `1` | Whether to validate timestamps (`0`/`1`) | + +## Caddy Configuration +FrankenPHP uses Caddy's configuration format (Caddyfile) instead of NGINX configuration. + +### Adding Custom Options +There are a few areas where you can use environment variables to customize your Caddy configuration: + +| Variable | Description | Official Documentation | +|----------|-------------|-------------| +| `CADDY_GLOBAL_OPTIONS` | Global Caddy options | [Caddy Global Options](https://caddyserver.com/docs/caddyfile/options){target="_blank"} | +| `CADDY_SERVER_EXTRA_DIRECTIVES` | Server-specific Caddy directives | [Caddy Server Directives](https://caddyserver.com/docs/caddyfile/directives){target="_blank"} | +| `CADDY_PHP_SERVER_OPTIONS` | PHP-specific Caddy directives (site-specific) | [FrankenPHP PHP Server Options](https://frankenphp.dev/docs/config/#caddyfile-config){target="_blank"} | +| `FRANKENPHP_CONFIG` | FrankenPHP-specific configuration (global) | [FrankenPHP Configuration](https://frankenphp.dev/docs/config/#caddyfile-config){target="_blank"} | + +```yml [compose.yml] +services: + php: + image: serversideup/php:8.4-frankenphp + environment: + CADDY_SERVER_EXTRA_DIRECTIVES: | + # Add custom headers + header { + X-Custom-Header "My Value" + -Server + } +``` + +## Further Customization +If you need to customize the container further, reference the docs below: + +- [Environment Variable Specification](/docs/reference/environment-variable-specification) - See which environment variables are available to customize PHP and Caddy settings. +- [Command Reference](/docs/reference/command-reference) - See which commands are available to run inside the container. +- [FrankenPHP Documentation](https://frankenphp.dev/){target="_blank"} - Official FrankenPHP documentation for advanced features. +- [Caddy Documentation](https://caddyserver.com/docs/){target="_blank"} - Official Caddy documentation for web server configuration. \ No newline at end of file From 833a8671bbc86f73c7e645f5cb55552213aee8b0 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 4 Nov 2025 11:55:31 -0600 Subject: [PATCH 166/170] Add documentation for configuring Laravel Octane with Docker, including setup instructions, health check implementation, and performance considerations. Introduce a health check script for Octane to ensure proper application status monitoring. --- .../3.framework-guides/1.laravel/octane.md | 101 ++++++++++++++++++ src/common/usr/local/bin/healthcheck-octane | 2 + 2 files changed, 103 insertions(+) create mode 100644 docs/content/docs/3.framework-guides/1.laravel/octane.md create mode 100644 src/common/usr/local/bin/healthcheck-octane diff --git a/docs/content/docs/3.framework-guides/1.laravel/octane.md b/docs/content/docs/3.framework-guides/1.laravel/octane.md new file mode 100644 index 000000000..41e83f063 --- /dev/null +++ b/docs/content/docs/3.framework-guides/1.laravel/octane.md @@ -0,0 +1,101 @@ +--- +head.title: 'Laravel Octane with Docker - Docker PHP - Server Side Up' +description: 'Learn how to configure Laravel Octane with Docker.' +layout: docs +title: Octane +--- + +::lead-p +Laravel Octane supercharges your application's performance by keeping it loaded in memory and serving requests at incredible speeds. The FrankenPHP variation of our images provides native Octane support with worker mode built-in. +:: + +## What is Laravel Octane? + +Laravel Octane boots your Laravel application once and keeps it in memory, then processes thousands of requests without reloading. This dramatically improves performance compared to traditional PHP execution. + +**Traditional PHP:** +Bootstrap → Handle Request → Teardown → Repeat for every request + +**With Octane:** +Bootstrap once → Handle unlimited requests + +::tip +FrankenPHP is Laravel's recommended application server for Octane and is included natively in our images. No additional installation required. +:: + +## Quick Start +Let's use this example project to get started. + +::warning{to="https://serversideup.net/open-source/spin/docs" target="_blank"} +This example assumes you already have a Laravel application installed. If you need help installing a new Laravel project with Docker, check out [Spin](https://serversideup.net/open-source/spin/docs){target="_blank"} for a simple way to get started. +:: + +### Classic Mode +By default, FrankenPHP runs in classic mode. Your compose file might look something like this: + +```yml [compose.yml] +services: + php: + image: serversideup/php:8.4-frankenphp + ports: + - "80:8080" + volumes: + - .:/var/www/html/ +``` + +We'll expand upon this classic mode file and modify it to run Laravel Octane (which uses FrankenPHP's worker mode). + +### Install Laravel Octane + +First, install Octane in your Laravel application: + +```bash [Terminal] +docker compose run php composer require laravel/octane +``` + +### Configure Worker Mode +We now want to update the compose file to run Laravel Octane and use proper health checks. + + +```yml [compose.yml]{8-13} +services: + php: + image: serversideup/php:8.4-frankenphp + ports: + - "80:8080" + volumes: + - .:/var/www/html/ + # Start Octane in worker mode + command: ["php", "artisan", "octane:start", "--server=frankenphp", "--port=8080"] + # Set healthcheck to use our native healthcheck script for Octane + healthcheck: + test: ["CMD", "healthcheck-octane"] + start_period: 10s +``` +We make two major changes here: +1. **Set the command to start Octane in worker mode** - Instead of starting FrankenPHP in classic mode, we start Octane in worker mode. +2. **Set the healthcheck to use our native healthcheck script for Octane** - This is important to ensure that Octane is running and healthy. + +### Testing Locally + +Run your application locally to test Octane: + +```bash [Terminal] +docker compose up +``` + +Your Laravel application will be available at `http://localhost` with Octane running in worker mode. + +## Things to Watch Out For +Since Octane is a whole different way of running Laravel compared to traditional PHP-FPM, there are a few things to watch out for. + +### Dependency Injection +Be careful with how you inject dependencies into long-lived objects. Injecting the wrong things into constructors can cause requests to "leak" between users. Review Laravel's [Dependency Injection and Octane](https://laravel.com/docs/12.x/octane#dependency-injection-and-octane) documentation for details. + +### Memory Leaks +Review Laravel's [Octane documentation on memory leaks](https://laravel.com/docs/12.x/octane#managing-memory-leaks) to understand what to avoid. + +## Learn More +- [FrankenPHP Variation Documentation](/docs/image-variations/frankenphp) +- [Laravel Octane Documentation](https://laravel.com/docs/12.x/octane) +- [FrankenPHP Documentation](https://frankenphp.dev/docs/) \ No newline at end of file diff --git a/src/common/usr/local/bin/healthcheck-octane b/src/common/usr/local/bin/healthcheck-octane new file mode 100644 index 000000000..07130fc50 --- /dev/null +++ b/src/common/usr/local/bin/healthcheck-octane @@ -0,0 +1,2 @@ +#!/bin/sh +php "${APP_BASE_DIR}/artisan" octane:status \ No newline at end of file From 3b6733155333962f1feb0a6ada421b515f865e42 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 4 Nov 2025 12:06:33 -0600 Subject: [PATCH 167/170] Update links in image variations documentation for consistency and improved navigation. Adjusted paths to ensure they are correctly formatted for internal referencing. --- docs/content/docs/2.image-variations/cli.md | 4 ++-- docs/content/docs/2.image-variations/fpm-nginx.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content/docs/2.image-variations/cli.md b/docs/content/docs/2.image-variations/cli.md index ce863bfe3..85d525189 100644 --- a/docs/content/docs/2.image-variations/cli.md +++ b/docs/content/docs/2.image-variations/cli.md @@ -74,5 +74,5 @@ docker compose run php php my-script.php ### Further Customization If you need to customize the container further, reference the docs below: -- [Environment Variable Specifications](docs/reference/environment-variable-specification) - See which environment variables are available to customize common PHP settings. -- [Command Reference](docs/reference/command-reference) - See which commands are available to run inside the container. +- [Environment Variable Specifications](/docs/reference/environment-variable-specification) - See which environment variables are available to customize common PHP settings. +- [Command Reference](/docs/reference/command-reference) - See which commands are available to run inside the container. diff --git a/docs/content/docs/2.image-variations/fpm-nginx.md b/docs/content/docs/2.image-variations/fpm-nginx.md index f4ace3da7..9b6e72e1f 100644 --- a/docs/content/docs/2.image-variations/fpm-nginx.md +++ b/docs/content/docs/2.image-variations/fpm-nginx.md @@ -242,7 +242,7 @@ For a complete list of available environment variables, see the [Environment Var Here are some tuning recommendations for different scenarios: ### For Production (low memory environments) -::note{to="docs/deployment-and-production/packaging-your-app-for-deployment"} +::note{to="/docs/deployment-and-production/packaging-your-app-for-deployment"} If you're running an application in production, you'll likely want to package your application inside an image for deployment. Click here to learn more. :: ```yml [compose.yml] From bc4211dc8f882d29189d7028fcedf7dec78b5e67 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 4 Nov 2025 12:37:49 -0600 Subject: [PATCH 168/170] Reintroduce redirect logic for page navigation in [...slug].vue to ensure users are properly redirected when a page has a redirect property. This change enhances user experience by maintaining expected navigation behavior. --- docs/app/pages/[...slug].vue | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/app/pages/[...slug].vue b/docs/app/pages/[...slug].vue index d4937684f..bbb43b41c 100644 --- a/docs/app/pages/[...slug].vue +++ b/docs/app/pages/[...slug].vue @@ -77,10 +77,6 @@ if (!page.value) { throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true }) } -if (page.value?.redirect) { - navigateTo(page.value?.redirect) -} - const { data: surround } = await useAsyncData(`${route.path}-surround`, () => { return queryCollectionItemSurroundings('docs', route.path, { fields: ['description'] @@ -103,6 +99,10 @@ defineOgImageComponent('Docs', { headline: headline.value }) +if (page.value?.redirect) { + navigateTo(page.value?.redirect) +} + const links = computed(() => { const links = [] if (toc?.bottom?.edit) { From 01c54668187aa37a84eda24064fad5d4f4721fc2 Mon Sep 17 00:00:00 2001 From: Dan Pastori Date: Tue, 4 Nov 2025 13:48:33 -0600 Subject: [PATCH 169/170] Only navigate after mount. This allows us to build the site --- docs/app/pages/[...slug].vue | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/app/pages/[...slug].vue b/docs/app/pages/[...slug].vue index bbb43b41c..97f5aa86a 100644 --- a/docs/app/pages/[...slug].vue +++ b/docs/app/pages/[...slug].vue @@ -99,10 +99,6 @@ defineOgImageComponent('Docs', { headline: headline.value }) -if (page.value?.redirect) { - navigateTo(page.value?.redirect) -} - const links = computed(() => { const links = [] if (toc?.bottom?.edit) { @@ -116,4 +112,10 @@ const links = computed(() => { return [...links, ...(toc?.bottom?.links || [])].filter(Boolean) }) + +onMounted(() => { + if (page.value?.redirect) { + navigateTo(page.value?.redirect) + } +}) \ No newline at end of file From bfd396bf8e7940a6423c644d07ce266fcd6705fa Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Tue, 4 Nov 2025 14:42:13 -0600 Subject: [PATCH 170/170] Update environment variable documentation to include `frankenphp` in the `SSL_PRIVATE_KEY_FILE` entry, enhancing clarity on supported configurations for HTTPS. --- .../docs/8.reference/1.environment-variable-specification.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/8.reference/1.environment-variable-specification.md b/docs/content/docs/8.reference/1.environment-variable-specification.md index 9587b4675..90ac8db3b 100644 --- a/docs/content/docs/8.reference/1.environment-variable-specification.md +++ b/docs/content/docs/8.reference/1.environment-variable-specification.md @@ -116,7 +116,7 @@ Setting environment variables all depends on what method you're using to run you `SHOW_WELCOME_MESSAGE`
*Default: "true"*|Show a helpful welcome message showing container information when the container starts.|all `SSL_CERTIFICATE_FILE`
*Default: "/etc/ssl/private/self-signed-web.crt"*|Path to public certificate file for HTTPS. You must provide this file otherwise a self-signed key pair will be generated for you.|fpm-nginx,
fpm-apache `SSL_MODE`
*Default: "off"*|Configure how you would like to handle SSL. This can be "off" (HTTP only), "mixed" (HTTP + HTTPS), or "full" (HTTPS only). If you use HTTP, you may need to also change `PHP_SESSION_COOKIE_SECURE`.|fpm-nginx,
fpm-apache,
unit -`SSL_PRIVATE_KEY_FILE`
*Default: "/etc/ssl/private/self-signed-web.key"*|Path to private key file for HTTPS. You must provide this file otherwise a self-signed key pair will be generated for you.|fpm-nginx,
fpm-apache +`SSL_PRIVATE_KEY_FILE`
*Default: "/etc/ssl/private/self-signed-web.key"*|Path to private key file for HTTPS. You must provide this file otherwise a self-signed key pair will be generated for you.|fpm-nginx,
fpm-apache,
frankenphp `UNIT_CERTIFICATE_NAME`
*Default: "self-signed-web-bundle"*| Name of your certificate bundle. This is used to configure HTTPS. (Official Docs)| unit `UNIT_CONFIG_DIRECTORY`
*Default: "/etc/unit/config.d"*|Path to the Unit configuration directory. Any *.json, *.js, and *.pem files will be loaded into Unit on initialization.| unit `UNIT_CONFIG_FILE`
*Default: "/etc/unit/config.d/config.json"*|Path to the Unit configuration file. One will be generated automatically by default. (Official Docs)| unit

9JlI=s?lQTc~6*0#kt|i$~ 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 U0f$p%|mAmH+?% literal 0 HcmV?d00001 diff --git a/docs/public/images/docs/reverse-proxy.svg b/docs/public/images/docs/reverse-proxy.svg new file mode 100644 index 000000000..0a20f0489 --- /dev/null +++ b/docs/public/images/docs/reverse-proxy.svg @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/public/images/docs/s6-overlay-container.svg b/docs/public/images/docs/s6-overlay-container.svg new file mode 100644 index 000000000..2db7ca086 --- /dev/null +++ b/docs/public/images/docs/s6-overlay-container.svg @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/public/images/docs/supervisor-container.svg b/docs/public/images/docs/supervisor-container.svg new file mode 100644 index 000000000..f23ae36ff --- /dev/null +++ b/docs/public/images/docs/supervisor-container.svg @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 06154ee3d576f0200884f20282ab5802f562e385 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 15:40:10 -0500 Subject: [PATCH 077/170] Fix documentation links for S6 Overlay and health checks, ensuring accurate navigation for users seeking guidance on process supervision and health check implementation in PHP Docker environments. --- .../docs/1.getting-started/2.these-images-vs-others.md | 4 ++-- .../docs/1.getting-started/5.default-configurations.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/content/docs/1.getting-started/2.these-images-vs-others.md b/docs/content/docs/1.getting-started/2.these-images-vs-others.md index 0fd424597..350476607 100644 --- a/docs/content/docs/1.getting-started/2.these-images-vs-others.md +++ b/docs/content/docs/1.getting-started/2.these-images-vs-others.md @@ -48,9 +48,9 @@ We believe images should be ready for production and able to live in the open an ## What is "S6 Overlay?" ::warning -Using **supervisor** to monitor multiple processes in a single container may lead to unintended consequences. This is why we use [S6 Overlay](/docs/guides/using-s6-overlay) to monitor multiple processes in a single container. +Using **supervisor** to monitor multiple processes in a single container may lead to unintended consequences. This is why we use [S6 Overlay](/docs/guide/using-s6-overlay) to monitor multiple processes in a single container. :: [S6 Overlay](https://github.com/just-containers/s6-overlay){target="_blank"} is a process supervisor designed for containerization from the ground up. It's a modern alternative to [Supervisor (aka Supervisord)](https://supervisord.org/){target="_blank"}. We only use this in our `serversideup/php:*-fpm-apache` and `serversideup/php:*-fpm-nginx` images, as they require two processes to run a service. -:u-button{to="/docs/guides/using-s6-overlay" label="Learn more about S6 Overlay" aria-label="Learn more about S6 Overlay" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file +:u-button{to="/docs/guide/using-s6-overlay" label="Learn more about S6 Overlay" aria-label="Learn more about S6 Overlay" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file diff --git a/docs/content/docs/1.getting-started/5.default-configurations.md b/docs/content/docs/1.getting-started/5.default-configurations.md index f75466930..2ff8a0953 100644 --- a/docs/content/docs/1.getting-started/5.default-configurations.md +++ b/docs/content/docs/1.getting-started/5.default-configurations.md @@ -104,7 +104,7 @@ For our `fpm` variation, we use the [`php-fpm-healthcheck`](https://github.com/r The `cli` variation does not have a health check because it doesn't really make sense to have one. Would love to discuss more if you feel different. -:u-button{to="/docs/guides/using-healthchecks-with-laravel" label="Learn more about health checks" aria-label="Learn more about health checks" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} +:u-button{to="/docs/guide/using-healthchecks-with-laravel" label="Learn more about health checks" aria-label="Learn more about health checks" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} ## Default Entrypoint Scripts From fe6f346ec82a338e8f05b7d2f5db7767b6c97b78 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 15:44:25 -0500 Subject: [PATCH 078/170] Add command reference documentation for Docker PHP image, detailing available commands to enhance developer experience, including installation scripts for Alpine and Debian, entrypoint usage, file permission management, and S6 Overlay integration. --- .../docs/8.reference/2.command-reference.md | 85 +++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 docs/content/docs/8.reference/2.command-reference.md diff --git a/docs/content/docs/8.reference/2.command-reference.md b/docs/content/docs/8.reference/2.command-reference.md new file mode 100644 index 000000000..71a0cbed0 --- /dev/null +++ b/docs/content/docs/8.reference/2.command-reference.md @@ -0,0 +1,85 @@ +--- +head.title: 'Command reference - Docker PHP - Server Side Up' +description: 'Learn about all the commands available within the serversideup/php image to improve your developer experience.' +layout: docs +--- + +::lead-p +We included a few commands in the `/usr/local/bin` directory to help you with your development experience. These commands are available in the `serversideup/php` image. +:: + +::note +Since our images are unprivileged by default, you'll need to switch to the `root` user to run these commands. This is a security feature that ensures that your container is as secure as possible. +:: + +## Official PHP Docker Commands +Since our images are based off the official PHP Docker images, any commands from the Official PHP Docker images are available in our images. You can find the full list of commands on the [official PHP Docker images documentation](https://hub.docker.com/_/php). + +## docker-php-serversideup-dep-install-alpine +This command will detect the operating system and install packages if it is an Alpine based system. This is helpful if you're building multiple operating systems from the same Dockerfile. + + +```bash [Example - Installing the git package on Alpine] +# Usage: docker-php-serversideup-dep-install-alpine [alpine-packages] +docker-php-serversideup-dep-install-alpine git +``` + +## docker-php-serversideup-dep-install-debian +This command will detect the operating system and install packages if it is a Debian based system. This is helpful if you're building multiple operating systems from the same Dockerfile. + +```bash [Example - Installing the git package on Debian] +# Usage: docker-php-serversideup-dep-install-debian [debian-packages] +docker-php-serversideup-dep-install-debian git +``` + +## docker-php-serversideup-entrypoint +For our images that **DO NOT use S6 Overlay**, this is our default entrypoint script. + +## docker-php-serversideup-install-php-ext-installer +This is an internal helper script to shorten up the syntax for the installation of the PHP extension installer. + +```bash [Example - Installing the PHP extension installer] +# Usage: docker-php-serversideup-install-php-ext-installer [version] +docker-php-serversideup-install-php-ext-installer 2.2.0 +``` + +## docker-php-serversideup-set-file-permissions +This command is used to set the file permissions of a service in the container. This is useful for development environments where you want to match the user and group ID of the host machine. + +[Learn more about working with file permissions →](/docs/guide/understanding-file-permissions) + +```bash [Example - Setting the file permissions of the NGINX service] +# Usage: docker-php-serversideup-set-file-permissions --owner USER:GROUP +docker-php-serversideup-set-file-permissions --owner 1000:1000 +``` + +The above command will automatically detect the service and update the file permissions accordingly. + +## docker-php-serversideup-set-id +This command is used to set the user and group ID of the `www-data` user in the container. This is useful for development environments where you want to match the user and group ID of the host machine. + +[Learn more about working with file permissions →](/docs/guide/understanding-file-permissions) + +```bash [Example - Setting the user and group ID of the www-data user] +# docker-php-serversideup-set-id [username] [uid]:[gid] +docker-php-serversideup-set-id www-data 1000:1000 +``` + +## docker-php-serversideup-s6-init +This command is used to copy our entrypoint scripts into the S6 Overlay scripts directory. This is useful if you're using S6 Overlay and want to ensure your scripts are executed in the correct order. + +[Learn more about using S6 Overlay dependencies →](/docs/customizing-the-image/adding-your-own-start-up-scripts#advanced-scenarios-s6-overlay-dependencies) + +## docker-php-serversideup-s6-install +This is a command used at build time to install a specific version of S6 Overlay. + +## install-php-extensions +This command is a wrapper around the `docker-php-ext-install` command that comes with the official PHP Docker images. This command allows you to install PHP extensions with a single command. + +[Check out the docker-php-extension-installer project on GitHub →](https://github.com/mlocati/docker-php-extension-installer){target="_blank"} + +Here's an example of how you can use this command: + +```bash [Example - Installing the "intl" extension] +install-php-extensions intl +``` \ No newline at end of file From fe4f6b3436c9865e21bea0440005dc1407df59d5 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 15:44:30 -0500 Subject: [PATCH 079/170] Add environment variable specification documentation for Docker PHP images, detailing available variables and their usage across different configurations, enhancing customization options for users. --- .../1.environment-variable-specification.md | 124 ++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 docs/content/docs/8.reference/1.environment-variable-specification.md diff --git a/docs/content/docs/8.reference/1.environment-variable-specification.md b/docs/content/docs/8.reference/1.environment-variable-specification.md new file mode 100644 index 000000000..352fca842 --- /dev/null +++ b/docs/content/docs/8.reference/1.environment-variable-specification.md @@ -0,0 +1,124 @@ +--- +head.title: 'Environment Variable Specifications - Docker PHP - Server Side Up' +description: 'View the complete reference for environment variables available in the Docker PHP images.' +layout: docs +--- + +::lead-p +Environment variables are a very powerful way to customize your container. Use the document below to see what options are available to customize without requiring you to mount any custom configuration files. +:: + +Setting environment variables all depends on what method you're using to run your container, but for most cases you might be using Docker Compose. + +:u-button{to="https://docs.docker.com/compose/environment-variables/#set-environment-variables-in-containers" target="_blank" label="Learn environment variables work with Docker Compose" aria-label="Learn how environment variables work with Docker Compose" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## Available Environment Variables +**Variable Name**|**Description**|**Used in variation** +:-----:|:-----:|:-----: +`APACHE_DOCUMENT_ROOT`
*Default: "/var/www/html/public"*|Sets the directory from which Apache will serve files. (
Official docs)|fpm-apache +`APACHE_MAX_CONNECTIONS_PER_CHILD`
*Default: "0"*|Sets the limit on the number of connections that an individual child server process will handle.(Official docs)|fpm-apache +`APACHE_MAX_REQUEST_WORKERS`
*Default: "150"*|Sets the limit on the number of simultaneous requests that will be served. (Official docs)|fpm-apache +`APACHE_MAX_SPARE_THREADS`
*Default: "75"*|Maximum number of idle threads. (Official docs)|fpm-apache +`APACHE_MIN_SPARE_THREADS`
*Default: "10"*|Minimum number of idle threads to handle request spikes. (Official docs)|fpm-apache +`APACHE_RUN_GROUP`
*Default: "www-data"*|Set the username of what Apache should run as.|fpm-apache +`APACHE_RUN_USER`
*Default: "www-data"*|Set the username of what Apache should run as.|fpm-apache +`APACHE_START_SERVERS`
*Default: "2"*|Sets the number of child server processes created on startup.(Official docs)|fpm-apache +`APACHE_THREAD_LIMIT`
*Default: "64"*|Set the maximum configured value for ThreadsPerChild for the lifetime of the Apache httpd process. (Official docs)|fpm-apache +`APACHE_THREADS_PER_CHILD`
*Default: "25"*|This directive sets the number of threads created by each child process. (Official docs)|fpm-apache +`APP_BASE_DIR`
*Default: "/var/www/html"*|Change this only if you mount your application to a different directory within the container. ℹ️ Be sure to change `NGINX_WEBROOT`, `APACHE_DOCUMENT_ROOT`, `UNIT_WEBROOT`, etc if it applies to your use case as well.|all +`AUTORUN_DEBUG`
*Default: "false"*|Enable debug mode for the Laravel automations. | all +`AUTORUN_ENABLED`
*Default: "false"*|Enable or disable all automations. It's advised to set this to `false` in certain CI environments (especially during a composer install). If this is set to `false`, all `AUTORUN_*` behaviors will also be disabled.| all +`AUTORUN_LARAVEL_OPTIMIZE`
*Default: "true"*|Automatically run "php artisan optimize" on container, attempting to `--except` in Laravel > `v11.38.0` (Official docs)
ℹ️ Requires `AUTORUN_ENABLED = true` to run. | all +`AUTORUN_LARAVEL_CONFIG_CACHE`
*Default: "true"*|Automatically run "php artisan config:cache" on container start.
ℹ️ Requires `AUTORUN_ENABLED = true` to run.| all +`AUTORUN_LARAVEL_EVENT_CACHE`
*Default: "true"*|Automatically run "php artisan event:cache" on container start.
ℹ️ Requires `AUTORUN_ENABLED = true` to run.| all +`AUTORUN_LARAVEL_MIGRATION`
*Default: "true"*|Automatically run `php artisan migrate --force` on container start.
ℹ️ Requires `AUTORUN_ENABLED = true` to run.| all +`AUTORUN_LARAVEL_MIGRATION_DATABASE`
*Default: null*| Run migrations on a specific database. In the rare case you need to use multiple databases, you can provide a comma-delimited list of connection names (e.g., "mysql,pgsql"). If `null`, it will use the default database connection.
ℹ️ Requires `AUTORUN_ENABLED = true` to run.| all +`AUTORUN_LARAVEL_MIGRATION_FORCE`
*Default: "true"*|Force migrations to run in production without confirmation. Set to `false` to disable the `--force` flag.
ℹ️ Requires `AUTORUN_ENABLED = true` to run.| all +`AUTORUN_LARAVEL_MIGRATION_ISOLATION`
*Default: "false"*|Requires Laravel v9.38.0 or higher and a database that supports table locks. Automatically run `php artisan migrate --force --isolated` on container start.

ℹ️ Requires `AUTORUN_ENABLED = true` to run.
ℹ️ Does not work with SQLite.
ℹ️ Only works with `AUTORUN_LARAVEL_MIGRATION_MODE = default`.| all +`AUTORUN_LARAVEL_MIGRATION_MODE`
*Default: "default"*|Set the migration mode. Valid options: `default` (runs `php artisan migrate`), `fresh` (runs `php artisan migrate:fresh`), or `refresh` (runs `php artisan migrate:refresh`).
ℹ️ Requires `AUTORUN_ENABLED = true` to run.
⚠️ WARNING:`fresh` and `refresh` are destructive and will drop all tables. Only use these in development or testing environments.| all +`AUTORUN_LARAVEL_MIGRATION_SEED`
*Default: "false"*|Automatically seed the database after migrations by adding the `--seed` flag.
ℹ️ Requires `AUTORUN_ENABLED = true` to run.| all +`AUTORUN_LARAVEL_MIGRATION_SKIP_DB_CHECK`
*Default: "false"*|Skip the database connection check before running migrations.
ℹ️ Requires `AUTORUN_ENABLED = true` to run.| all +`AUTORUN_LARAVEL_MIGRATION_TIMEOUT`
*Default: "30"*|The number of seconds to wait for the database to come online before attempting `php artisan migrate`..
ℹ️ Requires `AUTORUN_ENABLED = true` to run.| all +`AUTORUN_LARAVEL_ROUTE_CACHE`
*Default: "true"*|Automatically run "php artisan route:cache" on container start.
ℹ️ Requires `AUTORUN_ENABLED = true` to run.| all +`AUTORUN_LARAVEL_STORAGE_LINK`
*Default: "true"*|Automatically run "php artisan storage:link" on container start.
ℹ️ Requires `AUTORUN_ENABLED = true` to run.| all +`AUTORUN_LARAVEL_VIEW_CACHE`
*Default: "true"*|Automatically run "php artisan view:cache" on container start.
ℹ️ Requires `AUTORUN_ENABLED = true` to run.| all +`CADDY_ADMIN`
*Default: "off"*|Enable Caddy admin interface. (Official docs)|frankenphp +`CADDY_APP_PUBLIC_PATH`
*Default: "/var/www/html/public"*|The path to your public directory for your app. (Official docs)|frankenphp +`CADDY_AUTO_HTTPS`
*Default: "off"*|Enable automatic HTTPS. (Official docs)|frankenphp +`CADDY_GLOBAL_OPTIONS`
*Default: ""*|Set global options for the Caddy server. (Official docs)|frankenphp +`CADDY_HTTP_PORT`
*Default: "8080"*|Set the port for HTTP. (Official docs)|frankenphp +`CADDY_HTTPS_PORT`
*Default: "8443"*|Set the port for HTTPS. (Official docs)|frankenphp +`CADDY_HTTP_SERVER_ADDRESS`
*Default: "http://"*|Set the server address for HTTP. (Official docs)|frankenphp +`CADDY_HTTPS_SERVER_ADDRESS`
*Default: "https://"*|Set the server address for HTTPS. (Official docs)|frankenphp +`CADDY_LOG_FORMAT`
*Default: "console"*|Set the format for the Caddy log. (Official docs)|frankenphp +`CADDY_GLOBAL_LOG_LEVEL`
*Default: "warn"*|Set the global log level for the Caddy server. This can also be changed with `LOG_OUTPUT_LEVEL`, but `CADDY_GLOBAL_LOG_LEVEL` takes precedence. (Official docs)|frankenphp +`CADDY_SERVER_LOG_LEVEL`
*Default: "warn"*|Set the server log level for the Caddy server. This can also be changed with `LOG_OUTPUT_LEVEL`, but `CADDY_SERVER_LOG_LEVEL` takes precedence. (Official docs)|frankenphp +`CADDY_LOG_OUTPUT`
*Default: "stdout"*|Set the output for the Caddy log. (Official docs)|frankenphp +`CADDY_PHP_SERVER_OPTIONS`
*Default: ""*|Set PHP server options for the Caddy server. (Official docs)|frankenphp +`CADDY_SERVER_EXTRA_DIRECTIVES`
*Default: ""*|Set extra directives for the Caddy server. (Official docs)|frankenphp +`COMPOSER_ALLOW_SUPERUSER`
*Default: "1"*|Disable warning about running as super-user|all +`COMPOSER_HOME`
*Default: "/composer"*|The COMPOSER_HOME variable allows you to change the Composer home directory. This is a hidden, global (per-user on the machine) directory that is shared between all projects.|all +`COMPOSER_MAX_PARALLEL_HTTP`
*Default: "24"*|Set to an integer to configure how many files can be downloaded in parallel. Composer ships with 12 by default and must be between 1 and 50. If your proxy has issues with concurrency maybe you want to lower this. Increasing it should generally not result in performance gains.|all +`DISABLE_DEFAULT_CONFIG`
*Default: "false"*|Get full customization of the image and disable all default configurations and automations.| all +`FRANKENPHP_CONFIG`
*Default: ""*|Set the configuration for FrankenPHP. (Official docs)|frankenphp +`HEALTHCHECK_PATH`
*Default: "/healthcheck"*|Set the path for the health check endpoint. (Official docs)|all (except `cli` and `frankenphp`) +`LOG_OUTPUT_LEVEL`
*Default: "warn"*|Set your container output different verbosity levels: debug, info, off |all +`NGINX_ACCESS_LOG`
*Default: "/dev/stdout"*|Set the default output stream for access log.|fpm-nginx +`NGINX_ERROR_LOG`
*Default: "/dev/stderr"*|Set the default output stream for error log.|fpm-nginx +`NGINX_FASTCGI_BUFFERS`
*Default: "8 8k"*|Sets the number and size of the buffers used for reading a response from a FastCGI server. (Official Docs)|fpm-nginx +`NGINX_FASTCGI_BUFFER_SIZE`
*Default: "8k"*|Sets the size of the buffer used for reading a response from a FastCGI server. (Official Docs)|fpm-nginx +`NGINX_LISTEN_IP_PROTOCOL`
*Default: "all"*|Set the IP protocol for NGINX to listen on. Valid values are "all", "ipv4", and "ipv6". (Official Docs)|fpm-nginx +`NGINX_SERVER_TOKENS`
*Default: "off"*|Display NGINX version in responses. (Official Docs)|fpm-nginx +`NGINX_WEBROOT`
*Default: "`/var/www/html/public"*|Sets the root directory for requests. (Official Docs)|fpm-nginx +`NGINX_CLIENT_MAX_BODY_SIZE`
*Default: "100M"*|Sets the max body size for requests. (Official Docs*Default: "UTC"*|Control your timezone. (Official Docs)|all +`PHP_DISPLAY_ERRORS`
*Default: Off*|Show PHP errors on screen. (Official docs)|all +`PHP_DISPLAY_STARTUP_ERRORS`
*Default: Off*|Even when display_errors is on, errors that occur during PHP's startup sequence are not displayed. (Official docs)| all +`PHP_ERROR_LOG`
*Default: "/dev/stderr"*|Name of the file where script errors should be logged. . (Official docs)|all +`PHP_ERROR_REPORTING`
*Default: "22527"*|Set PHP error reporting level. Must be a number. Use this tool for help. (Official docs)|all +`PHP_FPM_PM_CONTROL`
*Defaults:
fpm: dynamic
fpm-apache: ondemand
fpm-nginx: ondemand*|Choose how the process manager will control the number of child processes. (Official docs)|fpm* +`PHP_FPM_PM_MAX_CHILDREN`
*Default: "20"*|The number of child processes to be created when pm is set to static and the maximum number of child processes to be created when pm is set to dynamic. (Official docs)|fpm* +`PHP_FPM_PM_MAX_REQUESTS`
*Default: "0"*|The number of requests each child process should execute before respawning. This can be useful to work around memory leaks in 3rd party libraries. (Official docs)|fpm* +`PHP_FPM_PM_MAX_SPARE_SERVERS`
*Default: "3"*|The desired maximum number of idle server processes. Used only when pm is set to dynamic. (Official docs)|fpm* +`PHP_FPM_PM_MIN_SPARE_SERVERS`
*Default: "1"*|The desired minimum number of idle server processes. Used only when pm is set to dynamic. (Official docs)|fpm* +`PHP_FPM_PM_START_SERVERS`
*Default: "2"*|The number of child processes created on startup. Used only when pm is set to dynamic. (Official docs)|fpm* +`PHP_FPM_PM_STATUS_PATH`
*Default: ""*|The path to the PHP-FPM status page. (Official docs)|fpm* +`PHP_FPM_POOL_NAME`
*Default: "www"*|Set the name of your PHP-FPM pool (helpful when running multiple sites on a single server).|fpm* +`PHP_FPM_PROCESS_CONTROL_TIMEOUT`
*Default: "10s"*|Set the timeout for the process control commands. (Official docs)|fpm* +`PHP_MAX_EXECUTION_TIME`
*Default: "99"*|Set the maximum time in seconds a script is allowed to run before it is terminated by the parser. (Official docs)|all +`PHP_MAX_INPUT_TIME`
*Default: "-1"*|This sets the maximum time in seconds a script is allowed to parse input data, like POST and GET. Timing begins at the moment PHP is invoked at the server and ends when execution begins. The default setting is -1, which means that max_execution_time is used instead. Set to 0 to allow unlimited time. This directive is hardcoded to -1 for the CLI SAPI by PHP. (Official docs)|all +`PHP_MAX_INPUT_VARS`
*Default: "1000"*|Set the limits for number of input variables (e.g., POST, GET, or COOKIE variables) that PHP will process in a single request. (Official docs)|all +`PHP_MEMORY_LIMIT`
*Default: "256M"*|Set the maximum amount of memory in bytes that a script is allowed to allocate. (Official docs)|all +`PHP_OPCACHE_ENABLE`
*Default: "0" (to keep developers sane)*|Enable or disable OPcache. ⚠️ This will set **both values** for `opcache.enable` and `opcache.enable_cli`. (Official docs)|all +`PHP_OPCACHE_ENABLE_FILE_OVERRIDE`
*Default: "0"*|Enable or disable file existence override (file_exists, etc.). (Official docs)|all +`PHP_OPCACHE_FORCE_RESTART_TIMEOUT`
*Default: "180"*|The number of seconds to wait for a scheduled restart to begin if the cache isn't active, in seconds. If the timeout is hit, then OPcache assumes that something is wrong and will kill the processes holding locks on the cache to permit a restart. (Official docs)|all +`PHP_OPCACHE_INTERNED_STRINGS_BUFFER`
*Default: "8"*|The amount of memory used to store interned strings, in megabytes. (Official docs)|all +`PHP_OPCACHE_JIT`
*Default: "off"*|Enable or disable the JIT compiler. (Official docs)|all +`PHP_OPCACHE_JIT_BUFFER_SIZE`
*Default: "0"*|The amount of shared memory to reserve for compiled JIT code. A zero value disables the JIT. (Official docs)|all +`PHP_OPCACHE_MAX_ACCELERATED_FILES`
*Default: "10000"*|The maximum number of keys (scripts) in the OPcache hash table. (Official docs)|all +`PHP_OPCACHE_MEMORY_CONSUMPTION`
*Default: "128"*|The amount of memory used by the OPcache engine, in megabytes. (Official docs)|all +`PHP_OPCACHE_REVALIDATE_FREQ`
*Default: "2"*|How often the OPcache checks for updates to cached files (in seconds). (Official docs)|all +`PHP_OPCACHE_SAVE_COMMENTS`
*Default: "1"*|Remove comments from OPcache to minify a bit further. Note: any code that depends on PHPDoc annotations can break from this. (Official docs)|all +`PHP_OPCACHE_VALIDATE_TIMESTAMPS`
*Default: "1"*|Whether OPcache checks for changes to files, or requires reload of PHP to revalidate OPcache. (Official docs)|all +`PHP_OPEN_BASEDIR`
*Default: "None"* |Limit the files that can be accessed by PHP to the specified directory-tree, including the file itself. `open_basedir` is just an extra safety net, that is in no way comprehensive, and can therefore not be relied upon when security is needed. (Official docs)| all +`PHP_POST_MAX_SIZE`
*Default: "100M"*|Sets max size of post data allowed. (Official docs)|all +`PHP_REALPATH_CACHE_TTL`
*Default: "120"*|The duration of time, in seconds for which to cache realpath information for a given file or directory. (Official docs)|all +`PHP_SESSION_COOKIE_SECURE`
*Default: 1 (true)*|Specifies whether cookies should only be sent over secure connections. (Official docs)|all +`PHP_UPLOAD_MAX_FILE_SIZE`
*Default: "100M"*|The maximum size of an uploaded file. (Official docs)|all +`PHP_ZEND_DETECT_UNICODE`
*Default: ""*|Check for BOM (Byte Order Mark) and see if the file contains valid multibyte characters. This detection is performed before processing of __halt_compiler(). Available only in Zend Multibyte mode. (Official docs)|all +`PHP_ZEND_MULTIBYTE`
*Default: "Off"*|Enable or disable Zend Multibyte. (Official docs)|all +`S6_BEHAVIOUR_IF_STAGE2_FAILS`
*Default: "2" (stop the container)*|Determines what the container should do if one of the service scripts fails (Official docs)|fpm-nginx,
fpm-apache +`S6_CMD_WAIT_FOR_SERVICES_MAXTIME`
*Default: "0"*|The maximum time (in milliseconds) the services could take to bring up before proceeding to CMD executing (Official docs)|fpm-nginx,
fpm-apache +`S6_VERBOSITY`
*Default: "1"*|Set the verbosity of "S6 Overlay" (the init system these images are based on). The default is "1" (print warnings and errors). The scale goes from 1 to 5, but the output will quickly become very noisy. If you're having issues, start here. You can also customize many other variables. (Official docs)|fpm-nginx,
fpm-apache +`SHOW_WELCOME_MESSAGE`
*Default: "true"*|Show a helpful welcome message showing container information when the container starts.|all +`SSL_CERTIFICATE_FILE`
*Default: "/etc/ssl/private/self-signed-web.crt"*|Path to public certificate file for HTTPS. You must provide this file otherwise a self-signed key pair will be generated for you.|fpm-nginx,
fpm-apache +`SSL_MODE`
*Default: "off"*|Configure how you would like to handle SSL. This can be "off" (HTTP only), "mixed" (HTTP + HTTPS), or "full" (HTTPS only). If you use HTTP, you may need to also change `PHP_SESSION_COOKIE_SECURE`.|fpm-nginx,
fpm-apache,
unit +`SSL_PRIVATE_KEY_FILE`
*Default: "/etc/ssl/private/self-signed-web.key"*|Path to private key file for HTTPS. You must provide this file otherwise a self-signed key pair will be generated for you.|fpm-nginx,
fpm-apache +`UNIT_CERTIFICATE_NAME`
*Default: "self-signed-web-bundle"*| Name of your certificate bundle. This is used to configure HTTPS. (Official Docs)| unit +`UNIT_CONFIG_DIRECTORY`
*Default: "/etc/unit/config.d"*|Path to the Unit configuration directory. Any *.json, *.js, and *.pem files will be loaded into Unit on initialization.| unit +`UNIT_CONFIG_FILE`
*Default: "/etc/unit/config.d/config.json"*|Path to the Unit configuration file. One will be generated automatically by default. (Official Docs)| unit +`UNIT_PROCESSES_IDLE_TIMEOUT`
*Default: "30"*|The maximum time in seconds that an idle process will be kept alive. (Official Docs)| unit +`UNIT_PROCESSES_MAX`
*Default: "20"*|The maximum number of application processes that can be started. (Official Docs)| unit +`UNIT_PROCESSES_SPARE`
*Default: "2"*|Minimum number of idle processes that Unit tries to maintain for an app. (Official Docs)| unit +`UNIT_WEBROOT`
*Default: "/var/www/html/public"*|Base directory of the app’s file structure. All URI paths are relative to it. (Official Docs)| unit +`UNIT_MAX_BODY_SIZE`
*Default: "104857600"* (100MB) | Sets maximum number of bytes in the body of a client’s request. (Official docs) | unit From a83a85d9dda4b2687c770d16c8aa094c93277983 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 15:44:52 -0500 Subject: [PATCH 080/170] Add navigation configuration for Advanced Guides in documentation, enhancing structure and accessibility for users seeking advanced topics in PHP Docker environments. --- docs/content/docs/{5.guides => 5.guide}/.navigation.yml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/content/docs/{5.guides => 5.guide}/.navigation.yml (100%) diff --git a/docs/content/docs/5.guides/.navigation.yml b/docs/content/docs/5.guide/.navigation.yml similarity index 100% rename from docs/content/docs/5.guides/.navigation.yml rename to docs/content/docs/5.guide/.navigation.yml From a1fa608a77bf94cd6c5398364b903ee165870728 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 15:47:05 -0500 Subject: [PATCH 081/170] Add Laravel automation, task scheduler, queue, horizon, and reverb documentation for Docker PHP images, providing comprehensive guides on configuring and managing these features, enhancing developer experience and deployment practices. --- .../1.laravel/1.automations.md | 161 ++++++++++++++++++ .../1.laravel/2.task-scheduler.md | 113 ++++++++++++ .../3.framework-guides/1.laravel/3.queue.md | 46 +++++ .../3.framework-guides/1.laravel/4.horizon.md | 51 ++++++ .../3.framework-guides/1.laravel/4.reverb.md | 71 ++++++++ 5 files changed, 442 insertions(+) create mode 100644 docs/content/docs/3.framework-guides/1.laravel/1.automations.md create mode 100644 docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md create mode 100644 docs/content/docs/3.framework-guides/1.laravel/3.queue.md create mode 100644 docs/content/docs/3.framework-guides/1.laravel/4.horizon.md create mode 100644 docs/content/docs/3.framework-guides/1.laravel/4.reverb.md diff --git a/docs/content/docs/3.framework-guides/1.laravel/1.automations.md b/docs/content/docs/3.framework-guides/1.laravel/1.automations.md new file mode 100644 index 000000000..0dc20ed8a --- /dev/null +++ b/docs/content/docs/3.framework-guides/1.laravel/1.automations.md @@ -0,0 +1,161 @@ +--- +head.title: 'Laravel Automations Script - Docker PHP - Server Side Up' +description: 'Automate your deployments and minimize your efforts with Laravel.' +layout: docs +title: Automations +--- + +::lead-p +`serversideup/php` has a "Laravel Automations" script that helps automate common tasks to maintain your Laravel application and improve it's performance. By default, the script is **DISABLED**. We only recommend enabling this script in production environments. +:: + +## What the script does + +::note +In order for this script to run,`AUTORUN_ENABLED` must be set to `true`. Once the main part of the script is enabled, you can control the individual tasks by setting the corresponding environment variables to `true` or `false`. See our [variable reference document](/docs/reference/environment-variable-specification) for more details. +:: + +| Environment Variable | Default | Description | +| -------------------- | -------------- | ----------- | +| `AUTORUN_ENABLED` | `false` | Enables the Laravel Automations script.
**ℹ️ Note:** This must be set to `true` for the script to run. | +| `AUTORUN_DEBUG` | `false` | Enables a special debug mode, specifically for the Laravel Automations script. | +| `AUTORUN_LARAVEL_CONFIG_CACHE` | `true` | `php artisan config:cache`: Caches the configuration files into a single file. | +| `AUTORUN_LARAVEL_EVENT_CACHE` | `true` | `php artisan event:cache`: Creates a manifest of all your application's events and listeners. | +| `AUTORUN_LARAVEL_MIGRATION` | `true` | `php artisan migrate`: Runs migrations. | +| `AUTORUN_LARAVEL_MIGRATION_DATABASE` | `null` | Run migrations on a specific database. In the rare case you need to use multiple databases, you can provide a comma-delimited list of connection names (e.g., "mysql,pgsql"). If `null`, it will use the default database connection. | +| `AUTORUN_LARAVEL_MIGRATION_FORCE` | `true` | Force migrations to run in production without confirmation. Set to `false` to disable the `--force` flag. | +| `AUTORUN_LARAVEL_MIGRATION_ISOLATION` | `false` | Run your migrations with the [`--isolated`](https://laravel.com/docs/12.x/migrations#running-migrations) flag.
**ℹ️ Note:** Requires Laravel v9.38.0+. Only works with `default` migration mode. | +| `AUTORUN_LARAVEL_MIGRATION_MODE` | `default` | Migration mode: `default`, `fresh`, or `refresh`.
**⚠️ Warning:** `fresh` and `refresh` drop all tables. | +| `AUTORUN_LARAVEL_MIGRATION_SEED` | `false` | Automatically seed the database after migrations using the `--seed` flag. | +| `AUTORUN_LARAVEL_MIGRATION_SKIP_DB_CHECK` | `false` | Skip the database connection check before running migrations. | +| `AUTORUN_LARAVEL_MIGRATION_TIMEOUT` | `30` | Number of seconds to wait for database connection before timing out during migrations. | +| `AUTORUN_LARAVEL_OPTIMIZE` | `true` | `php artisan optimize`: Optimizes the application. | +| `AUTORUN_LARAVEL_ROUTE_CACHE` | `true` | `php artisan route:cache`: Caches the routes. | +| `AUTORUN_LARAVEL_STORAGE_LINK` | `true` | `php artisan storage:link`: Creates a symbolic link from `public/storage` to `storage/app/public`. | +| `AUTORUN_LARAVEL_VIEW_CACHE` | `true` | `php artisan view:cache`: Caches the views. | + +## Database Connection Checks +Before running migrations, the automation script performs connection checks to ensure your database is ready. Understanding this process helps you configure timeouts and troubleshoot connection issues. + +::note +You can skip database connection checks entirely by setting `AUTORUN_LARAVEL_MIGRATION_SKIP_DB_CHECK=true`. This is useful when you're certain your database is ready or when using alternative connection verification methods. +:: + +::steps{level="3"} + +### Clear configuration cache +The script runs `php artisan config:clear` to ensure fresh database configuration is loaded before attempting any connections. + +### Attempt database connection +The script tests the database connection using a retry mechanism: +- Attempts to connect every second +- Continues for up to `AUTORUN_LARAVEL_MIGRATION_TIMEOUT` seconds (default: 30) +- Shows connection progress in real-time +- Logs detailed attempts every 5 seconds when `AUTORUN_DEBUG=true` + +### Verify each database connection +If you've specified multiple databases via `AUTORUN_LARAVEL_MIGRATION_DATABASE`, the script waits for each database connection individually before proceeding with migrations for that database. + +### Run migrations +Once the database connection is confirmed, the script executes the appropriate migration command based on your configuration. + +:: + +::tip +Set `AUTORUN_DEBUG=true` to see detailed connection attempt logs, which is helpful for troubleshooting connection issues. +:: + + +## php artisan storage:link +Creates a symbolic link from `public/storage` to `storage/app/public`. + +:u-button{to="https://laravel.com/docs/12.x/filesystem#the-public-disk" target="_blank" label="Read more about storage links" aria-label="Read more about storage links" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## php artisan migrate +Before running migrations, we ensure the database is online and ready to accept connections. By default, we will wait 30 seconds before timing out. + +### Migration Modes +You can control how migrations run using `AUTORUN_LARAVEL_MIGRATION_MODE`: + +| Mode | Description | +|------|-------------| +| `default` | Runs `php artisan migrate` - standard forward migrations | +| `fresh` | Runs `php artisan migrate:fresh` - drops all tables and re-runs migrations | +| `refresh` | Runs `php artisan migrate:refresh` - rolls back and re-runs migrations | + +::caution +Using `fresh` or `refresh` modes will **drop all tables** in your database. Only use these in development or testing environments. +:: + +### Force Flag +By default, migrations run with the `--force` flag to bypass production warnings. You can disable this by setting `AUTORUN_LARAVEL_MIGRATION_FORCE` to `false`. + +### Seeding +You can automatically seed your database after migrations by setting `AUTORUN_LARAVEL_MIGRATION_SEED` to `true`. This adds the `--seed` flag to your migration command. + +### Specific Database Migrations +If you need to specify the exact database connection to use for migrations, you can set `AUTORUN_LARAVEL_MIGRATION_DATABASE` to the name of the database connection you want to use. + +| Use case | Description | Value | +|----------|-------|-------------| +| Single database | Run migrations on the `mysql` database connection. | `AUTORUN_LARAVEL_MIGRATION_DATABASE=mysql` | +| Multiple databases | In the rare case you need to use multiple databases, you can provide a comma-delimited list of connection names (e.g., "mysql,pgsql"). | `AUTORUN_LARAVEL_MIGRATION_DATABASE=mysql,pgsql` | + +### Isolated Migrations +You can enable the [`--isolated`](https://laravel.com/docs/12.x/migrations#running-migrations) flag by setting `AUTORUN_LARAVEL_MIGRATION_ISOLATION` to `true`, which will ensure no other containers are running a migration. + +**Special Notes for Isolated Migrations:** +- Requires Laravel v9.38.0+ +- Only works with `default` migration mode (not compatible with `fresh` or `refresh`) +- Your application must be using the memcached, redis, dynamodb, database, file, or array cache driver as your application's default cache driver. In addition, all servers must be communicating with the same central cache server. + +:u-button{to="https://laravel.com/docs/12.x/migrations#running-migrations" target="_blank" label="Read more about migrations" aria-label="Read more about migrations" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## php artisan optimize +Laravel comes with an artisan command called `optimize`, which will optimize the application by caching the configuration, routes, views, and events all in one command. + +You can disable any cache features by setting the corresponding environment variable to `false` (for example, `AUTORUN_LARAVEL_CONFIG_CACHE` would disable configuration caching). + +If your application is running Laravel v11.38.0 or higher, we will utilize the `optimize --except` parameter to exclude any cache features you have disabled. Otherwise, we will run the individual optimizations separately. + +It's possible to disable the `optimize` command by setting `AUTORUN_LARAVEL_OPTIMIZE` to `false`, but the major advantage of using the `optimize` command is other dependencies may hook into this action and run other commands. + +:u-button{to="https://laravel.com/docs/12.x/deployment#optimization" target="_blank" label="Read more about optimizing Laravel" aria-label="Read more about optimizing Laravel" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## php artisan config:cache +This command caches all configuration files into a single file, which can then be quickly loaded by Laravel. Once the configuration is cache, the `.env` file will no longer be loaded. + +:u-button{to="https://laravel.com/docs/12.x/configuration#configuration-caching" target="_blank" label="Read more about configuration caching" aria-label="Read more about configuration caching" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## php artisan route:cache +This command caches the routes, dramatically decrease the time it takes to register all of your application's routes. After running this command, your cached routes file will be loaded on every request. + +:u-button{to="https://laravel.com/docs/12.x/routing#route-caching" target="_blank" label="Read more about route caching" aria-label="Read more about route caching" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## php artisan view:cache +This command caches all of the views in your application, which can greatly decrease the time it takes to render your views. + +:u-button{to="https://laravel.com/docs/12.x/views#optimizing-views" target="_blank" label="Read more about view caching" aria-label="Read more about view caching" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## php artisan event:cache +This command creates a manifest of all your application's events and listeners, which can greatly speed up the process of registering them with Laravel. + +:u-button{to="https://laravel.com/docs/12.x/events#event-discovery-in-production" target="_blank" label="Read more about event caching" aria-label="Read more about event caching" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + +## Debugging the AUTORUN script +It's very important to understand the nature of how containerized environments work when debugging the AUTORUN script. In some cases, some users may become frustrated when they push an update but their changes are never deployed. + +In most cases, this is due to a bug in their application code that causes a migration or some other process to fail. + +::note +If a failure occurs in the Laravel Automations script, it will exit with a non-zero exit code -- preventing the container from starting. +:: + +If you are experiencing issues, you can enable the `AUTORUN_DEBUG` environment variable to get more detailed ouput of what could be going wrong. + +If you need even more information, you can set `LOG_OUTPUT_LEVEL` to `debug` to get **A TON** of output of what's exactly happening. + +### Preventing issues with the AUTORUN script +- Ensure you are running the latest version of `serversideup/php` +- Ensure you have dependencies installed (ie. `composer install`) before calling this script +- Use automated testing to catch issues before deploying \ No newline at end of file diff --git a/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md b/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md new file mode 100644 index 000000000..28b4cdedd --- /dev/null +++ b/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md @@ -0,0 +1,113 @@ +--- +head.title: 'Laravel Task Scheduler with Docker - Docker PHP - Server Side Up' +description: 'Learn how to configure a Laravel Task Scheduler with Docker.' +layout: docs +title: Task Scheduler +--- + +## Laravel Task Scheduler with Docker +Running a Laravel task scheduler with Docker can be a little different from traditional methods. + +## Important concepts +1. If you're using `fpm-apache` or `fpm-nginx`, might need to set the stop signal to `SIGTERM` for a graceful shutdown (see this [PR](https://github.com/serversideup/docker-php/pull/437){target="_blank"} for more details why) +1. Be sure to set the health check +1. We will **not** use `cron` to run the scheduler +1. By default `schedule:work` checks every minute, so we will use that to run the system process +1. The actual time trigger itself is set within Laravel + +## More detail +We need to run the [schedule:work](https://laravel.com/docs/12.x/scheduling#running-the-scheduler-locally){target="_blank"} command from Laravel. Although the docs say "Running the scheduler locally", this is what we want in production. It will run the scheduler in the foreground and execute it every minute. You can configure your Laravel app for the exact time that a command should run through a [scheduled task](https://laravel.com/docs/12.x/scheduling#scheduling-artisan-commands){target="_blank"}. + + +## Examples +Here is a simplified example of how you can achieve this with Docker Compose: + +::note +Notice we're calling the artisan command explicitly with the full path (`/var/www/html/artisan`). This is because we need to run the command from the context of the container. +:: + +#### Example & Simplified Docker Compose File +```yaml [docker-compose.yml] +services: + php: + image: my/laravel-app + + task: + image: my/laravel-app + command: ["php", "/var/www/html/artisan", "schedule:work"] + stop_signal: SIGTERM # Set this for graceful shutdown if you're using fpm-apache or fpm-nginx + healthcheck: + # This is our native healthcheck script for the scheduler + test: ["CMD", "healthcheck-schedule"] + start_period: 10s +``` + + +#### Example in Laravel +::note +This example is for Laravel version <= 10. +:: + +This is an example how we would set the actual execution time within Laravel itself: +```php [app/Console/Kernel.php] +command('process:invoices')->daily()->at('02:00')->timezone('America/Chicago'); + $schedule->command('process:latefees')->daily()->at('04:00')->timezone('America/Chicago'); + } + + /** + * Register the commands for the application. + * + * @return void + */ + protected function commands() + { + $this->load(__DIR__.'/Commands'); + + require base_path('routes/console.php'); + } +} +``` + +```php [routes/console.php] +delete(); +})->daily()->at('04:00')->timezone('America/Chicago'); +``` + + + +## Get Up and Running The Easy Way +We do all the heavy lifting for you with Spin Pro. It's as easy as selecting it in a menu and we'll configure everything else for you. Learn how easy it is to get up and running with the Task Scheduler on Spin Pro. + +:u-button{to="https://getspin.pro/docs/services/laravel-scheduler" target="_blank" label="Learn more about Laravel Task Scheduler + Spin Pro" aria-label="Learn more about Laravel Task Scheduler + Spin Pro" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} diff --git a/docs/content/docs/3.framework-guides/1.laravel/3.queue.md b/docs/content/docs/3.framework-guides/1.laravel/3.queue.md new file mode 100644 index 000000000..0fe8837ec --- /dev/null +++ b/docs/content/docs/3.framework-guides/1.laravel/3.queue.md @@ -0,0 +1,46 @@ +--- +head.title: 'Laravel Queue with Docker - Docker PHP - Server Side Up' +description: 'Learn how to configure a Laravel Queue with Docker.' +layout: docs +title: Queue +--- + +## Laravel Queue with Docker +All you need to do is pass the Laravel Queue command to the container and Laravel will start the queue worker. + +```sh +php artisan queue:work --tries=3 +``` + +## Important concepts +1. It's usually best to run the queue as a separate container (but using the same image) +1. If you're using `fpm-apache` or `fpm-nginx`, might need to set the stop signal to `SIGTERM` for a graceful shutdown (see this [PR](https://github.com/serversideup/docker-php/pull/437){target="_blank"} for more details why) +1. Be sure to set the health check +1. Notice we're using the same `my/laravel-app` image for both the PHP and Queue services. This is a common practice to keep the image consistent. +1. If you need to run the queue in the same container, you might want to look into [writing your own S6 Overlay script](/docs/guide/using-s6-overlay#customizing-the-initialization-process){target="_blank"} to manage and monitor multiple processes in one container. + +## Run it with Docker +::note +Notice we're calling the artisan command explicitly with the full path (`/var/www/html/artisan`). This is because we need to run the command from the context of the container. +:: + +#### Example & Simplified Docker Compose File +```yaml [docker-compose.yml] +services: + php: + image: my/laravel-app + + queue: + image: my/laravel-app + command: ["php", "/var/www/html/artisan", "queue:work", "--tries=3"] + stop_signal: SIGTERM # Graceful shutdown for fpm-apache or fpm-nginx + healthcheck: + # This is our native healthcheck script for the queue + test: ["CMD", "healthcheck-queue"] + start_period: 10s +``` + +## Get Up and Running The Easy Way +We do all the heavy lifting for you with Spin Pro. It's as easy as selecting it in a menu and we'll configure everything else for you. Learn how easy it is to get up and running with Queues on Spin Pro. + +:u-button{to="https://getspin.pro/docs/services/laravel-queues" target="_blank" label="Learn more about Laravel Queues + Spin Pro" aria-label="Learn more about Laravel Queues + Spin Pro" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file diff --git a/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md b/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md new file mode 100644 index 000000000..fbb63d1df --- /dev/null +++ b/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md @@ -0,0 +1,51 @@ +--- +head.title: 'Laravel Horizon with Docker - Docker PHP - Server Side Up' +description: 'Learn how to configure Laravel Horizon with Docker.' +layout: docs +title: Horizon +--- + +## Laravel Horizon with Docker +We simply pass the command to the Docker container and Laravel will start the Horizon process. + +```sh +php artisan horizon +``` + +## Important concepts +1. In most cases, you probably want to run this as a separate container from your web container +1. If you're using `fpm-apache` or `fpm-nginx`, might need to set the stop signal to `SIGTERM` for a graceful shutdown (see this [PR](https://github.com/serversideup/docker-php/pull/437){target="_blank"} for more details why) +1. Be sure to set the health check +1. Ensure that you have your `.env` configured correctly to authenticate with Redis +1. Ensure Redis is running before you attempt to connect Horizon to Redis +1. If you need to run horizon in the same container, you might want to look into [writing your own S6 Overlay script](/docs/guide/using-s6-overlay#customizing-the-initialization-process){target="_blank"} to manage and monitor multiple processes in one container. + +## Run it with Docker +::note +Notice we're calling the artisan command explicitly with the full path (`/var/www/html/artisan`). This is because we need to run the command from the context of the container. +:: + +#### Example & Simplified Docker Compose File +```yaml [docker-compose.yml] +services: + php: + image: my/laravel-app + + redis: + image: redis:6 + command: "redis-server --appendonly yes --requirepass redispassword" + + horizon: + image: my/laravel-app + command: ["php", "/var/www/html/artisan", "horizon"] + stop_signal: SIGTERM # Set this for graceful shutdown if you're using fpm-apache or fpm-nginx + healthcheck: + # This is our native healthcheck script for Horizon + test: ["CMD", "healthcheck-horizon"] + start_period: 10s +``` + +## Get Up and Running The Easy Way +We do all the heavy lifting for you with Spin Pro. It's as easy as selecting it in a menu and we'll configure everything else for you. Learn how easy it is to get up and running with Horizon on Spin Pro. + +:u-button{to="https://getspin.pro/docs/services/laravel-horizon" target="_blank" label="Learn more about Laravel Horizon + Spin Pro" aria-label="Learn more about Laravel Horizon + Spin Pro" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file diff --git a/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md b/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md new file mode 100644 index 000000000..7163ee115 --- /dev/null +++ b/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md @@ -0,0 +1,71 @@ +--- +head.title: 'Laravel Reverb with Docker - Docker PHP - Server Side Up' +description: 'Learn how to configure Laravel Reverb with Docker.' +layout: docs +title: Reverb +--- + +## Laravel Reverb with Docker +We simply pass the command to the Docker container and Laravel will start the Reverb process. + +```sh +php artisan reverb:start +``` + +## Important concepts +1. You will need to follow the [Laravel Reverb setup instructions](https://laravel.com/docs/12.x/reverb) to install the Laravel Reverb package into your Laravel application. +1. In most cases, you probably want to run this as a separate container from your web container +1. If you're using `fpm-apache` or `fpm-nginx`, might need to set the stop signal to `SIGTERM` for a graceful shutdown (see this [PR](https://github.com/serversideup/docker-php/pull/437){target="_blank"} for more details why) +1. Be sure to set the health check +1. You may need a proxy like Traefik to correctly route traffic to the right container +1. If you need to run Reverb in the same container, you might want to look into [writing your own S6 Overlay script](/docs/guide/using-s6-overlay#customizing-the-initialization-process){target="_blank"} to manage and monitor multiple processes in one container. + +## Run it with Docker +::note +Notice Laravel Reverb is running on port `8000`, where as Laravel is running on port `8080`. You may need to set additional environment variables and configure a reverse proxy like Traefik to correctly route traffic to the right container. +:: + +#### Example & Simplified Docker Compose File +```yaml [docker-compose.yml] +services: + php: + image: my/laravel-app + labels: + - "traefik.enable=true" + - "traefik.http.routers.laravel.tls=true" + - "traefik.http.routers.laravel.entrypoints=websecure" + - "traefik.http.routers.laravel.rule=Host(`https://app.example.com`)" + - "traefik.http.services.laravel.loadbalancer.server.port=8080" + - "traefik.http.services.laravel.loadbalancer.server.scheme=http" + + reverb: + image: my/laravel-app + command: ["php", "/var/www/html/artisan", "--port=8000", "reverb:start"] + stop_signal: SIGTERM # Graceful shutdown for fpm-apache or fpm-nginx + healthcheck: + # This is our native healthcheck script for Reverb + test: ["CMD", "healthcheck-reverb"] + start_period: 10s + labels: + - "traefik.enable=true" + - "traefik.http.routers.reverb.tls=true" + - "traefik.http.routers.reverb.entrypoints=websecure" + - "traefik.http.routers.reverb.rule=Host(`https://reverb.example.com`)" + - "traefik.http.services.reverb.loadbalancer.server.port=8000" + - "traefik.http.services.reverb.loadbalancer.server.scheme=http" +``` + +## Laravel ENV updates +Reverb may require a few ENV variables to be set in your Laravel application. +| **Laravel ENV Variable** | **Description** | **Value if matching example above** | +| ------------------------- | --------- | --------- | +| `REVERB_HOST` | The hostname the **CLIENT** will connect to. | `reverb.example.com` | +| `REVERB_PORT` | The port the **CLIENT** will connect to. | `443` | +| `REVERB_SCHEME` | The scheme the **CLIENT** will connect to. | `https` | + +Be sure to not get `REVERB_HOST` or `REVERB_PORT` confused with `REVERB_SERVER_HOST` or `REVERB_SERVER_PORT`. The `_SERVER_` variables are for the **SERVER** (the Reverb daemon itself) and the others are for the **CLIENT** (people connecting to your application). + +## Get Up and Running The Easy Way +We do all the heavy lifting for you with Spin Pro. It's as easy as selecting it in a menu and we'll configure everything else for you. Learn how easy it is to get up and running with Reverb on Spin Pro. + +:u-button{to="https://getspin.pro/docs/services/laravel-reverb" target="_blank" label="Learn more about Laravel Reverb + Spin Pro" aria-label="Learn more about Laravel Reverb + Spin Pro" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file From df7ac7aac7c495c3ab143106646979f72d7d136e Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 15:47:21 -0500 Subject: [PATCH 082/170] Add WordPress optimization documentation for Docker PHP images, detailing security practices, deployment strategies, and community considerations, enhancing guidance for users modernizing WordPress with Docker. --- .../4.using-wordpress-with-docker.md | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 docs/content/docs/3.framework-guides/2.wordpress/4.using-wordpress-with-docker.md diff --git a/docs/content/docs/3.framework-guides/2.wordpress/4.using-wordpress-with-docker.md b/docs/content/docs/3.framework-guides/2.wordpress/4.using-wordpress-with-docker.md new file mode 100644 index 000000000..3e933a656 --- /dev/null +++ b/docs/content/docs/3.framework-guides/2.wordpress/4.using-wordpress-with-docker.md @@ -0,0 +1,64 @@ +--- +head.title: 'WordPress Optimizations - Docker PHP - Server Side Up' +description: 'Learn how serversideup/php is optimized for running WordPress in production.' +layout: docs +title: Using Docker with WordPress +--- +::lead-p +Ready to take the dive and modernize WordPress with Docker? + +Long story short, it can be definitely be worth it depending on your use case. From our experience, you can save yourself hours, or really over-engineer and dig yourself a hole. +:: + +## WordPress & Security Optimizations +* Hardening of Apache & NGINX included +* Disabling of XML-RPC +* Preventative access to sensitive version control or CI files +* Protection against other common attacks + +See our [Apache security.conf](https://github.com/serversideup/docker-php/blob/main/src/variations/fpm-apache/etc/apache2/conf-available/security.conf) for more detail. + +## "The WordPress Way" +We're very grateful for WordPress, and it even runs our blog for [Server Side Up](https://serversideup.net/). The only downside with WordPress is it has a lot of history with it. That means the core was written with in a mindset before all of the fancy and flashy methods that we have today. + +The most important thing you need to remember is always try to do things _"The WordPress Way"_. + +The more you work with it, the less you are fighting the platform. + +### What do you mean by "fighting the platform"? +Introducing modern toolsets to WordPress may allow you to get WordPress up and running, but severely limit you to the rest of the community tools. + +This could be things like (but not limited to): +* Using NGINX as the web server +* Deploying updates by packaging WordPress into a Docker Image +* Using too new of a PHP version +* Using [Roots Bedrock](https://roots.io/){target="_blank"} to modernize your development flow + +We've tried all of these above and we learned that most of the plugins that we relied on had issues with this. + +## How does Server Side Up run WordPress? +We embrace these principals: +1. Always do things "The WordPress Way" +1. Keep plugin installation to a minimum +1. Always use Apache as the webserver +1. Only commit _your own_ source code (not WordPress core or another plugin) + +## The structure +We run WordPress in production on Docker Swarm using: +1. [Traefik](https://traefik.io/traefik/){target="_blank"} (handles SSL automatically with Let's Encrypt) +2. [Our PHP-Apache image](https://hub.docker.com/r/serversideup/php/tags?name=fpm-apache&page=1&ordering=-name){target="_blank"} (this is optimized for WordPress) +3. [MariaDB](https://hub.docker.com/_/mariadb){target="_blank"} (the "non-Oracle" alternative to MySQL) + +## Deploying updates +We attempted to deploy WordPress with rolling updates (like we do with Laravel) by packaging WordPress into a Docker image use the [Roots Bedrock](https://roots.io/){target="_blank"} framework, but we ran into a ton of issues with community plugins. + +Our most stable solution (following "The WordPress Way") is to: +1. Mount `/var/www/html` of the container to the host +2. At the host, run an SSH `git pull` from our CI system + +Ugly, but it works 🤷‍♂️ + +## Example Repository +We included an example repository that makes it easy for you to clone down and get started. + +:u-button{to="https://github.com/serversideup/docker-wordpress" target="_blank" label="View the Example WordPress + Docker Repository" aria-label="View the Example WordPress + Docker Repository" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} From 7fe6f023751f87fcb37005005cc20cb311006cde Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 15:49:25 -0500 Subject: [PATCH 083/170] Add section on migrating from official PHP images in installation documentation, providing guidance for users already utilizing Docker, enhancing the onboarding experience for transitioning to our PHP Docker images. --- docs/content/docs/1.getting-started/3.installation.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/content/docs/1.getting-started/3.installation.md b/docs/content/docs/1.getting-started/3.installation.md index 9b9c8282b..9a854f3fc 100644 --- a/docs/content/docs/1.getting-started/3.installation.md +++ b/docs/content/docs/1.getting-started/3.installation.md @@ -36,6 +36,11 @@ If you'd like to learn more about containers, you can learn more following the g :u-button{to="/docs/deployment-and-production/container-basics" label="Learn More About Containers" aria-label="Learn More About Containers" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} +## Already using Docker? +If you're already using the official PHP images, switching will literally take you seconds. + +:u-button{to="/docs/guide/migrating-from-official-php-images" label="Learn how to migrate from the official PHP images" aria-label="Learn how to migrate from the official PHP images" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} + ## Quick Start In order to run containers, we need a container engine installed such as Docker. You can follow [Docker's installation guide](https://docs.docker.com/get-started/get-docker/) to get started. Confirm Docker is working by running these commands in your terminal: ```bash [Terminal] From 9aff799a7a4b0bf5c2c927172b8a5e21502e4ec2 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 16:01:02 -0500 Subject: [PATCH 084/170] Enhance Laravel documentation by adding tips for using Spin Pro for Task Scheduler, Queues, Horizon, and Reverb, streamlining the setup process for users deploying on VPS with Docker and zero downtime. --- .../1.laravel/2.task-scheduler.md | 13 +++++-------- .../docs/3.framework-guides/1.laravel/3.queue.md | 8 +++----- .../docs/3.framework-guides/1.laravel/4.horizon.md | 10 ++++------ .../docs/3.framework-guides/1.laravel/4.reverb.md | 10 ++++------ 4 files changed, 16 insertions(+), 25 deletions(-) diff --git a/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md b/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md index 28b4cdedd..65c04d207 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md +++ b/docs/content/docs/3.framework-guides/1.laravel/2.task-scheduler.md @@ -9,6 +9,10 @@ title: Task Scheduler Running a Laravel task scheduler with Docker can be a little different from traditional methods. ## Important concepts +::tip{to="https://getspin.pro/docs/services/laravel-scheduler" target="_blank"} +If you want the easiest way to get up and running with Laravel Task Scheduler on a VPS using Docker and zero downtime deployments, we recommend using [Spin Pro](https://getspin.pro/docs/services/laravel-scheduler){target="_blank"}. +:: + 1. If you're using `fpm-apache` or `fpm-nginx`, might need to set the stop signal to `SIGTERM` for a graceful shutdown (see this [PR](https://github.com/serversideup/docker-php/pull/437){target="_blank"} for more details why) 1. Be sure to set the health check 1. We will **not** use `cron` to run the scheduler @@ -103,11 +107,4 @@ use Illuminate\Support\Facades\Schedule; Schedule::call(function () { DB::table('recent_users')->delete(); })->daily()->at('04:00')->timezone('America/Chicago'); -``` - - - -## Get Up and Running The Easy Way -We do all the heavy lifting for you with Spin Pro. It's as easy as selecting it in a menu and we'll configure everything else for you. Learn how easy it is to get up and running with the Task Scheduler on Spin Pro. - -:u-button{to="https://getspin.pro/docs/services/laravel-scheduler" target="_blank" label="Learn more about Laravel Task Scheduler + Spin Pro" aria-label="Learn more about Laravel Task Scheduler + Spin Pro" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} +``` \ No newline at end of file diff --git a/docs/content/docs/3.framework-guides/1.laravel/3.queue.md b/docs/content/docs/3.framework-guides/1.laravel/3.queue.md index 0fe8837ec..d93de2674 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/3.queue.md +++ b/docs/content/docs/3.framework-guides/1.laravel/3.queue.md @@ -13,6 +13,9 @@ php artisan queue:work --tries=3 ``` ## Important concepts +::tip{to="https://getspin.pro/docs/services/laravel-queues" target="_blank"} +If you want the easiest way to get up and running with Laravel Queues on a VPS using Docker and zero downtime deployments, we recommend using [Spin Pro](https://getspin.pro/docs/services/laravel-queues){target="_blank"}. +:: 1. It's usually best to run the queue as a separate container (but using the same image) 1. If you're using `fpm-apache` or `fpm-nginx`, might need to set the stop signal to `SIGTERM` for a graceful shutdown (see this [PR](https://github.com/serversideup/docker-php/pull/437){target="_blank"} for more details why) 1. Be sure to set the health check @@ -39,8 +42,3 @@ services: test: ["CMD", "healthcheck-queue"] start_period: 10s ``` - -## Get Up and Running The Easy Way -We do all the heavy lifting for you with Spin Pro. It's as easy as selecting it in a menu and we'll configure everything else for you. Learn how easy it is to get up and running with Queues on Spin Pro. - -:u-button{to="https://getspin.pro/docs/services/laravel-queues" target="_blank" label="Learn more about Laravel Queues + Spin Pro" aria-label="Learn more about Laravel Queues + Spin Pro" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file diff --git a/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md b/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md index fbb63d1df..c9d4c0a6d 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md +++ b/docs/content/docs/3.framework-guides/1.laravel/4.horizon.md @@ -13,6 +13,9 @@ php artisan horizon ``` ## Important concepts +::tip{to="https://getspin.pro/docs/services/laravel-horizon" target="_blank"} +If you want the easiest way to get up and running with Laravel Horizon on a VPS using Docker and zero downtime deployments, we recommend using [Spin Pro](https://getspin.pro/docs/services/laravel-horizon){target="_blank"}. +:: 1. In most cases, you probably want to run this as a separate container from your web container 1. If you're using `fpm-apache` or `fpm-nginx`, might need to set the stop signal to `SIGTERM` for a graceful shutdown (see this [PR](https://github.com/serversideup/docker-php/pull/437){target="_blank"} for more details why) 1. Be sure to set the health check @@ -43,9 +46,4 @@ services: # This is our native healthcheck script for Horizon test: ["CMD", "healthcheck-horizon"] start_period: 10s -``` - -## Get Up and Running The Easy Way -We do all the heavy lifting for you with Spin Pro. It's as easy as selecting it in a menu and we'll configure everything else for you. Learn how easy it is to get up and running with Horizon on Spin Pro. - -:u-button{to="https://getspin.pro/docs/services/laravel-horizon" target="_blank" label="Learn more about Laravel Horizon + Spin Pro" aria-label="Learn more about Laravel Horizon + Spin Pro" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file +``` \ No newline at end of file diff --git a/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md b/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md index 7163ee115..6e104f873 100644 --- a/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md +++ b/docs/content/docs/3.framework-guides/1.laravel/4.reverb.md @@ -13,6 +13,9 @@ php artisan reverb:start ``` ## Important concepts +::tip{to="https://getspin.pro/docs/services/laravel-reverb" target="_blank"} +If you want the easiest way to get up and running with Laravel Reverb on a VPS using Docker and zero downtime deployments, we recommend using [Spin Pro](https://getspin.pro/docs/services/laravel-reverb){target="_blank"}. +:: 1. You will need to follow the [Laravel Reverb setup instructions](https://laravel.com/docs/12.x/reverb) to install the Laravel Reverb package into your Laravel application. 1. In most cases, you probably want to run this as a separate container from your web container 1. If you're using `fpm-apache` or `fpm-nginx`, might need to set the stop signal to `SIGTERM` for a graceful shutdown (see this [PR](https://github.com/serversideup/docker-php/pull/437){target="_blank"} for more details why) @@ -63,9 +66,4 @@ Reverb may require a few ENV variables to be set in your Laravel application. | `REVERB_PORT` | The port the **CLIENT** will connect to. | `443` | | `REVERB_SCHEME` | The scheme the **CLIENT** will connect to. | `https` | -Be sure to not get `REVERB_HOST` or `REVERB_PORT` confused with `REVERB_SERVER_HOST` or `REVERB_SERVER_PORT`. The `_SERVER_` variables are for the **SERVER** (the Reverb daemon itself) and the others are for the **CLIENT** (people connecting to your application). - -## Get Up and Running The Easy Way -We do all the heavy lifting for you with Spin Pro. It's as easy as selecting it in a menu and we'll configure everything else for you. Learn how easy it is to get up and running with Reverb on Spin Pro. - -:u-button{to="https://getspin.pro/docs/services/laravel-reverb" target="_blank" label="Learn more about Laravel Reverb + Spin Pro" aria-label="Learn more about Laravel Reverb + Spin Pro" size="md" color="primary" variant="outline" trailing-icon="i-lucide-arrow-right" class="font-bold"} \ No newline at end of file +Be sure to not get `REVERB_HOST` or `REVERB_PORT` confused with `REVERB_SERVER_HOST` or `REVERB_SERVER_PORT`. The `_SERVER_` variables are for the **SERVER** (the Reverb daemon itself) and the others are for the **CLIENT** (people connecting to your application). \ No newline at end of file From d8228eb09ab76b45c29c97e48608de10f8da9ae5 Mon Sep 17 00:00:00 2001 From: Jay Rogers Date: Wed, 22 Oct 2025 16:11:39 -0500 Subject: [PATCH 085/170] Add FPM-NGINX documentation, detailing usage, configuration, and performance tuning for PHP applications, enhancing guidance for users deploying Laravel and modern PHP frameworks with Docker. --- .../docs/2.image-variations/fpm-nginx.md | 333 ++++++++++++++++++ 1 file changed, 333 insertions(+) create mode 100644 docs/content/docs/2.image-variations/fpm-nginx.md diff --git a/docs/content/docs/2.image-variations/fpm-nginx.md b/docs/content/docs/2.image-variations/fpm-nginx.md new file mode 100644 index 000000000..c44bed551 --- /dev/null +++ b/docs/content/docs/2.image-variations/fpm-nginx.md @@ -0,0 +1,333 @@ +--- +title: FPM-NGINX +description: 'Learn how to use the FPM-NGINX variation of the serversideup/php image.' +--- + +::lead-p +The FPM-NGINX variation combines PHP-FPM with NGINX as a reverse proxy in a single container. This is the traditional setup widely adopted for many PHP applications and is currently is the best balance of performance, stability, and compatibility. If you want the latest and greatest, consider using the [FrankenPHP variation →](/docs/image-variations/frankenphp). +:: + +## When to Use FPM-NGINX +Use the FPM-NGINX variation when you need to: + +- Run Laravel applications with excellent performance and stability +- Want an all-in-one container with both web server and PHP processing +- Need a fast, lightweight web server with low resource consumption +- Serve static assets efficiently while processing PHP requests + +#### Perfect for +- Laravel applications (this is our most popular variation for Laravel) +- Modern PHP frameworks (Symfony, etc.) +- API-first applications +- Production deployments requiring high performance and stability + +#### What's Inside + +| Item | Status | +|------|--------| +| NGINX web server | ✅ | +| PHP-FPM process manager | ✅ | +| PHP CLI binary | ✅ | +| Common PHP extensions | ✅ | +| `composer` executable | ✅ | +| `install-php-extensions` script | ✅ | +| Essential system utilities | ✅ | +| S6 Overlay (process supervisor) | ✅ | +| Native health checks | ✅ (via HTTP endpoint) | +| SSL/TLS support | ✅ (self-signed certificates) | +| Process management | S6 Overlay supervising both NGINX and PHP-FPM | +| Exposed Ports | `8080` (HTTP), `8443` (HTTPS) | +| Stop Signal | `SIGQUIT` | + +## How FPM-NGINX Works +This variation runs both NGINX and PHP-FPM in a single container, managed by S6 Overlay. Here's how requests flow: + +::steps{level="4"} + +#### Client sends HTTP request +The container listens on port 8080 (or 8443 for HTTPS) for incoming HTTP requests. + +#### NGINX receives the request +NGINX receives the request and determines if it's a static file or PHP script. + +#### Check for static files +Static files (CSS, JavaScript, images) are served directly by NGINX. + +#### Forward PHP requests to PHP-FPM +PHP requests are forwarded to PHP-FPM via FastCGI protocol. + +#### Process PHP requests with PHP-FPM +PHP-FPM processes the PHP script and returns the result to NGINX. + +#### Send the response back to the client +NGINX sends the response back to the client. + +:: + +S6 Overlay ensures both NGINX and PHP-FPM are running and automatically restarts them if either process fails. + +::tip +This variation offers better performance than FPM-Apache for most modern PHP applications. NGINX is designed to handle high concurrency with lower resource consumption. +:: + +## Quick Start +Here are a few examples to help you get started with the FPM-NGINX variation. + +### Docker CLI +```bash [Terminal] +docker run -p 80:8080 -v $(pwd):/var/www/html/public serversideup/php:8.4-fpm-nginx +``` + +Your application will be available at `http://localhost`. The default webroot is `/var/www/html/public`. + +### Docker Compose + +::warning +Notice how we're mapping the current directory to `/var/www/html/`, but the actual default document root is `/var/www/html/public`. We're assuming you're creating the `public` directory and putting your PHP code in there. It's not best practice to expose your `compose.yml` file. See the [Installation guide](/docs/getting-started/installation) for a full example. +:: + +This is the recommended approach for local development and production deployments. + +```yml [compose.yml] +services: + php: + image: serversideup/php:8.4-fpm-nginx + ports: + - "80:8080" + volumes: + - ./:/var/www/html + environment: + PHP_OPCACHE_ENABLE: "1" +``` + +::tip +The FPM-NGINX variation uses ports 8080 and 8443 (instead of 80 and 443) to allow the container to run as a non-root user for better security. +:: + +### Laravel Example +The FPM-NGINX variation is perfectly suited for Laravel applications: + +```yml [compose.yml] +services: + php: + image: serversideup/php:8.4-fpm-nginx + ports: + - "80:8080" + - "443:8443" + volumes: + - .:/var/www/html + environment: + SSL_MODE: "full" + PHP_OPCACHE_ENABLE: "1" + depends_on: + - mariadb + - redis + + mariadb: + image: mariadb:11 + environment: + MYSQL_ROOT_PASSWORD: rootpassword + MYSQL_DATABASE: laravel + MYSQL_USER: laravel + MYSQL_PASSWORD: laravel + volumes: + - db_data:/var/lib/mysql + + redis: + image: redis:alpine + command: redis-server --appendonly yes + volumes: + - redis_data:/data + +volumes: + db_data: + redis_data: +``` + + +### Health Check +The FPM-NGINX variation includes a built-in health check that verifies NGINX is responding: + +::note +The health check endpoint is configurable via the `HEALTHCHECK_PATH` environment variable, which defaults to `/healthcheck`. +:: + +## SSL/TLS Support +The FPM-NGINX variation includes built-in SSL support with self-signed certificates for development. + +### Enabling SSL +```yml [compose.yml] +services: + php: + image: serversideup/php:8.4-fpm-nginx + ports: + - "80:8080" + - "443:8443" + volumes: + - ./:/var/www/html + environment: + SSL_MODE: "full" +``` + +Available SSL modes: +- `off` - SSL disabled (default) +- `mixed` - Both HTTP (8080) and HTTPS (8443) enabled +- `full` - HTTPS only on port 8443 + +### Custom SSL Certificates +For production, use your own SSL certificates: + +```yml [compose.yml] +services: + php: + image: serversideup/php:8.4-fpm-nginx + ports: + - "443:8443" + volumes: + - ./:/var/www/html + - ./certs/server.crt:/etc/ssl/private/self-signed-web.crt:ro + - ./certs/server.key:/etc/ssl/private/self-signed-web.key:ro + environment: + SSL_MODE: "full" +``` + +::warning +For production deployments, consider using a reverse proxy like Traefik or Caddy to handle SSL termination instead of managing certificates in the container. +:: + +## Environment Variables +The FPM-NGINX variation supports extensive customization through environment variables. + +### NGINX Configuration + +| Variable | Default | Description | +|----------|---------|-------------| +| `NGINX_WEBROOT` | `/var/www/html/public` | Document root for NGINX | +| `NGINX_ACCESS_LOG` | `/dev/stdout` | Path to access log file | +| `NGINX_ERROR_LOG` | `/dev/stderr` | Path to error log file | +| `NGINX_CLIENT_MAX_BODY_SIZE` | `100M` | Maximum upload/request body size | +| `NGINX_FASTCGI_BUFFERS` | `8 8k` | Number and size of FastCGI buffers | +| `NGINX_FASTCGI_BUFFER_SIZE` | `8k` | Size of the first FastCGI response buffer | +| `NGINX_SERVER_TOKENS` | `off` | Show NGINX version in headers (`on`/`off`) | +| `NGINX_LISTEN_IP_PROTOCOL` | `all` | IP protocol to listen on (`all`, `ipv4`, `ipv6`) | +| `SSL_MODE` | `off` | SSL mode: `off`, `mixed`, or `full` | +| `SSL_CERTIFICATE_FILE` | `/etc/ssl/private/self-signed-web.crt` | Path to SSL certificate | +| `SSL_PRIVATE_KEY_FILE` | `/etc/ssl/private/self-signed-web.key` | Path to SSL private key | +| `HEALTHCHECK_PATH` | `/healthcheck` | Path for health check endpoint | + +::tip +For a complete list of available environment variables, see the [Environment Variable Specification →](/docs/reference/environment-variable-specification). +:: + +### PHP-FPM Configuration + +| Variable | Default | Description | +|----------|---------|-------------| +| `PHP_FPM_POOL_NAME` | `www` | Name of the PHP-FPM pool | +| `PHP_FPM_PM_CONTROL` | `dynamic` | Process manager control (`dynamic`, `static`, `ondemand`) | +| `PHP_FPM_PM_MAX_CHILDREN` | `20` | Maximum number of child processes | +| `PHP_FPM_PM_START_SERVERS` | `2` | Number of child processes created on startup | +| `PHP_FPM_PM_MIN_SPARE_SERVERS` | `1` | Minimum number of idle processes | +| `PHP_FPM_PM_MAX_SPARE_SERVERS` | `3` | Maximum number of idle processes | +| `PHP_MEMORY_LIMIT` | `256M` | Maximum memory a script can use | +| `PHP_MAX_EXECUTION_TIME` | `99` | Maximum time a script can run (seconds) | +| `PHP_UPLOAD_MAX_FILE_SIZE` | `100M` | Maximum upload file size | +| `PHP_POST_MAX_SIZE` | `100M` | Maximum POST request size | + +## Performance Tuning +Here are some tuning recommendations for different scenarios: + +### For Production (low memory environments) +::note{to="docs/deployment-and-production/packaging-your-app-for-deployment"} +If you're running an application in production, you'll likely want to package your application inside an image for deployment. Click here to learn more. +:: +```yml [compose.yml] +services: + php: + # You'll likely replace this with your own custom image name + image: serversideup/php:8.4-fpm-nginx + environment: + # Enable OPcache for production + PHP_OPCACHE_ENABLE: "1" + + # NGINX Settings (adjust as needed) + NGINX_FASTCGI_BUFFERS: "16 16k" + NGINX_FASTCGI_BUFFER_SIZE: "32k" +``` + +### For High-Traffic Applications +```yml [compose.yml] +services: + php: + # You'll likely replace this with your own custom image name + image: serversideup/php:8.4-fpm-nginx + environment: + # NGINX Settings + NGINX_CLIENT_MAX_BODY_SIZE: "200M" + NGINX_FASTCGI_BUFFERS: "32 32k" + + # PHP-FPM Settings (adjust as needed) + PHP_FPM_PM_CONTROL: "static" + PHP_FPM_PM_MAX_CHILDREN: "50" + PHP_MEMORY_LIMIT: "512M" + + # OPcache Settings + PHP_OPCACHE_ENABLE: "1" +``` + +::note +These are just examples. Review the [Environment Variable Specification](/docs/reference/environment-variable-specification) for a complete list of available environment variables to match your needs. +:: + +## NGINX Configuration +Unlike Apache's `.htaccess` files, NGINX uses configuration files. The FPM-NGINX variation comes pre-configured for Laravel and modern PHP applications. + +### Default Configuration +The default NGINX configuration includes: +- FastCGI caching headers +- Gzip compression +- Security headers +- Laravel-compatible URL rewriting +- Static file optimization + +### Custom NGINX Configuration +You can add custom NGINX server configuration by mounting files: + +```yml [compose.yml] +services: + php: + image: serversideup/php:8.4-fpm-nginx + ports: + - "80:8080" + volumes: + - ./:/var/www/html + - ./custom-nginx.conf:/etc/nginx/conf.d/custom.conf:ro +``` + +Example custom configuration: + +```nginx [custom-nginx.conf] +# Add custom headers +add_header X-Custom-Header "My Value" always; + +# Custom location block +location /api { + try_files $uri $uri/ /index.php?$query_string; + + # Additional settings for API endpoints + client_max_body_size 50M; +} + +# Rate limiting +limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s; +location /api/ { + limit_req zone=api burst=20 nodelay; +} +``` + +## Further Customization +If you need to customize the container further, reference the docs below: + +- [Environment Variable Specification](/docs/reference/environment-variable-specification) - See which environment variables are available to customize PHP and NGINX settings. +- [Command Reference](/docs/reference/command-reference) - See which commands are available to run inside the container. + From fe997be04b89ee13e540d3095cf88f260532b800 Mon Sep 17 00:00:00 2001 From: Dan Pastori Date: Wed, 22 Oct 2025 16:13:58 -0500 Subject: [PATCH 086/170] Enhance documentation for PHP Docker images by adding optional 'redirect' field in content configuration, integrating '@vueuse/nuxt' in Nuxt configuration, and updating package dependencies. Introduced a new 'ServerSideUp' component for improved user interface and added redirection logic in page handling. Additionally, included a new logo for branding consistency. --- docs/app/app.vue | 2 + docs/app/components/ServerSideUp.vue | 237 ++++ docs/app/pages/[...slug].vue | 4 + docs/content.config.ts | 1 + docs/content/docs/index.md | 3 + docs/nuxt.config.ts | 1 + docs/package.json | 2 + .../logos/server-side-up-logo-horizontal.svg | 6 + docs/yarn.lock | 1103 +++++++++-------- 9 files changed, 831 insertions(+), 528 deletions(-) create mode 100644 docs/app/components/ServerSideUp.vue create mode 100644 docs/content/docs/index.md create mode 100644 docs/public/images/logos/server-side-up-logo-horizontal.svg diff --git a/docs/app/app.vue b/docs/app/app.vue index 20718807c..87830df57 100644 --- a/docs/app/app.vue +++ b/docs/app/app.vue @@ -2,6 +2,8 @@ + + +