diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index 7f09531..0000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,35 +0,0 @@ -// https://aka.ms/devcontainer.json -{ - "name": "Laravel Sail", - "dockerComposeFile": [ - "../docker-compose.yml" - ], - "service": "laravel.test", - "workspaceFolder": "/var/www/html", - "settings": {}, - "extensions": [ - "mikestead.dotenv", - "amiralizadeh9480.laravel-extra-intellisense", - "ryannaddy.laravel-artisan", - "onecentlin.laravel5-snippets", - "onecentlin.laravel-blade", - "hashicorp.hcl", - "ms-azuretools.vscode-docker", - "bmewburn.vscode-intelephense-client", - "xdebug.php-debug", - "redhat.vscode-yaml", - "eamodio.gitlens", - "coolbear.systemd-unit-file", - "ms-python.vscode-pylance", - "Vue.volar", - "timonwong.shellcheck", - "yzhang.markdown-all-in-one", - "EditorConfig.EditorConfig" - ], - "remoteUser": "sail", - "initializeCommand": "if [ ! -f .env ]; then cp .env.example .env; fi", - "postStartCommand": "composer i && php artisan migrate && php artisan ide:generate && php artisan ide:models -N" - // "forwardPorts": [], - // "runServices": [], - // "shutdownAction": "none", -} diff --git a/.env.example b/.env.example index 7fba895..bb21615 100644 --- a/.env.example +++ b/.env.example @@ -9,38 +9,35 @@ LOG_DEPRECATIONS_CHANNEL=null LOG_LEVEL=debug DB_CONNECTION=pgsql -DB_HOST=pgsql +DB_HOST=database DB_PORT=5432 DB_DATABASE=phonehome DB_USERNAME=phonehome DB_PASSWORD=phonehome -BROADCAST_DRIVER=redis -CACHE_DRIVER=redis +BROADCAST_DRIVER=log +CACHE_DRIVER=file FILESYSTEM_DISK=local -QUEUE_CONNECTION=redis -SESSION_DRIVER=redis +QUEUE_CONNECTION=sync +SESSION_DRIVER=file SESSION_LIFETIME=120 -MEMCACHED_HOST=memcached +MEMCACHED_HOST=127.0.0.1 -REDIS_HOST=redis +REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 MAIL_MAILER=smtp -MAIL_HOST=mailhog +MAIL_HOST=mailpit MAIL_PORT=1025 MAIL_USERNAME=null MAIL_PASSWORD=null MAIL_ENCRYPTION=null -MAIL_FROM_ADDRESS="hello@phonehome.localhost" +MAIL_FROM_ADDRESS="hello@example.com" MAIL_FROM_NAME="${APP_NAME}" GEOIP_TOKEN= -# Sail configuration -WWWGROUP=1000 -WWWUSER=1000 -SAIL_XDEBUG_MODE=develop,debug,coverage -SAIL_XDEBUG_CONFIG="client_host=127.0.0.1" +UID=1000 +GID=1000 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a8ed274..3edb58c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,6 +4,11 @@ on: - cron: "0 5 * * 1" workflow_call: workflow_dispatch: + +permissions: + contents: read + packages: write + jobs: build-image: name: Build images and push to registry @@ -19,7 +24,7 @@ jobs: uses: docker/metadata-action@v4 id: meta-app with: - bake-target: app + bake-target: app-production images: | ghcr.io/${{ github.repository }}-app tags: | @@ -32,7 +37,7 @@ jobs: uses: docker/metadata-action@v4 id: meta-web with: - bake-target: web + bake-target: web-production images: | ghcr.io/${{ github.repository }}-web tags: | @@ -41,102 +46,32 @@ jobs: type=semver,pattern={{major}}.{{minor}} type=semver,pattern={{major}},enable=${{ !startsWith(github.ref, 'refs/tags/0.') }} - - name: Generate cache tag for app image - uses: docker/metadata-action@v4 - id: cache-tag-app - with: - images: | - ghcr.io/${{ github.repository }}-app - tags: | - type=ref,event=branch - type=raw,enable=${{ github.ref_type == 'tag' }},value=${{ github.event.repository.default_branch }} - flavor: - suffix=-cache - - - name: Generate cache tag for web image + - name: Generate ns8 image tags uses: docker/metadata-action@v4 - id: cache-tag-web + id: meta-ns8 with: + bake-target: ns8 images: | - ghcr.io/${{ github.repository }}-web + ghcr.io/${{ github.repository }} tags: | type=ref,event=branch - type=raw,enable=${{ github.ref_type == 'tag' }},value=${{ github.event.repository.default_branch }} - flavor: - suffix=-cache + type=semver,pattern={{version}} - name: Login to Registry uses: docker/login-action@v2 with: registry: ghcr.io username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + password: ${{ github.token }} - uses: docker/bake-action@v3.1.0 with: - targets: release + targets: deploy files: | ./docker-bake.hcl ${{ steps.meta-app.outputs.bake-file }} ${{ steps.meta-web.outputs.bake-file }} + ${{ steps.meta-ns8.outputs.bake-file }} set: | - *.platform=linux/amd64 - app.cache-from=type=registry,ref=${{ steps.cache-tag-app.outputs.tags }} - app.cache-to=type=registry,ref=${{ steps.cache-tag-app.outputs.tags }},mode=max - web.cache-from=type=registry,ref=${{ steps.cache-tag-web.outputs.tags }} - web.cache-to=type=registry,ref=${{ steps.cache-tag-web.outputs.tags }},mode=max + *.cache-to=type=gha,mode=max push: true - - build-deploy: - name: Build NS8 deploy image - runs-on: ubuntu-22.04 - needs: build-image - steps: - - name: Checkout repo - uses: actions/checkout@v3 - - - name: Generate tags - uses: docker/metadata-action@v4 - id: meta - with: - images: | - ghcr.io/nethserver/ns8-phonehome - tags: | - type=ref,event=branch - type=semver,pattern={{version}} - - - name: Generate Phonehome image tags - uses: docker/metadata-action@v4 - id: phonehome-tags - with: - images: | - ghcr.io/${{ github.repository }} - tags: | - type=ref,event=branch - type=semver,pattern={{version}} - - - name: Login to Registry - uses: docker/login-action@v2 - with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - name: Build image with buildah - env: - TAGS: ${{ steps.meta.outputs.tags }} - LABELS: ${{ steps.meta.outputs.labels }} - ARGS: | - PHONEHOME_TAG=${{ steps.phonehome-tags.outputs.version }} - PHONEHOME_SERVER_APP=${{ steps.phonehome-tags.outputs.tags }}-app - PHONEHOME_SERVER_WEB=${{ steps.phonehome-tags.outputs.tags }}-web - working-directory: deploy/ns8 - run: | - ./build-images.sh - - - name: Push image to registry - run: | - PUSH_TAGS='${{ steps.meta.outputs.tags }}' - for tag in $PUSH_TAGS; do - podman push "$tag" - done diff --git a/.github/workflows/clean.yml b/.github/workflows/clean.yml deleted file mode 100644 index 5e9a7e8..0000000 --- a/.github/workflows/clean.yml +++ /dev/null @@ -1,68 +0,0 @@ -name: Clean Jobs -on: - delete: - schedule: - - cron: '0 20 * * *' - workflow_dispatch: - -permissions: - packages: write - -env: - GH_TOKEN: ${{ github.token }} - -jobs: - clean-dangling-images: - name: Clean Dangling Images from Registry - runs-on: ubuntu-22.04 - strategy: - matrix: - container: - - phonehome-server-web - - phonehome-server-app - - ns8-phonehome - steps: - - name: Delete dangling images from container releases - run: | - echo "Scanning ${{ matrix.container }} for dangling images..." - endpoint=${{ github.event.organization.url || github.event.repository.owner.url }}/packages/container/${{ matrix.container }}/versions - no_tag_versions=$(gh api --paginate --jq '.[] | select(.metadata.container.tags == []) | .id' "$endpoint") - for tag in $no_tag_versions; do - echo "Deleting $tag in ${{ matrix.container }}..." - gh api --input /dev/null -X DELETE --silent "$endpoint/$tag" - done - - clean-ref-images: - name: Remove Images from Deleted Refs - runs-on: ubuntu-22.04 - if: github.event_name == 'delete' - strategy: - matrix: - container: - - phonehome-server-web - - phonehome-server-app - - ns8-phonehome - steps: - - name: Delete Refs from Registry - run: | - echo "Scanning ${{ matrix.container }} for removed refs..." - ref=$(basename ${{ github.event.ref }}) - endpoint=${{ github.event.organization.url || github.event.repository.owner.url }}/packages/container/${{ matrix.container }}/versions - jq_query=".[] | select(.metadata.container.tags == [\"${ref}\"]) | .id" - versions_to_delete=$(gh api --paginate --jq "$jq_query" "$endpoint") - for version in $versions_to_delete; do - echo "Deleting $version in ${{ matrix.container }}..." - gh api --input /dev/null -X DELETE --silent "$endpoint/$version" - done - - - name: Delete Refs Cache - run: | - echo "Scanning ${{ matrix.container }} for removed refs cache..." - ref=$(basename ${{ github.event.ref }}) - endpoint=${{ github.event.organization.url || github.event.repository.owner.url }}/packages/container/${{ matrix.container }}/versions - jq_query=".[] | select(.metadata.container.tags == [\"${ref}-cache\"]) | .id" - versions_to_delete=$(gh api --paginate --jq "$jq_query" "$endpoint") - for version in $versions_to_delete; do - echo "Deleting $version in ${{ matrix.container }}..." - gh api --input /dev/null -X DELETE --silent "$endpoint/$version" - done diff --git a/.github/workflows/development.yml b/.github/workflows/development.yml index 38df4a6..fc1c8df 100644 --- a/.github/workflows/development.yml +++ b/.github/workflows/development.yml @@ -14,4 +14,3 @@ jobs: uses: ./.github/workflows/build.yml needs: - test-app-image - secrets: inherit diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e94fb2f..9f3a410 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,7 +1,15 @@ name: Testing on: + push: + branches: + - "renovate/**" pull_request: workflow_call: + +permissions: + contents: read + packages: read + jobs: test-app-image: name: Test app image @@ -13,24 +21,14 @@ jobs: - name: Create new buildx builder uses: docker/setup-buildx-action@v2 - - name: Generate Image Metadata - uses: docker/metadata-action@v4 - id: cache-from-tag + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 with: - images: | - ghcr.io/${{ github.repository }}-app - tags: | - type=ref,event=branch - type=raw,enable=${{ github.event_name == 'pull_request' }},value=${{ github.base_ref }} - flavor: | - latest=false - suffix=-cache + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ github.token }} - - uses: docker/bake-action@v3.1.0 - with: - files: | - ./docker-bake.hcl - targets: testing - set: | - *.platform=linux/amd64 - *.cache-from=type=registry,ref=${{ steps.cache-from-tag.outputs.tags }} + - name: Run testing + run: | + cp .env.example .env + docker compose run --rm --build testing diff --git a/.gitignore b/.gitignore index 286429e..42407c4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,95 @@ -_ide_helper* deploy/docker-compose/docker-compose.override.yml -# Created by https://www.toptal.com/developers/gitignore/api/linux,laravel,visualstudiocode -# Edit at https://www.toptal.com/developers/gitignore?templates=linux,laravel,visualstudiocode + +# Created by https://www.toptal.com/developers/gitignore/api/linux,laravel,visualstudiocode,intellij+all +# Edit at https://www.toptal.com/developers/gitignore?templates=linux,laravel,visualstudiocode,intellij+all + +### Intellij+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### Intellij+all Patch ### +# Ignore everything but code style settings and run configurations +# that are supposed to be shared within teams. + +.idea/* + +!.idea/codeStyles +!.idea/runConfigurations ### Laravel ### /vendor/ @@ -62,10 +150,4 @@ Homestead.json .history .ionide -# Support for Project snippet scope -.vscode/*.code-snippets - -# Ignore code-workspaces -*.code-workspace - -# End of https://www.toptal.com/developers/gitignore/api/linux,laravel,visualstudiocode +# End of https://www.toptal.com/developers/gitignore/api/linux,laravel,visualstudiocode,intellij+all diff --git a/.vscode/launch.json b/.vscode/launch.json deleted file mode 100644 index 8103dd2..0000000 --- a/.vscode/launch.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Listen for Xdebug", - "type": "php", - "request": "launch", - "port": 9003 - } - ] -} diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index 2bd7a10..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "label": "Format PHP", - "type": "shell", - "command": "./vendor/bin/pint", - "problemMatcher": [] - }, - { - "label": "PHPStan", - "type": "shell", - "command": "./vendor/bin/phpstan", - "problemMatcher": [] - }, - { - "label": "Run tests", - "type": "shell", - "command": "php artisan test", - "problemMatcher": [] - } - ] -} diff --git a/app/Console/Commands/SetupCommand.php b/app/Console/Commands/SetupCommand.php index 1eadbf4..c4225dd 100644 --- a/app/Console/Commands/SetupCommand.php +++ b/app/Console/Commands/SetupCommand.php @@ -34,13 +34,13 @@ public function handle(): int { $this->info('Waiting for database to come up'); $this->execProcess(['wait-for', '-t', '30', config('database.connections.mysql.host').':'.config('database.connections.mysql.port')]); - $this->info('Cheching if the redis is ready'); - $this->execProcess(['wait-for', '-t', '30', config('database.redis.cache.host').':'.config('database.redis.cache.port')]); - $this->info('Copying public folder contents to web container...'); - $this->execProcess(['cp', '-r', 'public', '/app']); - $this->info('Setting up Laravel'); - $this->call('config:cache'); - $this->execProcess(['su', '-s', '/bin/sh', '-c', 'php artisan view:cache', 'www-data']); + if (app()->isProduction()) { + $this->info('Copying public folder contents to web container...'); + $this->execProcess(['cp', '-r', 'public', '/app']); + $this->info('Setting up Laravel'); + $this->call('config:cache'); + $this->call('view:cache'); + } $this->call('storage:link'); $this->info('Migrating database'); $this->call('migrate', [ diff --git a/config/database.php b/config/database.php index 137ad18..9144b5f 100644 --- a/config/database.php +++ b/config/database.php @@ -15,7 +15,7 @@ | */ - 'default' => env('DB_CONNECTION', 'mysql'), + 'default' => env('DB_CONNECTION', 'pgsql'), /* |-------------------------------------------------------------------------- diff --git a/containers/nginx/Dockerfile b/containers/nginx/Dockerfile index ed1d3a7..b851188 100644 --- a/containers/nginx/Dockerfile +++ b/containers/nginx/Dockerfile @@ -1,10 +1,10 @@ -FROM nginx:1.25.2-alpine as production +FROM nginx:1.25.4-alpine as production WORKDIR /var/www/html -ADD https://github.com/eficode/wait-for/releases/download/v2.2.4/wait-for /usr/local/bin/ -COPY containers/nginx/start.sh /usr/local/bin/start -RUN chmod u+x /usr/local/bin/wait-for \ - && chmod u+x /usr/local/bin/start COPY containers/nginx/config /etc/nginx +ADD --chmod=755 \ + --checksum=sha256:206a8f9b2177703fc5aa924d85ad6c72e82413e2d09635b4c9c82a1b65b5b3d5 \ + https://github.com/eficode/wait-for/releases/download/v2.2.4/wait-for /usr/local/bin/wait-for +COPY --chmod=777 \ + containers/nginx/entrypoint.sh /docker-entrypoint.d/90-wait-fpm.sh COPY public ./public -ENTRYPOINT ["start"] -CMD ["nginx", "-g", "daemon off;"] +HEALTHCHECK CMD curl --fail --silent --output /dev/null http://localhost/status diff --git a/containers/nginx/config/conf.d/status.conf b/containers/nginx/config/conf.d/status.conf index cd6219b..44302f7 100644 --- a/containers/nginx/config/conf.d/status.conf +++ b/containers/nginx/config/conf.d/status.conf @@ -1,6 +1,6 @@ server { listen localhost; - server_name status.localhost; + server_name localhost; keepalive_timeout 0; access_log off; diff --git a/containers/nginx/config/h5bp/basic.conf b/containers/nginx/config/h5bp/basic.conf deleted file mode 100644 index faf9afc..0000000 --- a/containers/nginx/config/h5bp/basic.conf +++ /dev/null @@ -1,8 +0,0 @@ -# Nginx Server Configs | MIT License -# https://github.com/h5bp/server-configs-nginx - -include h5bp/security/referrer-policy.conf; -include h5bp/security/x-content-type-options.conf; -include h5bp/security/x-frame-options.conf; -include h5bp/location/security_file_access.conf; -include h5bp/cross-origin/requests.conf; diff --git a/containers/nginx/config/h5bp/cross-origin/requests.conf b/containers/nginx/config/h5bp/cross-origin/requests.conf deleted file mode 100644 index 976961f..0000000 --- a/containers/nginx/config/h5bp/cross-origin/requests.conf +++ /dev/null @@ -1,18 +0,0 @@ -# ---------------------------------------------------------------------- -# | Cross-origin requests | -# ---------------------------------------------------------------------- - -# Allow cross-origin requests. -# -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS -# https://enable-cors.org/ -# https://www.w3.org/TR/cors/ - -# (!) Do not use this without understanding the consequences. -# This will permit access from any other website. -# Instead of using this file, consider using a specific rule such as -# allowing access based on (sub)domain: -# -# add_header Access-Control-Allow-Origin "subdomain.example.com"; - -add_header Access-Control-Allow-Origin $cors; diff --git a/containers/nginx/config/h5bp/cross-origin/resource_timing.conf b/containers/nginx/config/h5bp/cross-origin/resource_timing.conf deleted file mode 100644 index c706a77..0000000 --- a/containers/nginx/config/h5bp/cross-origin/resource_timing.conf +++ /dev/null @@ -1,15 +0,0 @@ -# ---------------------------------------------------------------------- -# | Cross-origin resource timing | -# ---------------------------------------------------------------------- - -# Allow cross-origin access to the timing information for all resources. -# -# If a resource isn't served with a `Timing-Allow-Origin` header that would -# allow its timing information to be shared with the document, some of the -# attributes of the `PerformanceResourceTiming` object will be set to zero. -# -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Timing-Allow-Origin -# https://www.w3.org/TR/resource-timing/ -# https://www.stevesouders.com/blog/2014/08/21/resource-timing-practical-tips/ - -add_header Timing-Allow-Origin "*"; diff --git a/containers/nginx/config/h5bp/errors/custom_errors.conf b/containers/nginx/config/h5bp/errors/custom_errors.conf deleted file mode 100644 index 6b3e796..0000000 --- a/containers/nginx/config/h5bp/errors/custom_errors.conf +++ /dev/null @@ -1,9 +0,0 @@ -# ---------------------------------------------------------------------- -# | Custom error messages/pages | -# ---------------------------------------------------------------------- - -# Customize what Nginx returns to the client in case of an error. -# -# https://nginx.org/en/docs/http/ngx_http_core_module.html#error_page - -error_page 404 /404.html; diff --git a/containers/nginx/config/h5bp/location/security_file_access.conf b/containers/nginx/config/h5bp/location/security_file_access.conf deleted file mode 100644 index 1848020..0000000 --- a/containers/nginx/config/h5bp/location/security_file_access.conf +++ /dev/null @@ -1,41 +0,0 @@ -# ---------------------------------------------------------------------- -# | File access | -# ---------------------------------------------------------------------- - -# Block access to all hidden files and directories except for the -# visible content from within the `/.well-known/` hidden directory. -# -# These types of files usually contain user preferences or the preserved state -# of a utility, and can include rather private places like, for example, the -# `.git` or `.svn` directories. -# -# The `/.well-known/` directory represents the standard (RFC 5785) path prefix -# for "well-known locations" (e.g.: `/.well-known/manifest.json`, -# `/.well-known/keybase.txt`), and therefore, access to its visible content -# should not be blocked. -# -# https://www.mnot.net/blog/2010/04/07/well-known -# https://tools.ietf.org/html/rfc5785 - -location ~* /\.(?!well-known\/) { - deny all; -} - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Block access to files that can expose sensitive information. -# -# By default, block access to backup and source files that may be left by some -# text editors and can pose a security risk when anyone has access to them. -# -# https://feross.org/cmsploit/ -# -# (!) Update the `location` regular expression from below to include any files -# that might end up on your production server and can expose sensitive -# information about your website. These files may include: configuration -# files, files that contain metadata about the project (e.g.: project -# dependencies, build scripts, etc.). - -location ~* (?:#.*#|\.(?:bak|conf|dist|fla|in[ci]|log|orig|psd|sh|sql|sw[op])|~)$ { - deny all; -} diff --git a/containers/nginx/config/h5bp/location/web_performance_filename-based_cache_busting.conf b/containers/nginx/config/h5bp/location/web_performance_filename-based_cache_busting.conf deleted file mode 100644 index cb9274f..0000000 --- a/containers/nginx/config/h5bp/location/web_performance_filename-based_cache_busting.conf +++ /dev/null @@ -1,14 +0,0 @@ -# ---------------------------------------------------------------------- -# | Filename-based cache busting | -# ---------------------------------------------------------------------- - -# If you're not using a build process to manage your filename version revving, -# you might want to consider enabling the following directives. -# -# To understand why this is important and even a better solution than using -# something like `*.css?v231`, please see: -# https://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/ - -location ~* (.+)\.(?:\w+)\.(avifs?|bmp|css|cur|gif|ico|jpe?g|jxl|m?js|a?png|svgz?|webp|webmanifest)$ { - try_files $uri $1.$2; -} diff --git a/containers/nginx/config/h5bp/location/web_performance_svgz-compression.conf b/containers/nginx/config/h5bp/location/web_performance_svgz-compression.conf deleted file mode 100644 index 4e4143c..0000000 --- a/containers/nginx/config/h5bp/location/web_performance_svgz-compression.conf +++ /dev/null @@ -1,18 +0,0 @@ -# ---------------------------------------------------------------------- -# | SVGZ Compression | -# ---------------------------------------------------------------------- - -# SVGZ files are already compressed. -# Disable gzip function for `.svgz` files. - -location ~* \.svgz$ { - gzip off; - add_header Content-Encoding gzip; - - include h5bp/security/x-content-type-options.conf; - include h5bp/security/content-security-policy.conf; - include h5bp/security/referrer-policy.conf; - include h5bp/security/permissions-policy.conf; - include h5bp/security/cross-origin-policy.conf; - include h5bp/cross-origin/requests.conf; -} diff --git a/containers/nginx/config/h5bp/media_types/character_encodings.conf b/containers/nginx/config/h5bp/media_types/character_encodings.conf deleted file mode 100644 index 955c1db..0000000 --- a/containers/nginx/config/h5bp/media_types/character_encodings.conf +++ /dev/null @@ -1,32 +0,0 @@ -# ---------------------------------------------------------------------- -# | Character encodings | -# ---------------------------------------------------------------------- - -# Serve all resources labeled as `text/html` or `text/plain` with the media type -# `charset` parameter set to `UTF-8`. -# -# https://nginx.org/en/docs/http/ngx_http_charset_module.html#charset - -charset utf-8; - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Update charset_types to match updated mime.types. -# `text/html` is always included by charset module. -# Default: text/html text/xml text/plain text/vnd.wap.wml application/javascript application/rss+xml -# -# https://nginx.org/en/docs/http/ngx_http_charset_module.html#charset_types - -charset_types - text/css - text/plain - text/vnd.wap.wml - text/javascript - text/markdown - text/calendar - text/x-component - text/vcard - text/cache-manifest - text/vtt - application/json - application/manifest+json; diff --git a/containers/nginx/config/h5bp/media_types/media_types.conf b/containers/nginx/config/h5bp/media_types/media_types.conf deleted file mode 100644 index b7d6f9e..0000000 --- a/containers/nginx/config/h5bp/media_types/media_types.conf +++ /dev/null @@ -1,18 +0,0 @@ -# ---------------------------------------------------------------------- -# | Media types | -# ---------------------------------------------------------------------- - -# Serve resources with the proper media types (f.k.a. MIME types). -# -# https://www.iana.org/assignments/media-types/media-types.xhtml -# https://nginx.org/en/docs/http/ngx_http_core_module.html#types - -include mime.types; - -# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# Default: text/plain -# -# https://nginx.org/en/docs/http/ngx_http_core_module.html#default_type - -default_type application/octet-stream; diff --git a/containers/nginx/config/h5bp/security/content-security-policy.conf b/containers/nginx/config/h5bp/security/content-security-policy.conf deleted file mode 100644 index 20c2bd8..0000000 --- a/containers/nginx/config/h5bp/security/content-security-policy.conf +++ /dev/null @@ -1,28 +0,0 @@ -# ---------------------------------------------------------------------- -# | Content Security Policy (CSP) | -# ---------------------------------------------------------------------- - -# Mitigate the risk of cross-site scripting and other content-injection -# attacks. -# -# This can be done by setting a Content Security Policy which permits -# trusted sources of content for your website. -# -# There is no policy that fits all websites, you will have to modify the -# `Content-Security-Policy` directives in the example depending on your needs. -# -# To make your CSP implementation easier, you can use an online CSP header -# generator such as: -# https://report-uri.com/home/generate/ -# -# It is encouraged that you validate your CSP header using a CSP validator -# such as: -# https://csp-evaluator.withgoogle.com -# -# https://www.w3.org/TR/CSP/ -# https://owasp.org/www-project-secure-headers/#content-security-policy -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy -# https://developers.google.com/web/fundamentals/security/csp -# https://content-security-policy.com/ - -add_header Content-Security-Policy $content_security_policy always; diff --git a/containers/nginx/config/h5bp/security/cross-origin-policy.conf b/containers/nginx/config/h5bp/security/cross-origin-policy.conf deleted file mode 100644 index 40cb6e5..0000000 --- a/containers/nginx/config/h5bp/security/cross-origin-policy.conf +++ /dev/null @@ -1,44 +0,0 @@ -# ---------------------------------------------------------------------- -# | Cross Origin Policy | -# ---------------------------------------------------------------------- - -# Set strict a Cross Origin Policy to mitigate information leakage. -# -# (1) Cross-Origin-Embedder-Policy prevents a document from loading any -# cross-origin resources that don’t explicitly grant the document -# permission. -# https://html.spec.whatwg.org/multipage/origin.html#coep -# https://owasp.org/www-project-secure-headers/#cross-origin-embedder-policy -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy -# -# (2) Cross-Origin-Opener-Policy allows you to ensure a top-level document does -# not share a browsing context group with cross-origin documents. -# https://html.spec.whatwg.org/multipage/origin.html#cross-origin-opener-policies -# https://owasp.org/www-project-secure-headers/#cross-origin-opener-policy -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy -# -# (3) Cross-Origin-Resource-Policy allows to define a policy that lets web -# sites and applications opt in to protection against certain requests from -# other origins, to mitigate speculative side-channel attacks. -# https://fetch.spec.whatwg.org/#cross-origin-resource-policy-header -# https://owasp.org/www-project-secure-headers/#cross-origin-resource-policy -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy -# https://resourcepolicy.fyi/ -# -# To check your Cross Origin Policy, you can use an online service, such as: -# https://securityheaders.com/ -# https://observatory.mozilla.org/ -# -# https://web.dev/coop-coep/ -# https://web.dev/why-coop-coep/ -# https://web.dev/cross-origin-isolation-guide/ -# https://scotthelme.co.uk/coop-and-coep/ - -# (1) -add_header Cross-Origin-Embedder-Policy $coep_policy always; - -# (2) -add_header Cross-Origin-Opener-Policy $coop_policy always; - -# (3) -add_header Cross-Origin-Resource-Policy $corp_policy always; diff --git a/containers/nginx/config/h5bp/security/permissions-policy.conf b/containers/nginx/config/h5bp/security/permissions-policy.conf deleted file mode 100644 index 00bdedf..0000000 --- a/containers/nginx/config/h5bp/security/permissions-policy.conf +++ /dev/null @@ -1,23 +0,0 @@ -# ---------------------------------------------------------------------- -# | Permissions Policy | -# ---------------------------------------------------------------------- - -# Set a strict Permissions Policy to mitigate access to browser features. -# -# The header uses a structured syntax, and allows sites to more tightly -# restrict which origins can be granted access to features. -# The list of available features: https://github.com/w3c/webappsec-permissions-policy/blob/main/features.md -# -# The example policy below aims to disable all features expect synchronous -# `XMLHttpRequest` requests on the same origin. -# -# To check your Permissions Policy, you can use an online service, such as: -# https://securityheaders.com/ -# https://observatory.mozilla.org/ -# -# https://www.w3.org/TR/permissions-policy-1/ -# https://owasp.org/www-project-secure-headers/#permissions-policy -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy -# https://scotthelme.co.uk/a-new-security-header-feature-policy/ - -add_header Permissions-Policy $permissions_policy always; diff --git a/containers/nginx/config/h5bp/security/referrer-policy.conf b/containers/nginx/config/h5bp/security/referrer-policy.conf deleted file mode 100644 index 2c92a69..0000000 --- a/containers/nginx/config/h5bp/security/referrer-policy.conf +++ /dev/null @@ -1,25 +0,0 @@ -# ---------------------------------------------------------------------- -# | Referrer Policy | -# ---------------------------------------------------------------------- - -# Set a strict Referrer Policy to mitigate information leakage. -# -# (1) The `Referrer-Policy` header is included in responses for resources -# that are able to request (or navigate to) other resources. -# -# This includes the commonly used resource types: -# HTML, CSS, XML/SVG, PDF documents, scripts and workers. -# -# To prevent referrer leakage entirely, specify the `no-referrer` value -# instead. Note that the effect could impact analytics metrics negatively. -# -# To check your Referrer Policy, you can use an online service, such as: -# https://securityheaders.com/ -# https://observatory.mozilla.org/ -# -# https://www.w3.org/TR/referrer-policy/ -# https://owasp.org/www-project-secure-headers/#referrer-policy -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy -# https://scotthelme.co.uk/a-new-security-header-referrer-policy/ - -add_header Referrer-Policy $referrer_policy always; diff --git a/containers/nginx/config/h5bp/security/server_software_information.conf b/containers/nginx/config/h5bp/security/server_software_information.conf deleted file mode 100644 index f80048f..0000000 --- a/containers/nginx/config/h5bp/security/server_software_information.conf +++ /dev/null @@ -1,9 +0,0 @@ -# ---------------------------------------------------------------------- -# | Server software information | -# ---------------------------------------------------------------------- - -# Prevent Nginx from sending its version number in the "Server" response header. -# -# https://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens - -server_tokens off; diff --git a/containers/nginx/config/h5bp/security/strict-transport-security.conf b/containers/nginx/config/h5bp/security/strict-transport-security.conf deleted file mode 100644 index 9f66063..0000000 --- a/containers/nginx/config/h5bp/security/strict-transport-security.conf +++ /dev/null @@ -1,38 +0,0 @@ -# ---------------------------------------------------------------------- -# | HTTP Strict Transport Security (HSTS) | -# ---------------------------------------------------------------------- - -# Force client-side TLS (Transport Layer Security) redirection. -# -# If a user types `example.com` in their browser, even if the server redirects -# them to the secure version of the website, that still leaves a window of -# opportunity (the initial HTTP connection) for an attacker to downgrade or -# redirect the request. -# -# The following header ensures that a browser only connects to your server -# via HTTPS, regardless of what the users type in the browser's address bar. -# -# (!) Be aware that Strict Transport Security is not revokable and you -# must ensure being able to serve the site over HTTPS for the duration -# you've specified in the `max-age` directive. When you don't have a -# valid TLS connection anymore (e.g. due to an expired TLS certificate) -# your visitors will see a nasty error message even when attempting to -# connect over HTTP. -# -# (1) Preloading Strict Transport Security. -# To submit your site for HSTS preloading, it is required that: -# * the `includeSubDomains` directive is specified -# * the `preload` directive is specified -# * the `max-age` is specified with a value of at least 31536000 seconds -# (1 year). -# https://hstspreload.org/#deployment-recommendations -# -# https://tools.ietf.org/html/rfc6797#section-6.1 -# https://owasp.org/www-project-secure-headers/#http-strict-transport-security -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security -# https://www.html5rocks.com/en/tutorials/security/transport-layer-security/ -# https://hstspreload.org/ - -add_header Strict-Transport-Security "max-age=16070400; includeSubDomains" always; -# (1) Enable your site for HSTS preload inclusion. -# add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always; diff --git a/containers/nginx/config/h5bp/security/x-content-type-options.conf b/containers/nginx/config/h5bp/security/x-content-type-options.conf deleted file mode 100644 index ee0b464..0000000 --- a/containers/nginx/config/h5bp/security/x-content-type-options.conf +++ /dev/null @@ -1,17 +0,0 @@ -# ---------------------------------------------------------------------- -# | Content Type Options | -# ---------------------------------------------------------------------- - -# Prevent some browsers from MIME-sniffing the response. -# -# This reduces exposure to drive-by download attacks and cross-origin data -# leaks, and should be left uncommented, especially if the server is serving -# user-uploaded content or content that could potentially be treated as -# executable by the browser. -# -# https://owasp.org/www-project-secure-headers/#x-content-type-options -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options -# https://blogs.msdn.microsoft.com/ie/2008/07/02/ie8-security-part-v-comprehensive-protection/ -# https://mimesniff.spec.whatwg.org/ - -add_header X-Content-Type-Options nosniff always; diff --git a/containers/nginx/config/h5bp/security/x-frame-options.conf b/containers/nginx/config/h5bp/security/x-frame-options.conf deleted file mode 100644 index 22e7049..0000000 --- a/containers/nginx/config/h5bp/security/x-frame-options.conf +++ /dev/null @@ -1,37 +0,0 @@ -# ---------------------------------------------------------------------- -# | Frame Options | -# ---------------------------------------------------------------------- - -# Protect website against clickjacking. -# -# The example below sends the `X-Frame-Options` response header with the value -# `DENY`, informing browsers not to display the content of the web page in any -# frame. -# -# This might not be the best setting for everyone. You should read about the -# other two possible values the `X-Frame-Options` header field can have: -# `SAMEORIGIN` and `ALLOW-FROM`. -# https://tools.ietf.org/html/rfc7034#section-2.1. -# -# Keep in mind that while you could send the `X-Frame-Options` header for all -# of your website's pages, this has the potential downside that it forbids even -# non-malicious framing of your content. -# -# Nonetheless, you should ensure that you send the `X-Frame-Options` header for -# all pages that allow a user to make a state-changing operation (e.g: pages -# that contain one-click purchase links, checkout or bank-transfer confirmation -# pages, pages that make permanent configuration changes, etc.). -# -# Sending the `X-Frame-Options` header can also protect your website against -# more than just clickjacking attacks. -# https://cure53.de/xfo-clickjacking.pdf. -# -# (!) The `Content-Security-Policy` header has a `frame-ancestors` directive -# which obsoletes this header for supporting browsers. -# -# https://tools.ietf.org/html/rfc7034 -# https://owasp.org/www-project-secure-headers/#x-frame-options -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options -# https://docs.microsoft.com/archive/blogs/ieinternals/combating-clickjacking-with-x-frame-options - -add_header X-Frame-Options $x_frame_options always; diff --git a/containers/nginx/config/h5bp/tls/certificate_files.conf b/containers/nginx/config/h5bp/tls/certificate_files.conf deleted file mode 100644 index 5b326f4..0000000 --- a/containers/nginx/config/h5bp/tls/certificate_files.conf +++ /dev/null @@ -1,30 +0,0 @@ -# ---------------------------------------------------------------------- -# | Certificate files | -# ---------------------------------------------------------------------- - -# This default SSL certificate will be served whenever the client lacks support -# for SNI (Server Name Indication). -# -# (1) Certificate and key files location -# The certificate file can contain an intermediate certificate. -# -# https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate -# -# (2) Intermediate certificate location if loaded certificate (1) does not -# contain intermediate certificate when enabling OCSP stapling. -# -# https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_trusted_certificate -# -# (3) CA certificate file location for client certificate authentication. -# -# https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_client_certificate - -# (1) -ssl_certificate /etc/nginx/certs/default.crt; -ssl_certificate_key /etc/nginx/certs/default.key; - -# (2) -# ssl_trusted_certificate /path/to/ca.crt; - -# (3) -# ssl_client_certificate /etc/nginx/default_ssl.crt; diff --git a/containers/nginx/config/h5bp/tls/ocsp_stapling.conf b/containers/nginx/config/h5bp/tls/ocsp_stapling.conf deleted file mode 100644 index 4a16fbc..0000000 --- a/containers/nginx/config/h5bp/tls/ocsp_stapling.conf +++ /dev/null @@ -1,34 +0,0 @@ -# ---------------------------------------------------------------------- -# | Online Certificate Status Protocol stapling | -# ---------------------------------------------------------------------- - -# OCSP is a lightweight, only one record to help clients verify the validity of -# the server certificate. -# OCSP stapling allows the server to send its cached OCSP record during the TLS -# handshake, without the need of 3rd party OCSP responder. -# -# https://wiki.mozilla.org/Security/Server_Side_TLS#OCSP_Stapling -# https://tools.ietf.org/html/rfc6066#section-8 -# https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_stapling -# -# (1) Use Cloudflare 1.1.1.1 DNS resolver -# https://developers.cloudflare.com/1.1.1.1/setting-up-1.1.1.1/ -# -# (2) Use Google 8.8.8.8 DNS resolver -# https://developers.google.com/speed/public-dns/docs/using -# -# (3) Use OpenDNS resolver -# https://use.opendns.com - -ssl_stapling on; -ssl_stapling_verify on; - -resolver - # (1) - 1.1.1.1 1.0.0.1 [2606:4700:4700::1111] [2606:4700:4700::1001] - # (2) - 8.8.8.8 8.8.4.4 [2001:4860:4860::8888] [2001:4860:4860::8844] - # (3) - # 208.67.222.222 208.67.220.220 [2620:119:35::35] [2620:119:53::53] - valid=60s; -resolver_timeout 2s; diff --git a/containers/nginx/config/h5bp/tls/policy_balanced.conf b/containers/nginx/config/h5bp/tls/policy_balanced.conf deleted file mode 100644 index f8a19c9..0000000 --- a/containers/nginx/config/h5bp/tls/policy_balanced.conf +++ /dev/null @@ -1,20 +0,0 @@ -# ---------------------------------------------------------------------- -# | SSL policy - Balanced | -# ---------------------------------------------------------------------- - -# For services that need to support a wide range of clients, this configuration -# is reasonably balanced. -# -# (1) The NIST curves (prime256v1, secp384r1, secp521r1) are known to be weak -# and potentially vulnerable but are required to support Microsoft Edge -# and Safari. -# https://safecurves.cr.yp.to/ -# -# https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_configurations -# https://nginx.org/en/docs/http/ngx_http_ssl_module.html - -ssl_protocols TLSv1.2; -ssl_ciphers EECDH+CHACHA20:EECDH+AES; - -# (1) -ssl_ecdh_curve X25519:prime256v1:secp521r1:secp384r1; diff --git a/containers/nginx/config/h5bp/tls/policy_strict.conf b/containers/nginx/config/h5bp/tls/policy_strict.conf deleted file mode 100644 index 8d0a70b..0000000 --- a/containers/nginx/config/h5bp/tls/policy_strict.conf +++ /dev/null @@ -1,50 +0,0 @@ -# ---------------------------------------------------------------------- -# | SSL policy - Strict | -# ---------------------------------------------------------------------- - -# For services that don't need backward compatibility, the parameters below -# provide the highest level of security and performance. -# -# (!) This policy enforces a strong TLS configuration, which may raise -# errors with old clients. -# If a more compatible profile is required, use the "balanced" policy. -# -# (!) TLSv1.3 and its 0-RTT feature require NGINX >=1.15.4 and OpenSSL >=1.1.1 -# to be installed. -# -# (!) Don't enable `ssl_early_data` blindly! Requests sent within early data are -# subject to replay attacks. -# -# (1) The NIST curves (prime256v1, secp384r1, secp521r1) are known to be weak -# and potentially vulnerable. -# -# Add them back to the parameter `ssl_ecdh_curve` below to support -# Microsoft Edge and Safari. -# -# https://safecurves.cr.yp.to/ -# -# (2) Enables TLS 1.3 0-RTT, allows for faster resumption of TLS sessions. -# -# (!) Requests sent within early data are subject to replay attacks. -# To protect against such attacks at the application layer, the -# `$ssl_early_data` variable should be used: -# -# proxy_set_header Early-Data $ssl_early_data; -# -# The application should return response code 425 "Too Early" for anything -# that could contain user supplied data. -# -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/425 -# -# https://github.com/certbot/certbot/issues/6367 -# https://github.com/mozilla/server-side-tls/issues/217 -# https://nginx.org/en/docs/http/ngx_http_ssl_module.html - -ssl_protocols TLSv1.2 TLSv1.3; -ssl_ciphers EECDH+CHACHA20:EECDH+AES; - -# (1) -ssl_ecdh_curve X25519; - -# (2) -#ssl_early_data on; diff --git a/containers/nginx/config/h5bp/tls/ssl_engine.conf b/containers/nginx/config/h5bp/tls/ssl_engine.conf deleted file mode 100644 index 41d477d..0000000 --- a/containers/nginx/config/h5bp/tls/ssl_engine.conf +++ /dev/null @@ -1,44 +0,0 @@ -# ---------------------------------------------------------------------- -# | SSL engine | -# ---------------------------------------------------------------------- - -# (1) Optimize SSL by caching session parameters for 24 hours. -# This cuts down on the number of expensive SSL handshakes. -# By enabling a cache, we tell the client to re-use the already -# negotiated state. -# Here 10m (10 MB) in ssl_session_cache is size value (not time). -# 1 MB cache can store about 4000 sessions, so we can store 40000 sessions. -# -# (2) Use a higher keepalive timeout to reduce the need for repeated handshakes -# (!) Shouldn't be done unless you serve primarily HTTPS. -# Default is 75s -# -# (3) SSL buffer size -# Set 1400 bytes to fit in one MTU. -# https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_buffer_size -# -# (4) Disable session tickets -# Session tickets keys are not auto-rotated. Only a HUP / restart will do -# so and when a restart is performed the previous key is lost, which resets -# all previous sessions. -# Only enable session tickets if you set up a manual rotation mechanism. -# https://trac.nginx.org/nginx/changeset/1356a3b9692441e163b4e78be4e9f5a46c7479e9/nginx -# https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_tickets -# -# (5) Basic security improvements - -# (1) -ssl_session_timeout 24h; -ssl_session_cache shared:SSL:10m; - -# (2) -keepalive_timeout 300s; - -# (3) -# ssl_buffer_size 1400; - -# (4) -ssl_session_tickets off; - -# (5) -ssl_prefer_server_ciphers on; diff --git a/containers/nginx/config/h5bp/web_performance/cache-file-descriptors.conf b/containers/nginx/config/h5bp/web_performance/cache-file-descriptors.conf deleted file mode 100644 index 5f5e176..0000000 --- a/containers/nginx/config/h5bp/web_performance/cache-file-descriptors.conf +++ /dev/null @@ -1,34 +0,0 @@ -# ---------------------------------------------------------------------- -# | Cache file-descriptors | -# ---------------------------------------------------------------------- - -# This tells Nginx to cache open file handles, "Not Found" errors and -# metadata about files and their permissions. -# -# Based on these cached metadata, Nginx can immediately begin sending data when -# a popular file is requested, and will also know to immediately send a 404 if a -# file is missing on disk, and so on. -# -# (!) It also means that the server won't react immediately to changes on disk, -# which may be undesirable. -# As only metadata are cached, edited files may be truncated until the cache -# is refreshed. -# https://github.com/h5bp/server-configs-nginx/issues/203 -# -# In the below configuration, inactive files are released from the cache after -# 20 seconds, whereas active (recently requested) files are re-validated every -# 30 seconds. -# Descriptors will not be cached unless they are used at least 2 times within -# 20 seconds (the inactive time). -# A maximum of the 1000 most recently used file descriptors can be cached at -# any time. -# -# Production servers with stable file collections will definitely want to enable -# the cache. -# -# https://nginx.org/en/docs/http/ngx_http_core_module.html#open_file_cache - -open_file_cache max=1000 inactive=20s; -open_file_cache_valid 30s; -open_file_cache_min_uses 2; -open_file_cache_errors on; diff --git a/containers/nginx/config/h5bp/web_performance/cache_expiration.conf b/containers/nginx/config/h5bp/web_performance/cache_expiration.conf deleted file mode 100644 index 1f2055e..0000000 --- a/containers/nginx/config/h5bp/web_performance/cache_expiration.conf +++ /dev/null @@ -1,76 +0,0 @@ -# ---------------------------------------------------------------------- -# | Cache expiration | -# ---------------------------------------------------------------------- - -# Serve resources with a far-future expiration date. -# -# (!) If you don't control versioning with filename-based cache busting, you -# should consider lowering the cache times to something like one week. -# -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Expires -# https://nginx.org/en/docs/http/ngx_http_headers_module.html#expires - -map $sent_http_content_type $expires { - default 1y; - - # No content - "" off; - - # CSS - ~*text/css 1y; - - # Data interchange - ~*application/atom\+xml 1h; - ~*application/rdf\+xml 1h; - ~*application/rss\+xml 1h; - - ~*application/json 0; - ~*application/ld\+json 0; - ~*application/schema\+json 0; - ~*application/geo\+json 0; - ~*application/xml 0; - ~*text/calendar 0; - ~*text/xml 0; - - # Favicon (cannot be renamed!) and cursor images - ~*image/vnd.microsoft.icon 1w; - ~*image/x-icon 1w; - - # HTML - ~*text/html 0; - - # JavaScript - ~*application/javascript 1y; - ~*application/x-javascript 1y; - ~*text/javascript 1y; - - # Manifest files - ~*application/manifest\+json 1w; - ~*application/x-web-app-manifest\+json 0; - ~*text/cache-manifest 0; - - # Markdown - ~*text/markdown 0; - - # Media files - ~*audio/ 1y; - ~*image/ 1y; - ~*video/ 1y; - - # WebAssembly - ~*application/wasm 1y; - - # Web fonts - ~*font/ 1y; - ~*application/vnd.ms-fontobject 1y; - ~*application/x-font-ttf 1y; - ~*application/x-font-woff 1y; - ~*application/font-woff 1y; - ~*application/font-woff2 1y; - - # Other - ~*text/x-cross-domain-policy 1w; -} - -expires $expires; diff --git a/containers/nginx/config/h5bp/web_performance/compression.conf b/containers/nginx/config/h5bp/web_performance/compression.conf deleted file mode 100644 index 1f9dc3c..0000000 --- a/containers/nginx/config/h5bp/web_performance/compression.conf +++ /dev/null @@ -1,71 +0,0 @@ -# ---------------------------------------------------------------------- -# | Compression | -# ---------------------------------------------------------------------- - -# https://nginx.org/en/docs/http/ngx_http_gzip_module.html - -# Enable gzip compression. -# Default: off -gzip on; - -# Compression level (1-9). -# 5 is a perfect compromise between size and CPU usage, offering about 75% -# reduction for most ASCII files (almost identical to level 9). -# Default: 1 -gzip_comp_level 5; - -# Don't compress anything that's already small and unlikely to shrink much if at -# all (the default is 20 bytes, which is bad as that usually leads to larger -# files after gzipping). -# Default: 20 -gzip_min_length 256; - -# Compress data even for clients that are connecting to us via proxies, -# identified by the "Via" header (required for CloudFront). -# Default: off -gzip_proxied any; - -# Tell proxies to cache both the gzipped and regular version of a resource -# whenever the client's Accept-Encoding capabilities header varies; -# Avoids the issue where a non-gzip capable client (which is extremely rare -# today) would display gibberish if their proxy gave them the gzipped version. -# Default: off -gzip_vary on; - -# Compress all output labeled with one of the following MIME-types. -# `text/html` is always compressed by gzip module. -# Default: text/html -gzip_types - application/atom+xml - application/geo+json - application/javascript - application/x-javascript - application/json - application/ld+json - application/manifest+json - application/rdf+xml - application/rss+xml - application/vnd.ms-fontobject - application/wasm - application/x-web-app-manifest+json - application/xhtml+xml - application/xml - font/eot - font/otf - font/ttf - image/bmp - image/svg+xml - image/vnd.microsoft.icon - image/x-icon - text/cache-manifest - text/calendar - text/css - text/javascript - text/markdown - text/plain - text/xml - text/vcard - text/vnd.rim.location.xloc - text/vtt - text/x-component - text/x-cross-domain-policy; diff --git a/containers/nginx/config/h5bp/web_performance/content_transformation.conf b/containers/nginx/config/h5bp/web_performance/content_transformation.conf deleted file mode 100644 index 0de6ddc..0000000 --- a/containers/nginx/config/h5bp/web_performance/content_transformation.conf +++ /dev/null @@ -1,29 +0,0 @@ -# ---------------------------------------------------------------------- -# | Content transformation | -# ---------------------------------------------------------------------- - -# Prevent intermediate caches or proxies (such as those used by mobile -# network providers) and browsers data-saving features from modifying -# the website's content using the `cache-control: no-transform` directive. -# -# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control -# https://tools.ietf.org/html/rfc7234#section-5.2.2.4 -# -# (!) Carefully consider the impact on your visitors before disabling -# content transformation. These transformations are performed to -# improve the experience for data- and cost-constrained users -# (e.g. users on a 2G connection). -# -# You can test the effects of content transformation applied by -# Google's Lite Mode by visiting: https://googleweblight.com/i?u=https://www.example.com -# -# https://support.google.com/webmasters/answer/6211428 -# -# (!) If you are using `ngx_pagespeed`, note that disabling this will -# prevent `PageSpeed` from rewriting HTML files, and, if the -# `pagespeed DisableRewriteOnNoTransform` directive isn't set to -# `off`, also from rewriting other resources. -# -# https://developers.google.com/speed/pagespeed/module/configuration#notransform - -add_header Cache-Control "no-transform"; diff --git a/containers/nginx/config/h5bp/web_performance/pre-compressed_content_brotli.conf b/containers/nginx/config/h5bp/web_performance/pre-compressed_content_brotli.conf deleted file mode 100644 index fc8ad5e..0000000 --- a/containers/nginx/config/h5bp/web_performance/pre-compressed_content_brotli.conf +++ /dev/null @@ -1,17 +0,0 @@ -# ---------------------------------------------------------------------- -# | Brotli pre-compressed content | -# ---------------------------------------------------------------------- - -# Serve brotli compressed CSS, JS, HTML, SVG, ICS and JSON files if they exist -# and if the client accepts br encoding. -# -# (!) To make this part relevant, you need to generate encoded files by your -# own. Enabling this part will not auto-generate brotlied files. -# -# Note that some clients (e.g. browsers) require a secure connection to request -# brotli-compressed resources. -# https://www.chromestatus.com/feature/5420797577396224 -# -# https://github.com/eustas/ngx_brotli/#brotli_static - -brotli_static on; diff --git a/containers/nginx/config/h5bp/web_performance/pre-compressed_content_gzip.conf b/containers/nginx/config/h5bp/web_performance/pre-compressed_content_gzip.conf deleted file mode 100644 index fb1c4f5..0000000 --- a/containers/nginx/config/h5bp/web_performance/pre-compressed_content_gzip.conf +++ /dev/null @@ -1,13 +0,0 @@ -# ---------------------------------------------------------------------- -# | GZip pre-compressed content | -# ---------------------------------------------------------------------- - -# Serve gzip compressed CSS, JS, HTML, SVG, ICS, and JSON files if they exist -# and if the client accepts gzip encoding. -# -# (!) To make this part relevant, you need to generate encoded files by your -# own. Enabling this part will not auto-generate gziped files. -# -# https://nginx.org/en/docs/http/ngx_http_gzip_static_module.html - -gzip_static on; diff --git a/containers/nginx/config/mime.types b/containers/nginx/config/mime.types deleted file mode 100644 index f5b666b..0000000 --- a/containers/nginx/config/mime.types +++ /dev/null @@ -1,140 +0,0 @@ -types { - - # Data interchange - - application/atom+xml atom; - application/json json map topojson; - application/ld+json jsonld; - application/rss+xml rss; - # Normalize to standard type. - # https://tools.ietf.org/html/rfc7946#section-12 - application/geo+json geojson; - application/xml xml; - # Normalize to standard type. - # https://tools.ietf.org/html/rfc3870#section-2 - application/rdf+xml rdf; - - - # JavaScript - - # Servers should use text/javascript for JavaScript resources. - # https://html.spec.whatwg.org/multipage/scripting.html#scriptingLanguages - text/javascript js mjs; - application/wasm wasm; - - - # Manifest files - - application/manifest+json webmanifest; - application/x-web-app-manifest+json webapp; - text/cache-manifest appcache; - - - # Media files - - audio/midi mid midi kar; - audio/mp4 aac f4a f4b m4a; - audio/mpeg mp3; - audio/ogg oga ogg opus; - audio/x-realaudio ra; - audio/x-wav wav; - image/apng apng; - image/avif avif; - image/avif-sequence avifs; - image/bmp bmp; - image/gif gif; - image/jpeg jpeg jpg; - image/jxl jxl; - image/jxr jxr hdp wdp; - image/png png; - image/svg+xml svg svgz; - image/tiff tif tiff; - image/vnd.wap.wbmp wbmp; - image/webp webp; - image/x-jng jng; - video/3gpp 3gp 3gpp; - video/mp4 f4p f4v m4v mp4; - video/mpeg mpeg mpg; - video/ogg ogv; - video/quicktime mov; - video/webm webm; - video/x-flv flv; - video/x-mng mng; - video/x-ms-asf asf asx; - video/x-msvideo avi; - - # Serving `.ico` image files with a different media type - # prevents Internet Explorer from displaying then as images: - # https://github.com/h5bp/html5-boilerplate/commit/37b5fec090d00f38de64b591bcddcb205aadf8ee - - image/x-icon cur ico; - - - # Microsoft Office - - application/msword doc; - application/vnd.ms-excel xls; - application/vnd.ms-powerpoint ppt; - application/vnd.openxmlformats-officedocument.wordprocessingml.document docx; - application/vnd.openxmlformats-officedocument.spreadsheetml.sheet xlsx; - application/vnd.openxmlformats-officedocument.presentationml.presentation pptx; - - - # Web fonts - - font/woff woff; - font/woff2 woff2; - application/vnd.ms-fontobject eot; - font/ttf ttf; - font/collection ttc; - font/otf otf; - - - # Other - - application/java-archive ear jar war; - application/mac-binhex40 hqx; - application/octet-stream bin deb dll dmg exe img iso msi msm msp safariextz; - application/pdf pdf; - application/postscript ai eps ps; - application/rtf rtf; - application/vnd.google-earth.kml+xml kml; - application/vnd.google-earth.kmz kmz; - application/vnd.wap.wmlc wmlc; - application/x-7z-compressed 7z; - application/x-bb-appworld bbaw; - application/x-bittorrent torrent; - application/x-chrome-extension crx; - application/x-cocoa cco; - application/x-java-archive-diff jardiff; - application/x-java-jnlp-file jnlp; - application/x-makeself run; - application/x-opera-extension oex; - application/x-perl pl pm; - application/x-pilot pdb prc; - application/x-rar-compressed rar; - application/x-redhat-package-manager rpm; - application/x-sea sea; - application/x-shockwave-flash swf; - application/x-stuffit sit; - application/x-tcl tcl tk; - application/x-x509-ca-cert crt der pem; - application/x-xpinstall xpi; - application/xhtml+xml xhtml; - application/xslt+xml xsl; - application/zip zip; - text/calendar ics; - text/css css; - text/csv csv; - text/html htm html shtml; - text/markdown md markdown; - text/mathml mml; - text/plain txt; - text/vcard vcard vcf; - text/vnd.rim.location.xloc xloc; - text/vnd.sun.j2me.app-descriptor jad; - text/vnd.wap.wml wml; - text/vtt vtt; - text/x-component htc; - -} diff --git a/containers/nginx/config/nginx.conf b/containers/nginx/config/nginx.conf index 271f283..aaeaebd 100644 --- a/containers/nginx/config/nginx.conf +++ b/containers/nginx/config/nginx.conf @@ -1,164 +1,70 @@ -# Configuration File - Nginx Server Configs -# https://nginx.org/en/docs/ -# Run as a unique, less privileged user for security reasons. -# Default: nobody nobody -# https://nginx.org/en/docs/ngx_core_module.html#user -# https://en.wikipedia.org/wiki/Principle_of_least_privilege -user nginx; +user nginx; +worker_processes auto; -# Sets the worker threads to the number of CPU cores available in the system for -# best performance. Should be > the number of CPU cores. -# Maximum number of connections = worker_processes * worker_connections -# Default: 1 -# https://nginx.org/en/docs/ngx_core_module.html#worker_processes -worker_processes auto; +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; -# Maximum number of open files per worker process. -# Should be > worker_connections. -# Default: no limit -# https://nginx.org/en/docs/ngx_core_module.html#worker_rlimit_nofile -worker_rlimit_nofile 8192; -# Provides the configuration file context in which the directives that affect -# connection processing are specified. -# https://nginx.org/en/docs/ngx_core_module.html#events events { - - # If you need more connections than this, you start optimizing your OS. - # That's probably the point at which you hire people who are smarter than you - # as this is *a lot* of requests. - # Should be < worker_rlimit_nofile. - # Default: 512 - # https://nginx.org/en/docs/ngx_core_module.html#worker_connections - worker_connections 8000; - + worker_connections 1024; } -# Log errors and warnings to this file -# This is only used when you don't override it on a `server` level -# Default: logs/error.log error -# https://nginx.org/en/docs/ngx_core_module.html#error_log -error_log /var/log/nginx/error.log warn; - -# The file storing the process ID of the main process -# Default: logs/nginx.pid -# https://nginx.org/en/docs/ngx_core_module.html#pid -pid /var/run/nginx.pid; - -# Include files in the custom.d folder. -# Custom configuration and value files should be placed in the custom.d -# folder. -# The configurations should be disabled by prefixing files with a dot. -include custom.d/*.conf; http { - - # Hide Nginx version information. - include h5bp/security/server_software_information.conf; - - # Specify media (MIME) types for files. - include h5bp/media_types/media_types.conf; - - # Set character encodings. - include h5bp/media_types/character_encodings.conf; - - # Include $http_x_forwarded_for within default format used in log files - # https://nginx.org/en/docs/http/ngx_http_log_module.html#log_format - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - # Log access to this file - # This is only used when you don't override it on a `server` level - # Default: logs/access.log combined - # https://nginx.org/en/docs/http/ngx_http_log_module.html#access_log - access_log /var/log/nginx/access.log main; - - # How long to allow each connection to stay idle. - # Longer values are better for each individual client, particularly for SSL, - # but means that worker connections are tied up longer. - # Default: 75s - # https://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout - keepalive_timeout 20s; - - # Speed up file transfers by using `sendfile()` to copy directly between - # descriptors rather than using `read()`/`write()``. - # For performance reasons, on FreeBSD systems w/ ZFS this option should be - # disabled as ZFS's ARC caches frequently used files in RAM by default. - # Default: off - # https://nginx.org/en/docs/http/ngx_http_core_module.html#sendfile - sendfile on; - - # Don't send out partial frames; this increases throughput since TCP frames - # are filled up before being sent out. - # Default: off - # https://nginx.org/en/docs/http/ngx_http_core_module.html#tcp_nopush - tcp_nopush on; - - # Enable gzip compression. - include h5bp/web_performance/compression.conf; - - # Specify file cache expiration. - include h5bp/web_performance/cache_expiration.conf; - - # Add X-Frame-Options for HTML documents. - # h5bp/security/x-frame-options.conf - map $sent_http_content_type $x_frame_options { - ~*text/html DENY; - } - - # Add Content-Security-Policy for HTML documents. - # h5bp/security/content-security-policy.conf - map $sent_http_content_type $content_security_policy { - ~*text/(html|javascript)|application/pdf|xml "default-src 'self'; base-uri 'none'; form-action 'self'; frame-ancestors 'none'; object-src 'none'; upgrade-insecure-requests"; - } - - # Add Permissions-Policy for HTML documents. - # h5bp/security/permissions-policy.conf - map $sent_http_content_type $permissions_policy { - ~*text/(html|javascript)|application/pdf|xml "accelerometer=(),autoplay=(),camera=(),display-capture=(),document-domain=(),encrypted-media=(),fullscreen=(),geolocation=(),gyroscope=(),magnetometer=(),microphone=(),midi=(),payment=(),picture-in-picture=(),publickey-credentials-get=(),screen-wake-lock=(),sync-xhr=(self),usb=(),web-share=(),xr-spatial-tracking=()"; - } - - # Add Referrer-Policy for HTML documents. - # h5bp/security/referrer-policy.conf - map $sent_http_content_type $referrer_policy { - ~*text/(css|html|javascript)|application\/pdf|xml "strict-origin-when-cross-origin"; - } - - # Add Cross-Origin-Policies for HTML documents. - # h5bp/security/cross-origin-policy.conf - # Cross-Origin-Embedder-Policy - map $sent_http_content_type $coep_policy { - ~*text/(html|javascript)|application/pdf|xml "require-corp"; - } - # Cross-Origin-Opener-Policy - map $sent_http_content_type $coop_policy { - ~*text/(html|javascript)|application/pdf|xml "same-origin"; - } - # Cross-Origin-Resource-Policy - map $sent_http_content_type $corp_policy { - ~*text/(html|javascript)|application/pdf|xml "same-origin"; - } - - # Add Access-Control-Allow-Origin. - # h5bp/cross-origin/requests.conf - map $sent_http_content_type $cors { - # Images - ~*image/ "*"; - - # Web fonts - ~*font/ "*"; - ~*application/vnd.ms-fontobject "*"; - ~*application/x-font-ttf "*"; - ~*application/font-woff "*"; - ~*application/x-font-woff "*"; - ~*application/font-woff2 "*"; - } - - # Include files in the conf.d folder. - # `server` configuration files should be placed in the conf.d folder. - # The configurations should be disabled by prefixing files with a dot. - include conf.d/*.conf; - + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + gzip on; + gzip_comp_level 5; + gzip_min_length 256; + gzip_proxied any; + gzip_vary on; + gzip_types + application/atom+xml + application/geo+json + application/javascript + application/x-javascript + application/json + application/ld+json + application/manifest+json + application/rdf+xml + application/rss+xml + application/vnd.ms-fontobject + application/wasm + application/x-web-app-manifest+json + application/xhtml+xml + application/xml + font/eot + font/otf + font/ttf + image/bmp + image/svg+xml + image/vnd.microsoft.icon + image/x-icon + text/cache-manifest + text/calendar + text/css + text/javascript + text/markdown + text/plain + text/xml + text/vcard + text/vnd.rim.location.xloc + text/vtt + text/x-component + text/x-cross-domain-policy; + + include /etc/nginx/conf.d/*.conf; } diff --git a/containers/nginx/config/templates/default.conf.template b/containers/nginx/config/templates/default.conf.template index 82516d2..8de7059 100644 --- a/containers/nginx/config/templates/default.conf.template +++ b/containers/nginx/config/templates/default.conf.template @@ -1,36 +1,35 @@ server { - listen [::]:80; - listen 80; + server_tokens off; - server_name www.${APP_DOMAIN}; + listen 80; + listen [::]:80; + server_name _; + root /var/www/html/public; - return 301 $scheme://${APP_DOMAIN}$request_uri; -} + add_header X-Frame-Options "SAMEORIGIN"; + add_header X-Content-Type-Options "nosniff"; -server { - # listen [::]:80 accept_filter=httpready; # for FreeBSD - # listen 80 accept_filter=httpready; # for FreeBSD - listen [::]:80; - listen 80; + index index.php; - # The host name to respond to - server_name ${APP_DOMAIN}; + charset utf-8; - # Path for static files - root /var/www/html/public; + location / { + try_files $uri $uri/ /index.php?$query_string; + } - index index.php; + location = /favicon.ico { access_log off; log_not_found off; } + location = /robots.txt { access_log off; log_not_found off; } - location / { - try_files $uri $uri/ /index.php?$query_string; - } + location ~ \.php$ { + fastcgi_pass ${FPM_URL}:${FPM_PORT}; + fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; + include fastcgi_params; + } - location ~ \.php$ { - fastcgi_pass ${FPM_URL}:${FPM_PORT}; - fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name; - include fastcgi_params; - } + location ~ /\.(?!well-known).* { + deny all; + } - # Include the basic h5bp config set - include h5bp/basic.conf; + error_page 403 /index.php; + error_page 404 /index.php; } diff --git a/containers/nginx/entrypoint.sh b/containers/nginx/entrypoint.sh new file mode 100644 index 0000000..2dd0f97 --- /dev/null +++ b/containers/nginx/entrypoint.sh @@ -0,0 +1,5 @@ +#!/usr/bin/env sh + +set -e + +wait-for "${FPM_URL:?Missing FPM_URL}:${FPM_PORT:?Missing FPM_PORT}" -t 60 diff --git a/containers/nginx/start.sh b/containers/nginx/start.sh deleted file mode 100644 index 90b25e4..0000000 --- a/containers/nginx/start.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/usr/bin/env sh -set -e - -# This ensures the command "nginx" waits, while everything else runs without delays. -if [ "$1" = "nginx" ]; then - echo "Wait for PHP backend to come up..." - wait-for -t 30 "${FPM_URL}:${FPM_PORT}" -fi -exec /docker-entrypoint.sh "$@" diff --git a/containers/php/Dockerfile b/containers/php/Dockerfile index 7de008e..55d3656 100644 --- a/containers/php/Dockerfile +++ b/containers/php/Dockerfile @@ -1,28 +1,57 @@ -FROM php:8.1.19-fpm-alpine as base -WORKDIR /var/www/html/ -COPY --from=mlocati/php-extension-installer:2.1.49 /usr/bin/install-php-extensions /usr/local/bin/ -RUN install-php-extensions \ - opcache \ +# base image for all containers +FROM php:8.3.3-fpm-alpine as base +WORKDIR /var/www/html +# install extensions and packages +COPY --from=mlocati/php-extension-installer:2.2.2 /usr/bin/install-php-extensions /usr/local/sbin/ +RUN apk add --no-cache \ + netcat-openbsd \ + postgresql15-client \ + procps \ + && install-php-extensions \ pcntl \ pdo_pgsql \ pgsql \ redis \ zip -COPY --from=composer:2.5.8 /usr/bin/composer /usr/local/bin/composer +COPY --from=composer:2.7.1 /usr/bin/composer /usr/local/bin/composer +FROM base as development +# install xdebug and additional packages +RUN apk add --no-cache \ + bash \ + git \ + shadow \ + sudo \ + && install-php-extensions \ + xdebug \ + # configuring php and passwordless sudo + && mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini" \ + && echo "ALL ALL=(ALL:ALL) NOPASSWD: ALL" > "/etc/sudoers.d/password_less_sudo" +ADD --chmod=777 \ + --checksum=sha256:206a8f9b2177703fc5aa924d85ad6c72e82413e2d09635b4c9c82a1b65b5b3d5 \ + https://github.com/eficode/wait-for/releases/download/v2.2.4/wait-for /usr/local/bin/wait-for +COPY --chmod=777 containers/php/entrypoint.sh /usr/local/sbin/entrypoint +ENTRYPOINT ["entrypoint"] +CMD ["php-fpm"] +ARG UID +ARG GID +RUN usermod -u "$UID" www-data \ + && groupmod -g "$GID" www-data +ENV XDEBUG_MODE=develop,debug,coverage +ENV XDEBUG_CONFIG="client_host=host.docker.internal" +USER www-data + +# vendor files FROM base as vendor COPY composer.json . COPY composer.lock . -RUN composer check-platform-reqs \ - && composer i --no-scripts --no-dev +RUN composer i --no-scripts --no-dev --ignore-platform-reqs -FROM base as vendor_test -COPY composer.json . -COPY composer.lock . -COPY --from=vendor /var/www/html/vendor /var/www/html/vendor -RUN composer check-platform-reqs \ - && composer i --no-scripts +# vendor dev files +FROM vendor as vendor_test +RUN composer i --no-scripts --ignore-platform-reqs +# all application files FROM base as application COPY app ./app COPY bootstrap ./bootstrap @@ -37,42 +66,46 @@ COPY composer.json . COPY composer.lock . FROM base as testing -ENV APP_KEY=base64:Y6qJHTnzxMzrqw3wrm/jMsWACRWTykYARWxw9mkPqC8= -ENV DB_CONNECTION=sqlite -ENV DB_DATABASE=:memory: RUN install-php-extensions xdebug COPY --from=application /var/www/html /var/www/html COPY --from=vendor_test /var/www/html/vendor /var/www/html/vendor -RUN composer run post-autoload-dump --no-ansi --no-plugins COPY tests ./tests COPY phpunit.xml . -RUN COMPOSER_ALLOW_SUPERUSER=1 composer dump-autoload \ +RUN composer check-platform-reqs \ + && composer dump-autoload \ && chown -R www-data:www-data storage USER www-data -RUN XDEBUG_MODE=coverage php artisan test --parallel --coverage-cobertura coverage.cobertura.xml +ENV XDEBUG_MODE=coverage +CMD ["php", "artisan", "test", "--coverage-cobertura", "coverage.cobertura.xml"] FROM base as production -RUN apk add --no-cache \ - fcgiwrap \ +# container php extensions, packages and using official production configuration +RUN install-php-extensions \ + opcache \ + && apk add --no-cache \ netcat-openbsd \ procps \ - && echo "pm.status_path = /status" >> /usr/local/etc/php-fpm.d/zz-docker.conf \ && echo "access.log = /dev/null" >> /usr/local/etc/php-fpm.d/zz-docker.conf \ - && mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" + && mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" \ + && echo "* * * * * cd /var/www/html && php artisan schedule >> /dev/null 2>&1" > /etc/crontabs/www-data +# php configuration COPY containers/php/conf.d /usr/local/etc/php/conf.d -ADD https://raw.githubusercontent.com/renatomefi/php-fpm-healthcheck/v0.5.0/php-fpm-healthcheck /usr/local/bin/ -ADD https://github.com/eficode/wait-for/releases/download/v2.2.4/wait-for /usr/local/bin/ -COPY containers/php/entrypoint.sh /usr/local/bin/entrypoint +# additional binaries and entrypoint +ADD --chmod=777 \ + --checksum=sha256:206a8f9b2177703fc5aa924d85ad6c72e82413e2d09635b4c9c82a1b65b5b3d5 \ + https://github.com/eficode/wait-for/releases/download/v2.2.4/wait-for /usr/local/bin/wait-for +COPY --chmod=777 containers/php/entrypoint.sh /usr/local/sbin/entrypoint +ENTRYPOINT ["entrypoint"] +CMD ["php-fpm"] +# container ready, copy over application and do software bootstrap COPY --from=application /var/www/html /var/www/html COPY --from=vendor /var/www/html/vendor /var/www/html/vendor -RUN chmod u+x /usr/local/bin/php-fpm-healthcheck \ - && chmod u+x /usr/local/bin/wait-for \ - && chmod u+x /usr/local/bin/entrypoint \ - && chown -R www-data:www-data storage \ - && COMPOSER_ALLOW_SUPERUSER=1 composer dump-autoload --optimize \ +ARG COMPOSER_ALLOW_SUPERUSER=1 +RUN chown -R www-data:www-data storage \ + && composer dump-autoload --optimize \ && echo -n "opcache.max_accelerated_files=" >> "$PHP_INI_DIR/conf.d/opcache.ini" \ && echo $(find . -name "*.php" | wc -l | awk '{print (int($1/1000)+2)*1000}') >> "$PHP_INI_DIR/conf.d/opcache.ini" \ + && composer check-platform-reqs \ && rm /usr/local/bin/composer \ - && rm /usr/local/bin/install-php-extensions + && rm /usr/local/sbin/install-php-extensions VOLUME ["/var/www/html/bootstrap", "/var/www/html/storage"] -ENTRYPOINT ["entrypoint"] diff --git a/containers/php/entrypoint.sh b/containers/php/entrypoint.sh index 45613d6..94a3f49 100644 --- a/containers/php/entrypoint.sh +++ b/containers/php/entrypoint.sh @@ -1,20 +1,19 @@ #!/usr/bin/env sh -set -e -ROLE=${ROLE:-app} +set -e -if [ -n "$1" ]; then - echo "Executing $1" - exec "$@" -else - if [ "$ROLE" = "app" ]; then - exec php-fpm - elif [ "$ROLE" = "setup" ]; then - php artisan app:setup - elif [ "$ROLE" = "scheduler" ]; then - su -s '/bin/sh' -c 'php artisan schedule:work --quiet' www-data +# Bootstrap application +if [ "$1" = 'php-fpm' ]; then + wait-for "${DB_HOST:?Missing DB_HOST}:${DB_PORT:?Missing DB_PORT}" -t 60 + if [ "$APP_ENV" = "local" ]; then + composer i else - echo "Unknown role '$ROLE'" - exit 1 + php artisan optimize fi + php artisan migrate --force + php artisan storage:link + php artisan app:geoip:download + chown -R www-data:www-data storage fi + +exec "$@" diff --git a/deploy/docker-compose/.env.example b/deploy/docker-compose/.env.example index 71b54fd..e74736a 100644 --- a/deploy/docker-compose/.env.example +++ b/deploy/docker-compose/.env.example @@ -15,15 +15,11 @@ DB_DATABASE=phonehome DB_USERNAME=phonehome DB_PASSWORD=phonehome -BROADCAST_DRIVER=redis -CACHE_DRIVER=redis +BROADCAST_DRIVER=log +CACHE_DRIVER=file FILESYSTEM_DISK=local -QUEUE_CONNECTION=redis -SESSION_DRIVER=redis +QUEUE_CONNECTION=sync +SESSION_DRIVER=file SESSION_LIFETIME=120 -REDIS_HOST=redis -REDIS_PASSWORD=null -REDIS_PORT=6379 - GEOIP_TOKEN= diff --git a/deploy/docker-compose/docker-compose.yml b/deploy/docker-compose/docker-compose.yml index 332ddd4..f8f2616 100644 --- a/deploy/docker-compose/docker-compose.yml +++ b/deploy/docker-compose/docker-compose.yml @@ -1,13 +1,7 @@ -name: phone-home +name: phonehome-prod services: - redis: - image: redis:6.2.12-alpine - healthcheck: - test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ] - volumes: - - redis:/data database: - image: postgres:14.9-alpine + image: postgres:14.11-alpine healthcheck: test: [ "CMD", "pg_isready", "-q", "-d", "phonehome", "-U", "phonehome" ] volumes: @@ -16,65 +10,26 @@ services: POSTGRES_DB: phonehome POSTGRES_USER: phonehome POSTGRES_PASSWORD: phonehome - setup: - image: ghcr.io/nethserver/phonehome-server-app:${TAG:-latest} - depends_on: - - database - - redis - volumes: - - public:/app/public - - bootstrap:/var/www/html/bootstrap - - storage:/var/www/html/storage - secrets: - - source: env_file - target: /var/www/html/.env - environment: - ROLE: "setup" app: - image: ghcr.io/nethserver/phonehome-server-app:${TAG:-latest} - healthcheck: - test: [ "CMD", "php-fpm-healthcheck" ] - depends_on: - setup: - condition: service_completed_successfully + image: ghcr.io/nethserver/phonehome-server-app:latest volumes: - bootstrap:/var/www/html/bootstrap - storage:/var/www/html/storage - secrets: - - source: env_file - target: /var/www/html/.env + env_file: + - .env scheduler: - image: ghcr.io/nethserver/phonehome-server-app:${TAG:-latest} - depends_on: - setup: - condition: service_completed_successfully - stop_signal: SIGKILL - volumes: - - bootstrap:/var/www/html/bootstrap - - storage:/var/www/html/storage - secrets: - - source: env_file - target: /var/www/html/.env - environment: - ROLE: "scheduler" + extends: + service: app + command: [ "crond", "-f", "-l", "2" ] web: - image: ghcr.io/nethserver/phonehome-server-web:${TAG:-latest} + image: ghcr.io/nethserver/phonehome-server-web:latest healthcheck: test: [ "CMD", "curl", "--fail", "--silent", "--output", "/dev/null", "http://localhost/status" ] - volumes: - - public:/var/www/html/public:ro environment: - APP_DOMAIN: localhost FPM_URL: app FPM_PORT: 9000 volumes: - redis: {} - database: {} - public: {} - bootstrap: {} - storage: {} - -secrets: - env_file: - file: .env + database: { } + bootstrap: { } + storage: { } diff --git a/deploy/ns8/Dockerfile b/deploy/ns8/Dockerfile index 72b12f5..4f02de1 100644 --- a/deploy/ns8/Dockerfile +++ b/deploy/ns8/Dockerfile @@ -2,7 +2,8 @@ FROM docker.io/node:20.11.1-alpine as node_build WORKDIR /app COPY ui/package.json . COPY ui/yarn.lock . -RUN yarn +RUN --mount=type=cache,target=/usr/local/share/.cache \ + yarn COPY ui/.browserslistrc . COPY ui/.eslintrc.js . COPY ui/babel.config.js . @@ -13,16 +14,9 @@ ENV NODE_OPTIONS=--openssl-legacy-provider RUN yarn build FROM scratch as production -COPY imageroot /imageroot +COPY --link imageroot /imageroot COPY --from=node_build /app/dist /ui LABEL org.nethserver.authorizations="traefik@node:routeadm" LABEL org.nethserver.tcp-ports-demand="1" LABEL org.nethserver.rootfull="0" -ARG PHONEHOME_TAG=latest -ARG PHONEHOME_SERVER_APP=ghcr.io/nethserver/phonehome-server-app -ARG PHONEHOME_SERVER_WEB=ghcr.io/nethserver/phonehome-server-web -LABEL org.nethserver.images="docker.io/postgres:14.9-alpine \ - docker.io/redis:6.2.12-alpine \ - $PHONEHOME_SERVER_APP:$PHONEHOME_TAG \ - $PHONEHOME_SERVER_WEB:$PHONEHOME_TAG" ENTRYPOINT ["/"] diff --git a/deploy/ns8/build-images.sh b/deploy/ns8/build-images.sh deleted file mode 100755 index 121f88b..0000000 --- a/deploy/ns8/build-images.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env sh - -# -# Copyright (C) 2022 Nethesis S.r.l. -# SPDX-License-Identifier: GPL-3.0-or-later -# - -set -e - -# Set up all variables needed to build the arguments -tags=${TAGS:-ghcr.io/nethserver/phonehome-server:latest} -labels=${LABELS:-} -args=${ARGS:-} - -for tag in $tags; do - set -- "$@" --tag="$tag" -done - -for label in $labels; do - set -- "$@" --label="$label" -done - -for arg in $args; do - set -- "$@" --build-arg="$arg" -done - -# Execute the buildah build command with the additional arguments given above -buildah build \ - --force-rm \ - --jobs "$(nproc)" \ - --layers \ - --file Dockerfile \ - --target production \ - "$@" \ - . - -# If it's run locally, print the next commands to publish the images tagged -if [ -z "${CI}" ]; then - echo "Manually push the images with:" - for tag in $tags; do - echo "podman push $tag" - done -fi diff --git a/deploy/ns8/imageroot/systemd/user/app.service b/deploy/ns8/imageroot/systemd/user/app.service index 76616c2..6ff3072 100644 --- a/deploy/ns8/imageroot/systemd/user/app.service +++ b/deploy/ns8/imageroot/systemd/user/app.service @@ -20,8 +20,6 @@ ExecStart=/usr/bin/podman run \ --volume bootstrap:/var/www/html/bootstrap \ --volume storage:/var/www/html/storage \ --env-file %S/state/environment \ - --env REDIS_HOST=${PHONEHOME_REDIS_HOST} \ - --env REDIS_PASSWORD=${PHONEHOME_REDIS_PASSWORD} \ ${PHONEHOME_SERVER_APP_IMAGE} ExecStop=/usr/bin/podman stop --ignore --cidfile %t/app.ctr-id -t 10 ExecStopPost=/usr/bin/podman rm --ignore -f --cidfile %t/app.ctr-id diff --git a/docker-bake.hcl b/docker-bake.hcl index ef1a22f..738696b 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -1,53 +1,53 @@ -target "base" { - target = "production" - context = "." - output = ["type=docker"] -} - -target "app" { - inherits = ["base"] +target "app-production" { dockerfile = "containers/php/Dockerfile" + target = "production" + tags = [ + "ghcr.io/nethserver/phonehome-server-app:latest" + ] cache-from = [ - "type=registry,ref=ghcr.io/nethserver/phonehome-server-app:master-cache" + "type=gha" ] -} - -target "app-develop" { - inherits = ["app"] - tags = [ - "ghcr.io/nethserver/phonehome-server-app:latest" + output = [ + "type=docker" ] } -target "web" { - inherits = ["base"] +target "web-production" { dockerfile = "containers/nginx/Dockerfile" + target = "production" + tags = [ + "ghcr.io/nethserver/phonehome-server-web:latest" + ] cache-from = [ - "type=registry,ref=ghcr.io/nethserver/phonehome-server-web:master-cache" + "type=gha" ] -} - -target "web-develop" { - inherits = ["web"] - tags = [ - "ghcr.io/nethserver/phonehome-server-web:latest" + output = [ + "type=docker" ] } -target "testing" { - inherits = ["app"] - target = "testing" - output = [""] -} - -group "develop" { - targets = ["app-develop", "web-develop"] +target "ns8" { + dockerfile = "Dockerfile" + context = "deploy/ns8" + target = "production" + tags = [ + "ghcr.io/nethserver/phonehome-server:latest" + ] + labels = { + "org.nethserver.images" : "docker.io/postgres:14.9-alpine docker.io/redis:6.2.12-alpine ${target.app-production.tags[0]} ${target.web-production.tags[0]}" + } + cache-from = [ + "type=gha" + ] + output = [ + "type=docker" + ] } -group "release" { - targets = ["app", "web"] +group "deploy" { + targets = ["default", "ns8"] } group "default" { - targets = ["develop"] + targets = ["app-production", "web-production"] } diff --git a/docker-compose.yml b/docker-compose.yml index 10f9707..633b0d4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,65 +1,73 @@ -# For more information: https://laravel.com/docs/sail -version: '3' +name: phonehome-development services: - laravel.test: + database: + image: postgres:14.11-alpine + healthcheck: + test: [ "CMD", "pg_isready", "-q", "-d", $DB_DATABASE, "-U", $DB_USERNAME ] + ports: + - "5432:5432" + volumes: + - database:/var/lib/postgresql/data + environment: + POSTGRES_DB: $DB_DATABASE + POSTGRES_USER: $DB_USERNAME + POSTGRES_PASSWORD: $DB_PASSWORD + app: + pull_policy: never build: - context: ./vendor/laravel/sail/runtimes/8.1 - dockerfile: Dockerfile + dockerfile: containers/php/Dockerfile + target: development args: - WWWGROUP: '${WWWGROUP}' - image: sail-8.1/app + UID: ${UID:-1000} + GID: ${GID:-1000} + hostname: app extra_hosts: - 'host.docker.internal:host-gateway' - ports: - - '${APP_PORT:-80}:80' - - '${VITE_PORT:-5173}:${VITE_PORT:-5173}' - environment: - WWWUSER: '${WWWUSER}' - LARAVEL_SAIL: 1 - XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}' - XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}' - volumes: - - '.:/var/www/html' - networks: - - sail + volumes: &app-volumes + - .:/var/www/html + - home:/home/www-data + env_file: + - .env + web: + pull_policy: never + build: + dockerfile: containers/nginx/Dockerfile depends_on: - - pgsql - - redis - pgsql: - image: postgres:14.9-alpine + - app + volumes: *app-volumes ports: - - '${FORWARD_DB_PORT:-5432}:5432' + - "80:80" environment: - PGPASSWORD: '${DB_PASSWORD:-secret}' - POSTGRES_DB: '${DB_DATABASE}' - POSTGRES_USER: '${DB_USERNAME}' - POSTGRES_PASSWORD: '${DB_PASSWORD:-secret}' - volumes: - - 'sail-pgsql:/var/lib/postgresql/data' - - './vendor/laravel/sail/database/pgsql/create-testing-database.sql:/docker-entrypoint-initdb.d/10-create-testing-database.sql' - networks: - - sail - healthcheck: - test: ["CMD", "pg_isready", "-q", "-d", "${DB_DATABASE}", "-U", "${DB_USERNAME}"] - retries: 3 - timeout: 5s - redis: - image: redis:6.2.12-alpine + FPM_URL: app + FPM_PORT: 9000 + + adminer: + image: adminer:4.8.1 ports: - - '${FORWARD_REDIS_PORT:-6379}:6379' - volumes: - - 'sail-redis:/data' - networks: - - sail - healthcheck: - test: ["CMD", "redis-cli", "ping"] - retries: 3 - timeout: 5s -networks: - sail: - driver: bridge + - "8080:8080" + environment: + ADMINER_DEFAULT_SERVER: database + + testing: + profiles: + - testing + pull_policy: never + build: + dockerfile: containers/php/Dockerfile + target: testing + depends_on: + - database + secrets: + - source: env_file + target: /var/www/html/.env + environment: + APP_ENV: testing + APP_KEY: base64:jobMaruKa1iNGS74JK7PGywi5zGWdgIo0HoMG0B+hrY= + volumes: - sail-pgsql: - driver: local - sail-redis: - driver: local + database: { } + home: { } + +secrets: + env_file: + file: .env diff --git a/routes/web.php b/routes/web.php index 608b94d..7832b5a 100644 --- a/routes/web.php +++ b/routes/web.php @@ -19,6 +19,5 @@ }); Route::post('/', CompatibilityController::class) - ->name('installation.store') ->withoutMiddleware('web') ->middleware('api'); diff --git a/tests/Feature/CompatibilityTest.php b/tests/Feature/CompatibilityTest.php index 6530682..7a7b162 100644 --- a/tests/Feature/CompatibilityTest.php +++ b/tests/Feature/CompatibilityTest.php @@ -50,7 +50,6 @@ }); $installation = Installation::factory()->make(); - /** @var Tests\TestCase $this */ $this->postJson( '/', [ @@ -76,7 +75,6 @@ $country->name = $installation->country->name; $country->isoCode = $installation->country->code; - /** @var Tests\TestCase $this */ $this->mock( GeoIpLocator::class, fn (MockInterface $mock) => $mock->shouldReceive('locate') @@ -108,7 +106,6 @@ $country->name = 'Italy'; $country->isoCode = 'IT'; - /** @var Tests\TestCase $this */ $this->mock( GeoIpLocator::class, fn (MockInterface $mock) => $mock->shouldReceive('locate') @@ -305,7 +302,6 @@ $country->name = 'Italy'; $country->isoCode = 'IT'; - /** @var Tests\TestCase $this */ $this->mock( GeoIpLocator::class, fn (MockInterface $mock) => $mock->shouldReceive('locate') @@ -343,7 +339,6 @@ }); $installation = Installation::factory()->make(); - /** @var Tests\TestCase $this */ $this->postJson( '/', [ @@ -362,7 +357,6 @@ ]); $installation = Installation::factory()->make(); - /** @var Tests\TestCase $this */ $this->postJson( '/', [