├── .dockerignore ├── .env.example ├── .github └── workflows │ └── push.yml ├── .gitignore ├── README.md ├── build ├── Dockerfile ├── bin │ ├── wait_for_mysql │ └── wait_for_redis ├── docker-compose.local.yml ├── docker-compose.test.yml ├── docker-entrypoint └── kubernetes.yaml ├── config ├── apache │ └── vhost.conf ├── php │ └── php.ini └── supervisor │ └── supervisord.conf ├── dock └── src ├── .gitignore ├── app ├── Console │ ├── Commands │ │ └── IncrementCounter.php │ └── Kernel.php ├── Exceptions │ └── Handler.php ├── Http │ ├── Controllers │ │ └── Controller.php │ ├── Kernel.php │ └── Middleware │ │ ├── Authenticate.php │ │ ├── EncryptCookies.php │ │ ├── PreventRequestsDuringMaintenance.php │ │ ├── RedirectIfAuthenticated.php │ │ ├── TrimStrings.php │ │ ├── TrustHosts.php │ │ ├── TrustProxies.php │ │ └── VerifyCsrfToken.php ├── Jobs │ └── IncrementCounter.php ├── Models │ └── User.php └── Providers │ ├── AppServiceProvider.php │ ├── AuthServiceProvider.php │ ├── BroadcastServiceProvider.php │ ├── EventServiceProvider.php │ ├── HorizonServiceProvider.php │ └── RouteServiceProvider.php ├── artisan ├── bootstrap ├── app.php └── cache │ └── .gitignore ├── composer.json ├── composer.lock ├── config ├── app.php ├── auth.php ├── broadcasting.php ├── cache.php ├── cors.php ├── database.php ├── filesystems.php ├── hashing.php ├── horizon.php ├── logging.php ├── mail.php ├── queue.php ├── services.php ├── session.php └── view.php ├── database ├── .gitignore ├── factories │ └── UserFactory.php ├── migrations │ ├── 2014_10_12_000000_create_users_table.php │ ├── 2014_10_12_100000_create_password_resets_table.php │ └── 2019_08_19_000000_create_failed_jobs_table.php └── seeders │ └── DatabaseSeeder.php ├── package.json ├── phpunit.xml ├── public ├── .htaccess ├── favicon.ico ├── index.php ├── robots.txt ├── vendor │ └── horizon │ │ ├── app-dark.css │ │ ├── app.css │ │ ├── app.js │ │ ├── img │ │ ├── favicon.png │ │ ├── horizon.svg │ │ └── sprite.svg │ │ └── mix-manifest.json └── web.config ├── resources ├── css │ └── app.css ├── js │ ├── app.js │ └── bootstrap.js ├── lang │ └── en │ │ ├── auth.php │ │ ├── pagination.php │ │ ├── passwords.php │ │ └── validation.php └── views │ ├── status.blade.php │ └── welcome.blade.php ├── routes ├── api.php ├── channels.php ├── console.php └── web.php ├── server.php ├── storage ├── app │ ├── .gitignore │ └── public │ │ └── .gitignore ├── framework │ ├── .gitignore │ ├── cache │ │ ├── .gitignore │ │ └── data │ │ │ └── .gitignore │ ├── sessions │ │ └── .gitignore │ ├── testing │ │ └── .gitignore │ └── views │ │ └── .gitignore └── logs │ └── .gitignore ├── tests ├── CreatesApplication.php ├── Feature │ └── ExampleTest.php ├── TestCase.php └── Unit │ └── ExampleTest.php └── webpack.mix.js /.dockerignore: -------------------------------------------------------------------------------- 1 | # Laravel 2 | src/bootstrap/cache/* 3 | src/storage/app/* 4 | src/storage/framework/cache/* 5 | src/storage/framework/sessions/* 6 | src/storage/framework/testing/* 7 | src/storage/framework/views/* 8 | src/storage/logs/* 9 | 10 | # etc. 11 | **/.env 12 | **/.git 13 | **/*node_modules 14 | **/.DS_Store -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | APP_ID=laraveldock 2 | KUBERNETES_CONTEXT= 3 | TZ=UTC 4 | 5 | REGISTRY=ghcr.io 6 | REGISTRY_USER= 7 | REGISTRY_PASSWORD= 8 | 9 | HOST_PORT_HTTP= 10 | HOST_PORT_HTTPS= 11 | HOST_PORT_DB= 12 | HOST_PORT_REDIS= 13 | 14 | APP_NAME=Laravel 15 | APP_ENV=local 16 | APP_KEY= 17 | APP_DEBUG=true 18 | APP_URL=http://localhost 19 | 20 | LOG_CHANNEL=stack 21 | LOG_LEVEL=debug 22 | 23 | DB_CONNECTION=mysql 24 | DB_HOST=db 25 | DB_PORT=3306 26 | DB_DATABASE=laraveldock 27 | DB_USERNAME=root 28 | DB_PASSWORD=secret 29 | 30 | BROADCAST_DRIVER=log 31 | CACHE_DRIVER=redis 32 | FILESYSTEM_DRIVER=local 33 | QUEUE_CONNECTION=redis 34 | SESSION_DRIVER=redis 35 | SESSION_LIFETIME=120 36 | 37 | MEMCACHED_HOST=127.0.0.1 38 | 39 | REDIS_HOST=redis 40 | REDIS_PASSWORD=rediz 41 | REDIS_PORT=6379 42 | 43 | MAIL_MAILER=smtp 44 | MAIL_HOST=mailhog 45 | MAIL_PORT=1025 46 | MAIL_USERNAME=null 47 | MAIL_PASSWORD=null 48 | MAIL_ENCRYPTION=null 49 | MAIL_FROM_ADDRESS=null 50 | MAIL_FROM_NAME="${APP_NAME}" 51 | 52 | AWS_ACCESS_KEY_ID= 53 | AWS_SECRET_ACCESS_KEY= 54 | AWS_DEFAULT_REGION=us-east-1 55 | AWS_BUCKET= 56 | AWS_USE_PATH_STYLE_ENDPOINT=false 57 | 58 | PUSHER_APP_ID= 59 | PUSHER_APP_KEY= 60 | PUSHER_APP_SECRET= 61 | PUSHER_APP_CLUSTER=mt1 62 | 63 | MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" 64 | MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" 65 | -------------------------------------------------------------------------------- /.github/workflows/push.yml: -------------------------------------------------------------------------------- 1 | name: Build and Test 2 | on: push 3 | jobs: 4 | build: 5 | name: Build 6 | runs-on: ubuntu-latest 7 | timeout-minutes: 60 8 | steps: 9 | - uses: actions/checkout@v2 10 | - name: Build image 11 | run: ./dock build app 12 | - name: Start app 13 | run: | 14 | ./dock up 15 | ./dock exec wait_for_mysql 16 | ./dock exec wait_for_redis 17 | ./dock exec php artisan migrate 18 | - name: Run PHPUnit 19 | run: ./dock test 20 | - name: Show Laravel log 21 | if: always() 22 | run: ./dock exec "cat storage/logs/laravel.log" 23 | - name: Publish image 24 | if: github.ref == 'refs/heads/main' || contains(github.event.head_commit.message, '/publish') 25 | run: | 26 | BRANCH=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,') 27 | COMMIT=$(echo "${{ github.sha }}" | cut -c1-7) 28 | IMAGE="ghcr.io/jarnovanleeuwen/laravel-dock:${BRANCH}-${COMMIT}" 29 | echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin 30 | docker tag app ${IMAGE} 31 | docker push ${IMAGE} 32 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/ 2 | /.env 3 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build and Test](https://github.com/jarnovanleeuwen/laravel-dock/actions/workflows/push.yml/badge.svg)](https://github.com/jarnovanleeuwen/laravel-dock/actions/workflows/push.yml) 2 | 3 | Learning the concepts of [Docker](https://www.docker.com/), I created an example Laravel application using Docker's best architectural and security practices. The boilerplate code in this repository provides: 4 | 5 | - Good practices on security (not running as root, no passwordless databases, no unnecessary file permissions). 6 | - Using official Apache, PHP 8, MySQL 8 and Redis 6 images. 7 | - A single code base for **development and production environments**. 8 | - A single `.env` configuration file. 9 | - A slim `Dockerfile` using only **official images**. 10 | - Tests structured for your CI/CD pipeline. 11 | - A convenient binary providing `up`, `artisan`, `exec`, `push`, and even `deploy` commands. 12 | - Deployments to **Kubernetes** using the commit hash for easy rollbacks or staging. 13 | - Built-in support for Laravel's key concepts: **scheduling, queues, cache etc.** 14 | - Built-in Laravel Horizon for managing queue workers through configuration. 15 | - All configuration in source control (e.g. virtual hosts, OPcache, InnoDB parameters). 16 | - Integrated with **GitHub Actions** for automated testing and publishing of images. 17 | 18 | # Installation 19 | 20 | *Docker Engine version 18.06.0 or higher is required.* 21 | 22 | - Install [Docker Desktop for Mac](https://hub.docker.com/editions/community/docker-ce-desktop-mac) (or the equivalent for your operating system) 23 | - Clone this repository 24 | - Copy `.env.example` to `.env` and edit the file to match your environment. 25 | - Run `./dock up` 26 | - Run `./dock exec composer install` 27 | - Run `./dock artisan migrate` 28 | - Visit http://localhost 29 | 30 | The application will show a status page that can be used to help you understand how the cache, scheduler and queue work together. When the scheduler is running, it will dispatch a job every minute that is being processed immediately when the queue (Horizon) is running. Example output: 31 | 32 | ``` 33 | Database Driver mysql 34 | Database Server db:3306 35 | Cache Driver redis 36 | Queue Driver redis 37 | Cache Test 11:21:50 (TTL: 1 minute) 38 | Scheduler Test 2 jobs dispatched 39 | Queue Test 2 jobs handled 40 | ``` 41 | 42 | # Usage 43 | 44 | The stack can be managed through the `dock ` command-line executable. It supports the following commands. 45 | 46 | | Command | Description | 47 | |---------|-------------| 48 | | `up` | Start the local stack (webserver, database) for development. | 49 | | `down` | Stop the local stack. | 50 | | `restart` | Restart the local stack. | 51 | | `scheduler` | Start Laravel's scheduler daemon. | 52 | | `queue` | Start Laravel Horizon (queue workers). | 53 | | `tail` | Tail and follow the Laravel logs. | 54 | | `build ` | Build and tag an image ready for production. | 55 | | `push ` | Push the latest image to the container registry defined in `REGISTRY`. | 56 | | `deploy ` | Deploy to Kubernetes | 57 | | `exec [...]` | Run arbitrary commands inside the running application container. For example: `dock exec bash` to open an interactive shell in the running app container. | 58 | | `kubectl [...]` | Run `kubectl` with the context defined in `KUBERNETES_CONTEXT`. | 59 | | `test [...]` | Run `phpunit` inside the running application container. For example: `dock test --filter ExampleTest`. | 60 | | `artisan [...]` | Run `artisan` inside the running application container. For example: `dock artisan tinker`. | 61 | | `` | Will be passed to `docker-compose`. For example: `dock ps`. | 62 | 63 | By default, Apache binds to port 80, MySQL to port 3306 and Redis to port 6379. This can be changed by modifying `HOST_PORT_HTTP`, `HOST_PORT_HTTPS`, `HOST_PORT_DB` or `HOST_PORT_REDIS`. 64 | 65 | # Kubernetes 66 | 67 | You can deploy the Laravel application, including MySQL, Redis, Horizon and a scheduler by applying the [`kubernetes.yaml`](https://github.com/jarnovanleeuwen/laravel-dock/blob/main/build/kubernetes.yaml) config. The example assumes that you are using external (managed) services for MySQL and Redis, but this can be modified to run your own containers using persistent volumes. 68 | 69 | First, create secrets for the Docker registry and application keys and passwords. 70 | ```sh 71 | ./dock kubectl create secret docker-registry regcred --docker-server= --docker-username= --docker-password= 72 | ./dock kubectl create secret generic app-secrets --from-literal=APP_KEY='<256 bit key>' --from-literal=DB_PASSWORD='' --from-literal=REDIS_PASSWORD='' 73 | ``` 74 | 75 | Then, deploy the application. 76 | ```sh 77 | ./dock deploy 78 | ``` 79 | 80 | Finally, you can run the migrations or any other artisan command. 81 | ```sh 82 | ./dock kubectl exec -it service/web -- php artisan migrate 83 | ``` 84 | 85 | # GitHub Actions 86 | This repository includes and uses an example workflow that builds the image, starts the application, runs the tests and publishes the image to the GitHub Container Registry. Images are tagged with the SHA-hash of the commit that triggered the build. By default, the image is only published for builds in the `main` branch. However, the image is also published in other branches when the commit message includes the string `/publish`. 87 | 88 | You can find the workflow at https://github.com/jarnovanleeuwen/laravel-dock/blob/main/.github/workflows/push.yml. 89 | -------------------------------------------------------------------------------- /build/Dockerfile: -------------------------------------------------------------------------------- 1 | # Directory containing the source files 2 | ARG SRC="./src" 3 | 4 | # 5 | # Apache + PHP 6 | # 7 | FROM php:8.0-apache as app 8 | 9 | # Install dependencies 10 | RUN apt-get update && apt-get install -y git mariadb-client nano supervisor libpng-dev libjpeg-dev libicu-dev libxml2-dev libzip-dev zip gnupg2 ssl-cert redis-tools 11 | 12 | # Install extensions 13 | RUN pecl install redis 14 | 15 | RUN docker-php-ext-configure gd --with-jpeg &&\ 16 | docker-php-ext-configure intl && \ 17 | docker-php-ext-configure zip && \ 18 | docker-php-ext-install bcmath gd intl opcache pcntl pdo_mysql soap zip && \ 19 | docker-php-ext-enable redis 20 | 21 | # Create non-root user 22 | RUN useradd --create-home webdev 23 | 24 | # Use default PHP production configuration and enable Apache's mod_rewrite and mod_ssl. 25 | RUN mv $PHP_INI_DIR/php.ini-production $PHP_INI_DIR/php.ini && \ 26 | chown -R webdev $PHP_INI_DIR/conf.d && \ 27 | a2enmod ssl && \ 28 | a2enmod rewrite 29 | 30 | # Override with custom PHP settings 31 | COPY ./config/php/php.ini $PHP_INI_DIR/conf.d/php.ini 32 | 33 | # Overwrite the default Apache vhost with the custom vhost 34 | COPY ./config/apache/vhost.conf /etc/apache2/sites-available/000-default.conf 35 | 36 | # Add Supervisor config for Laravel Horizon 37 | COPY ./config/supervisor/supervisord.conf /etc/supervisor/conf.d/supervisord.conf 38 | 39 | # Copy useful scripts (e.g. scripts that help waiting for services to boot) 40 | COPY ./build/bin/ /usr/local/bin/ 41 | 42 | # Install Composer 43 | COPY --from=composer:2 /usr/bin/composer /usr/bin/composer 44 | 45 | # Set working directory 46 | WORKDIR /var/www/html 47 | 48 | # Custom entrypoint to run the app as scheduler or queue worker 49 | COPY ./build/docker-entrypoint /usr/local/bin/ 50 | CMD ["/usr/local/bin/docker-entrypoint"] 51 | 52 | 53 | # 54 | # Production build 55 | # 56 | FROM app as production 57 | ARG SRC 58 | 59 | # Switch user 60 | USER webdev 61 | 62 | # Copy existing application directory contents and change 63 | # ownership of the application files so that they are not 64 | # writable by Apache's www-user 65 | COPY --chown=webdev:webdev $SRC ./ 66 | 67 | # Set proper permissions + install dependencies using Composer 68 | RUN touch storage/logs/laravel.log \ 69 | && chmod -R 777 bootstrap/cache storage \ 70 | && composer install --no-interaction --no-plugins --prefer-dist --ansi 71 | 72 | # Switch default user back to root 73 | USER root 74 | -------------------------------------------------------------------------------- /build/bin/wait_for_mysql: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo -n "Waiting for MySQL.." 4 | 5 | while ! mysql --protocol TCP -h"${DB_HOST}" -P"${DB_PORT}" -u"${DB_USERNAME}" -p"${DB_PASSWORD}" -e"show databases;" > /dev/null 2>&1; do 6 | echo -n . 7 | sleep 1 8 | ((counter++)) 9 | 10 | if [ $counter -gt 60 ]; then 11 | >&2 echo "failed" 12 | exit 1 13 | fi 14 | done 15 | 16 | echo 17 | -------------------------------------------------------------------------------- /build/bin/wait_for_redis: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo -n "Waiting for Redis.." 4 | 5 | while ! (REDISCLI_AUTH=$REDIS_PASSWORD redis-cli -h "${REDIS_HOST}" ping | grep PONG > /dev/null); do 6 | echo -n . 7 | sleep 1 8 | ((counter++)) 9 | 10 | if [ $counter -gt 60 ]; then 11 | >&2 echo "failed" 12 | exit 1 13 | fi 14 | done 15 | 16 | echo 17 | -------------------------------------------------------------------------------- /build/docker-compose.local.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | # Docker Network 4 | networks: 5 | network: 6 | driver: bridge 7 | attachable: true 8 | 9 | # Volumes 10 | volumes: 11 | mysql: 12 | driver: local 13 | redis: 14 | driver: local 15 | 16 | services: 17 | # Apache + PHP 18 | web: 19 | build: 20 | context: ../ 21 | dockerfile: build/Dockerfile 22 | target: app 23 | image: app-local 24 | environment: 25 | - CONTAINER_ROLE=app 26 | - REDIS_HOST=redis 27 | - REDIS_PORT=6379 28 | env_file: ../.env 29 | ports: 30 | - "${HOST_PORT_HTTP:-80}:80" 31 | - "${HOST_PORT_HTTPS:-443}:443" 32 | depends_on: 33 | - db 34 | - redis 35 | volumes: 36 | - ../src:/var/www/html:delegated 37 | networks: 38 | - network 39 | 40 | # Scheduler 41 | scheduler: 42 | image: app-local 43 | user: webdev 44 | environment: 45 | - CONTAINER_ROLE=scheduler 46 | - REDIS_HOST=redis 47 | - REDIS_PORT=6379 48 | env_file: ../.env 49 | depends_on: 50 | - web 51 | volumes: 52 | - ../src:/var/www/html:delegated 53 | networks: 54 | - network 55 | 56 | # Queue worker 57 | queue: 58 | image: app-local 59 | environment: 60 | - CONTAINER_ROLE=queue 61 | - REDIS_HOST=redis 62 | - REDIS_PORT=6379 63 | env_file: ../.env 64 | depends_on: 65 | - web 66 | volumes: 67 | - ../src:/var/www/html:delegated 68 | networks: 69 | - network 70 | 71 | # MySQL 72 | db: 73 | image: mysql:8.0.23 74 | command: [ "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci", "--default-authentication-plugin=mysql_native_password" ] 75 | environment: 76 | - TZ=${TZ} 77 | - MYSQL_ROOT_PASSWORD=${DB_PASSWORD} 78 | - MYSQL_DATABASE=${DB_DATABASE} 79 | env_file: ../.env 80 | ports: 81 | - "${HOST_PORT_DB:-3306}:3306" 82 | volumes: 83 | - mysql:/var/lib/mysql/ 84 | networks: 85 | - network 86 | 87 | # Redis 88 | redis: 89 | image: redis:6.2.4 90 | command: [ "redis-server", "--appendonly", "yes", "--requirepass", "${REDIS_PASSWORD}" ] 91 | env_file: ../.env 92 | ports: 93 | - "${HOST_PORT_REDIS:-6379}:6379" 94 | volumes: 95 | - redis:/data 96 | networks: 97 | - network 98 | -------------------------------------------------------------------------------- /build/docker-compose.test.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | # Docker Network 4 | networks: 5 | network: 6 | driver: bridge 7 | 8 | services: 9 | # Apache + PHP 10 | web: 11 | build: 12 | context: ../ 13 | dockerfile: build/Dockerfile 14 | image: app 15 | environment: 16 | - APP_ENV=testing 17 | - APP_DEBUG=true 18 | - APP_KEY=TESTTESTTESTTESTTESTTESTTESTTEST 19 | - APP_URL=http://web/ 20 | - CONTAINER_ROLE=app 21 | - DB_HOST=db 22 | - DB_PORT=3306 23 | - DB_DATABASE=testing 24 | - DB_USERNAME=root 25 | - DB_PASSWORD=root 26 | - CACHE_DRIVER=redis 27 | - FILESYSTEM_DRIVER=local 28 | - SESSION_DRIVER=redis 29 | - REDIS_HOST=redis 30 | - REDIS_PORT=6379 31 | - REDIS_PASSWORD=rediz 32 | depends_on: 33 | - db 34 | - redis 35 | networks: 36 | - network 37 | 38 | # MySQL 39 | db: 40 | image: mysql:8.0.23 41 | command: ["--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci", "--default-authentication-plugin=mysql_native_password"] 42 | environment: 43 | - MYSQL_ROOT_PASSWORD=root 44 | - MYSQL_DATABASE=testing 45 | networks: 46 | - network 47 | 48 | # Redis 49 | redis: 50 | image: redis:5.0.6 51 | command: ["redis-server", "--appendonly", "yes", "--requirepass", "rediz"] 52 | networks: 53 | - network 54 | -------------------------------------------------------------------------------- /build/docker-entrypoint: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | role=${CONTAINER_ROLE:-app} 4 | env=${APP_ENV:-production} 5 | 6 | wait_for_mysql || exit 1 7 | wait_for_redis || exit 1 8 | 9 | if [ "$env" = "production" ]; then 10 | echo "Clearing cache..." 11 | php artisan cache:clear 12 | 13 | echo "Caching configuration..." 14 | php artisan config:cache 15 | php artisan route:cache 16 | php artisan view:cache 17 | fi 18 | 19 | if [ "$role" = "app" ]; then 20 | exec apache2-foreground 21 | 22 | elif [ "$role" = "queue" ]; then 23 | echo "Starting Supervisor..." 24 | supervisord -c /etc/supervisor/conf.d/supervisord.conf 25 | 26 | elif [ "$role" = "scheduler" ]; then 27 | echo "Running scheduler..." 28 | while [ true ] 29 | do 30 | php artisan schedule:run --verbose --no-interaction & 31 | sleep 60 32 | done 33 | 34 | else 35 | echo "Unknown container role [$role]" 36 | exit 1 37 | fi 38 | -------------------------------------------------------------------------------- /build/kubernetes.yaml: -------------------------------------------------------------------------------- 1 | # Create a secret named 'regcred' for your Docker registry credentials. 2 | # 3 | # kubectl create secret docker-registry regcred \ 4 | # --docker-server= \ 5 | # --docker-username= \ 6 | # --docker-password= 7 | # 8 | # Create a secret named 'app-secrets' for secret keys and passwords, such as for root access to your MySQL database. 9 | # Those will be passed to your app containers as environment variables. 10 | # 11 | # kubectl create secret generic app-secrets \ 12 | # --from-literal=APP_KEY='<256 bit key>' \ 13 | # --from-literal=DB_USERNAME='' \ 14 | # --from-literal=DB_PASSWORD='' \ 15 | # --from-literal=REDIS_PASSWORD='' 16 | 17 | apiVersion: v1 18 | kind: ConfigMap 19 | metadata: 20 | name: app-config 21 | data: 22 | APP_NAME: "laravel-dock on Kubernetes" 23 | APP_ENV: "production" 24 | APP_DEBUG: "false" 25 | APP_URL: "http://localhost" 26 | 27 | TZ: "UTC" 28 | 29 | LOG_CHANNEL: "stderr" 30 | 31 | DB_HOST: "your-db-server.net" 32 | DB_PORT: "3306" 33 | DB_DATABASE: "laraveldock" 34 | 35 | REDIS_HOST: "your-redis-server.net" 36 | REDIS_PORT: "6379" 37 | 38 | BROADCAST_DRIVER: "log" 39 | CACHE_DRIVER: "redis" 40 | QUEUE_CONNECTION: "redis" 41 | SESSION_DRIVER: "redis" 42 | 43 | --- 44 | 45 | apiVersion: v1 46 | kind: Service 47 | metadata: 48 | name: web 49 | spec: 50 | ports: 51 | - port: 80 52 | targetPort: 80 53 | selector: 54 | app: web 55 | 56 | --- 57 | 58 | apiVersion: apps/v1 59 | kind: Deployment 60 | metadata: 61 | name: web 62 | spec: 63 | selector: 64 | matchLabels: 65 | app: web 66 | template: 67 | metadata: 68 | labels: 69 | app: web 70 | spec: 71 | containers: 72 | - name: app 73 | image: ghcr.io/jarnovanleeuwen/laravel-dock:{{TAG}} 74 | envFrom: 75 | - configMapRef: 76 | name: app-config 77 | - secretRef: 78 | name: app-secrets 79 | env: 80 | - name: CONTAINER_ROLE 81 | value: "app" 82 | ports: 83 | - containerPort: 80 84 | # Accept connections until the pod has been removed from the services on all nodes. 85 | # See https://freecontent.manning.com/handling-client-requests-properly-with-kubernetes/ 86 | lifecycle: 87 | preStop: 88 | exec: 89 | command: ["sleep", "5"] 90 | # Start sending traffic only after the application is ready (Apache is running). 91 | readinessProbe: 92 | exec: 93 | command: 94 | - curl 95 | - http://localhost 96 | # initialDelaySeconds: 0 97 | periodSeconds: 10 # default is 10 98 | timeoutSeconds: 10 # default is 1 99 | # successThreshold: 1 100 | # failureThreshold: 3 101 | resources: 102 | requests: 103 | cpu: 1000m 104 | memory: 2048Mi 105 | imagePullSecrets: 106 | - name: regcred 107 | 108 | --- 109 | 110 | apiVersion: apps/v1 111 | kind: Deployment 112 | metadata: 113 | name: scheduler 114 | spec: 115 | selector: 116 | matchLabels: 117 | app: scheduler 118 | strategy: 119 | type: Recreate 120 | template: 121 | metadata: 122 | labels: 123 | app: scheduler 124 | spec: 125 | containers: 126 | - name: app 127 | image: ghcr.io/jarnovanleeuwen/laravel-dock:{{TAG}} 128 | envFrom: 129 | - configMapRef: 130 | name: app-config 131 | - secretRef: 132 | name: app-secrets 133 | env: 134 | - name: CONTAINER_ROLE 135 | value: "scheduler" 136 | resources: 137 | requests: 138 | cpu: 250m 139 | memory: 1024Mi 140 | imagePullSecrets: 141 | - name: regcred 142 | 143 | --- 144 | 145 | apiVersion: apps/v1 146 | kind: Deployment 147 | metadata: 148 | name: queue 149 | spec: 150 | selector: 151 | matchLabels: 152 | app: queue 153 | strategy: 154 | type: Recreate 155 | template: 156 | metadata: 157 | labels: 158 | app: queue 159 | spec: 160 | containers: 161 | - name: app 162 | image: ghcr.io/jarnovanleeuwen/laravel-dock:{{TAG}} 163 | envFrom: 164 | - configMapRef: 165 | name: app-config 166 | - secretRef: 167 | name: app-secrets 168 | env: 169 | - name: CONTAINER_ROLE 170 | value: "queue" 171 | resources: 172 | requests: 173 | cpu: 250m 174 | memory: 1024Mi 175 | imagePullSecrets: 176 | - name: regcred 177 | -------------------------------------------------------------------------------- /config/apache/vhost.conf: -------------------------------------------------------------------------------- 1 | 2 | DocumentRoot /var/www/html/public 3 | 4 | 5 | AllowOverride all 6 | Require all granted 7 | 8 | 9 | ErrorLog ${APACHE_LOG_DIR}/error.log 10 | CustomLog ${APACHE_LOG_DIR}/access.log combined 11 | -------------------------------------------------------------------------------- /config/php/php.ini: -------------------------------------------------------------------------------- 1 | upload_max_filesize=40M 2 | post_max_size=40M 3 | 4 | opcache.enable=1 5 | opcache.enable_cli=1 6 | opcache.max_accelerated_files=50000 -------------------------------------------------------------------------------- /config/supervisor/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | user=root 4 | logfile=/dev/stdout 5 | logfile_maxbytes=0 6 | pidfile=/var/run/supervisord.pid 7 | 8 | [program:horizon] 9 | process_name=%(program_name)s 10 | command=php /var/www/html/artisan horizon 11 | user=webdev 12 | autostart=true 13 | autorestart=true 14 | stdout_logfile=/dev/stdout 15 | stdout_logfile_maxbytes=0 16 | stderr_logfile=/dev/stderr 17 | stderr_logfile_maxbytes=0 -------------------------------------------------------------------------------- /dock: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Exit on errors 4 | set -e 5 | 6 | # Change working directory to the same location as this file. 7 | cd "$(dirname ${BASH_SOURCE[0]})" 8 | 9 | if [ -z "$CI" ]; then 10 | source .env 11 | fi 12 | 13 | APP_ID=${APP_ID:-laraveldock} 14 | APP_USER="root" 15 | BUILD_DIR="build" 16 | 17 | DOCKERFILE="${BUILD_DIR}/Dockerfile" 18 | KUBERNETES_DEPLOYMENT="${BUILD_DIR}/kubernetes.yaml" 19 | 20 | print_kubernetes_context() { 21 | echo "Using Kubernetes context [$KUBERNETES_CONTEXT]" 22 | } 23 | 24 | if [ -z "$CI" ]; then 25 | COMPOSE_PARAMS="-f ${BUILD_DIR}/docker-compose.local.yml --env-file .env"; 26 | else 27 | COMPOSE_PARAMS="-f ${BUILD_DIR}/docker-compose.test.yml"; 28 | fi 29 | 30 | COMPOSE="docker-compose --project-name ${APP_ID} ${COMPOSE_PARAMS}" 31 | 32 | if [ -z "$CI" ]; then 33 | RUN="docker run -it" 34 | else 35 | RUN="docker run" 36 | fi 37 | 38 | if [ $# -gt 0 ]; then 39 | 40 | if [ "$1" == "up" ]; then 41 | if [ -z "$CI" ]; then 42 | ${COMPOSE} up --build db redis web 43 | else 44 | ${COMPOSE} up --detach web 45 | fi 46 | 47 | elif [ "$1" == "scheduler" ]; then 48 | ${COMPOSE} up --build scheduler 49 | 50 | elif [ "$1" == "queue" ]; then 51 | ${COMPOSE} up --build queue 52 | 53 | elif [ "$1" == "down" ]; then 54 | ${COMPOSE} down 55 | 56 | elif [ "$1" == "restart" ]; then 57 | ./$0 down 58 | ./$0 up 59 | 60 | elif [ "$1" == "build" ]; then 61 | if [ -z "$2" ]; then 62 | echo "Tag required" 63 | exit 64 | fi 65 | 66 | docker build --file ${DOCKERFILE} --target production --tag $2 . 67 | 68 | elif [ "$1" == "push" ]; then 69 | if [ -z "$2" ]; then 70 | echo "Tag required" 71 | exit 72 | fi 73 | 74 | if docker login -u ${REGISTRY_USER} -p ${REGISTRY_PASSWORD} ${REGISTRY} > /dev/null 2>&1; then 75 | docker push $2 76 | else 77 | echo "Login to registry failed for [${REGISTRY_USER}] at [${REGISTRY}]" 78 | fi 79 | 80 | elif [ "$1" == "deploy" ]; then 81 | if [ -z "$2" ]; then 82 | echo "Build ID required" 83 | exit 84 | fi 85 | print_kubernetes_context 86 | echo 87 | read -p "Are you sure you want to deploy [$2]? (y/N) " -r 88 | echo 89 | if [[ $REPLY =~ ^[Yy]$ ]]; then 90 | cat ${KUBERNETES_DEPLOYMENT} | sed "s/{{TAG}}/$2/g" | kubectl apply --context=${KUBERNETES_CONTEXT} -f - 91 | echo 92 | echo -e "Done! To view the status run:\n\n\t./dock status\n" 93 | fi 94 | 95 | elif [ "$1" == "status" ]; then 96 | print_kubernetes_context 97 | kubectl --context ${KUBERNETES_CONTEXT} get pods,deployments,statefulsets,hpa -o wide 98 | 99 | elif [ "$1" == "tail" ]; then 100 | $0 exec "cd storage/logs && tail -n 1000 -F laravel.log" 101 | 102 | elif [ "$1" == "exec" ]; then 103 | shift 1 104 | ARGS="$@" 105 | if [ -z "$CI" ]; then 106 | ${COMPOSE} exec --user ${APP_USER} web bash -c "$ARGS" 107 | else 108 | ${COMPOSE} exec -T web bash -c "$ARGS" 109 | fi 110 | 111 | elif [ "$1" == "kubectl" ]; then 112 | shift 1 113 | ARGS="$@" 114 | print_kubernetes_context 115 | kubectl --context ${KUBERNETES_CONTEXT} ${ARGS} 116 | 117 | elif [ "$1" == "test" ]; then 118 | shift 1 119 | ARGS="$@" 120 | $0 exec "vendor/bin/phpunit $ARGS" 121 | 122 | elif [ "$1" == "artisan" ]; then 123 | shift 1 124 | ARGS="$@" 125 | $0 exec "php artisan $ARGS" 126 | 127 | else 128 | ${COMPOSE} "$@" 129 | fi 130 | else 131 | ${COMPOSE} ps 132 | fi 133 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /public/hot 3 | /public/storage 4 | /storage/*.key 5 | /vendor 6 | .env 7 | .env.backup 8 | .phpunit.result.cache 9 | docker-compose.override.yml 10 | Homestead.json 11 | Homestead.yaml 12 | npm-debug.log 13 | yarn-error.log 14 | /.idea 15 | /.vscode 16 | -------------------------------------------------------------------------------- /src/app/Console/Commands/IncrementCounter.php: -------------------------------------------------------------------------------- 1 | command('counter:increment')->everyMinute(); 28 | } 29 | 30 | /** 31 | * Register the commands for the application. 32 | * 33 | * @return void 34 | */ 35 | protected function commands() 36 | { 37 | $this->load(__DIR__.'/Commands'); 38 | 39 | require base_path('routes/console.php'); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/app/Exceptions/Handler.php: -------------------------------------------------------------------------------- 1 | reportable(function (Throwable $e) { 38 | // 39 | }); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/app/Http/Controllers/Controller.php: -------------------------------------------------------------------------------- 1 | [ 33 | \App\Http\Middleware\EncryptCookies::class, 34 | \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, 35 | \Illuminate\Session\Middleware\StartSession::class, 36 | // \Illuminate\Session\Middleware\AuthenticateSession::class, 37 | \Illuminate\View\Middleware\ShareErrorsFromSession::class, 38 | \App\Http\Middleware\VerifyCsrfToken::class, 39 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 40 | ], 41 | 42 | 'api' => [ 43 | 'throttle:api', 44 | \Illuminate\Routing\Middleware\SubstituteBindings::class, 45 | ], 46 | ]; 47 | 48 | /** 49 | * The application's route middleware. 50 | * 51 | * These middleware may be assigned to groups or used individually. 52 | * 53 | * @var array 54 | */ 55 | protected $routeMiddleware = [ 56 | 'auth' => \App\Http\Middleware\Authenticate::class, 57 | 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, 58 | 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, 59 | 'can' => \Illuminate\Auth\Middleware\Authorize::class, 60 | 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, 61 | 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, 62 | 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 63 | 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 64 | 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, 65 | ]; 66 | } 67 | -------------------------------------------------------------------------------- /src/app/Http/Middleware/Authenticate.php: -------------------------------------------------------------------------------- 1 | expectsJson()) { 18 | return route('login'); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/app/Http/Middleware/EncryptCookies.php: -------------------------------------------------------------------------------- 1 | check()) { 26 | return redirect(RouteServiceProvider::HOME); 27 | } 28 | } 29 | 30 | return $next($request); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/app/Http/Middleware/TrimStrings.php: -------------------------------------------------------------------------------- 1 | allSubdomainsOfApplicationUrl(), 18 | ]; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/app/Http/Middleware/TrustProxies.php: -------------------------------------------------------------------------------- 1 | 'datetime', 42 | ]; 43 | } 44 | -------------------------------------------------------------------------------- /src/app/Providers/AppServiceProvider.php: -------------------------------------------------------------------------------- 1 | 'App\Policies\ModelPolicy', 17 | ]; 18 | 19 | /** 20 | * Register any authentication / authorization services. 21 | * 22 | * @return void 23 | */ 24 | public function boot() 25 | { 26 | $this->registerPolicies(); 27 | 28 | // 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/app/Providers/BroadcastServiceProvider.php: -------------------------------------------------------------------------------- 1 | [ 19 | SendEmailVerificationNotification::class, 20 | ], 21 | ]; 22 | 23 | /** 24 | * Register any events for your application. 25 | * 26 | * @return void 27 | */ 28 | public function boot() 29 | { 30 | // 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/app/Providers/HorizonServiceProvider.php: -------------------------------------------------------------------------------- 1 | email, [ 38 | // 39 | ]); 40 | }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/app/Providers/RouteServiceProvider.php: -------------------------------------------------------------------------------- 1 | configureRateLimiting(); 39 | 40 | $this->routes(function () { 41 | Route::prefix('api') 42 | ->middleware('api') 43 | ->namespace($this->namespace) 44 | ->group(base_path('routes/api.php')); 45 | 46 | Route::middleware('web') 47 | ->namespace($this->namespace) 48 | ->group(base_path('routes/web.php')); 49 | }); 50 | } 51 | 52 | /** 53 | * Configure the rate limiters for the application. 54 | * 55 | * @return void 56 | */ 57 | protected function configureRateLimiting() 58 | { 59 | RateLimiter::for('api', function (Request $request) { 60 | return Limit::perMinute(60)->by(optional($request->user())->id ?: $request->ip()); 61 | }); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/artisan: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | make(Illuminate\Contracts\Console\Kernel::class); 34 | 35 | $status = $kernel->handle( 36 | $input = new Symfony\Component\Console\Input\ArgvInput, 37 | new Symfony\Component\Console\Output\ConsoleOutput 38 | ); 39 | 40 | /* 41 | |-------------------------------------------------------------------------- 42 | | Shutdown The Application 43 | |-------------------------------------------------------------------------- 44 | | 45 | | Once Artisan has finished running, we will fire off the shutdown events 46 | | so that any final work may be done by the application before we shut 47 | | down the process. This is the last thing to happen to the request. 48 | | 49 | */ 50 | 51 | $kernel->terminate($input, $status); 52 | 53 | exit($status); 54 | -------------------------------------------------------------------------------- /src/bootstrap/app.php: -------------------------------------------------------------------------------- 1 | singleton( 30 | Illuminate\Contracts\Http\Kernel::class, 31 | App\Http\Kernel::class 32 | ); 33 | 34 | $app->singleton( 35 | Illuminate\Contracts\Console\Kernel::class, 36 | App\Console\Kernel::class 37 | ); 38 | 39 | $app->singleton( 40 | Illuminate\Contracts\Debug\ExceptionHandler::class, 41 | App\Exceptions\Handler::class 42 | ); 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Return The Application 47 | |-------------------------------------------------------------------------- 48 | | 49 | | This script returns the application instance. The instance is given to 50 | | the calling script so we can separate the building of the instances 51 | | from the actual running of the application and sending responses. 52 | | 53 | */ 54 | 55 | return $app; 56 | -------------------------------------------------------------------------------- /src/bootstrap/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /src/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "laravel/laravel", 3 | "type": "project", 4 | "description": "The Laravel Framework.", 5 | "keywords": ["framework", "laravel"], 6 | "license": "MIT", 7 | "require": { 8 | "php": "^7.3|^8.0", 9 | "fideloper/proxy": "^4.4", 10 | "fruitcake/laravel-cors": "^2.0", 11 | "guzzlehttp/guzzle": "^7.0.1", 12 | "laravel/framework": "^8.40", 13 | "laravel/horizon": "^5.7", 14 | "laravel/tinker": "^2.5" 15 | }, 16 | "require-dev": { 17 | "facade/ignition": "^2.5", 18 | "fakerphp/faker": "^1.9.1", 19 | "laravel/sail": "^1.0.1", 20 | "mockery/mockery": "^1.4.2", 21 | "nunomaduro/collision": "^5.0", 22 | "phpunit/phpunit": "^9.3.3" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "App\\": "app/", 27 | "Database\\Factories\\": "database/factories/", 28 | "Database\\Seeders\\": "database/seeders/" 29 | } 30 | }, 31 | "autoload-dev": { 32 | "psr-4": { 33 | "Tests\\": "tests/" 34 | } 35 | }, 36 | "scripts": { 37 | "post-autoload-dump": [ 38 | "Illuminate\\Foundation\\ComposerScripts::postAutoloadDump", 39 | "@php artisan package:discover --ansi" 40 | ], 41 | "post-root-package-install": [ 42 | "@php -r \"file_exists('.env') || copy('.env.example', '.env');\"" 43 | ], 44 | "post-create-project-cmd": [ 45 | "@php artisan key:generate --ansi" 46 | ] 47 | }, 48 | "extra": { 49 | "laravel": { 50 | "dont-discover": [] 51 | } 52 | }, 53 | "config": { 54 | "optimize-autoloader": true, 55 | "preferred-install": "dist", 56 | "sort-packages": true 57 | }, 58 | "minimum-stability": "dev", 59 | "prefer-stable": true 60 | } 61 | -------------------------------------------------------------------------------- /src/config/app.php: -------------------------------------------------------------------------------- 1 | env('APP_NAME', 'Laravel'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Application Environment 21 | |-------------------------------------------------------------------------- 22 | | 23 | | This value determines the "environment" your application is currently 24 | | running in. This may determine how you prefer to configure various 25 | | services the application utilizes. Set this in your ".env" file. 26 | | 27 | */ 28 | 29 | 'env' => env('APP_ENV', 'production'), 30 | 31 | /* 32 | |-------------------------------------------------------------------------- 33 | | Application Debug Mode 34 | |-------------------------------------------------------------------------- 35 | | 36 | | When your application is in debug mode, detailed error messages with 37 | | stack traces will be shown on every error that occurs within your 38 | | application. If disabled, a simple generic error page is shown. 39 | | 40 | */ 41 | 42 | 'debug' => (bool) env('APP_DEBUG', false), 43 | 44 | /* 45 | |-------------------------------------------------------------------------- 46 | | Application URL 47 | |-------------------------------------------------------------------------- 48 | | 49 | | This URL is used by the console to properly generate URLs when using 50 | | the Artisan command line tool. You should set this to the root of 51 | | your application so that it is used when running Artisan tasks. 52 | | 53 | */ 54 | 55 | 'url' => env('APP_URL', 'http://localhost'), 56 | 57 | 'asset_url' => env('ASSET_URL', null), 58 | 59 | /* 60 | |-------------------------------------------------------------------------- 61 | | Application Timezone 62 | |-------------------------------------------------------------------------- 63 | | 64 | | Here you may specify the default timezone for your application, which 65 | | will be used by the PHP date and date-time functions. We have gone 66 | | ahead and set this to a sensible default for you out of the box. 67 | | 68 | */ 69 | 70 | 'timezone' => 'UTC', 71 | 72 | /* 73 | |-------------------------------------------------------------------------- 74 | | Application Locale Configuration 75 | |-------------------------------------------------------------------------- 76 | | 77 | | The application locale determines the default locale that will be used 78 | | by the translation service provider. You are free to set this value 79 | | to any of the locales which will be supported by the application. 80 | | 81 | */ 82 | 83 | 'locale' => 'en', 84 | 85 | /* 86 | |-------------------------------------------------------------------------- 87 | | Application Fallback Locale 88 | |-------------------------------------------------------------------------- 89 | | 90 | | The fallback locale determines the locale to use when the current one 91 | | is not available. You may change the value to correspond to any of 92 | | the language folders that are provided through your application. 93 | | 94 | */ 95 | 96 | 'fallback_locale' => 'en', 97 | 98 | /* 99 | |-------------------------------------------------------------------------- 100 | | Faker Locale 101 | |-------------------------------------------------------------------------- 102 | | 103 | | This locale will be used by the Faker PHP library when generating fake 104 | | data for your database seeds. For example, this will be used to get 105 | | localized telephone numbers, street address information and more. 106 | | 107 | */ 108 | 109 | 'faker_locale' => 'en_US', 110 | 111 | /* 112 | |-------------------------------------------------------------------------- 113 | | Encryption Key 114 | |-------------------------------------------------------------------------- 115 | | 116 | | This key is used by the Illuminate encrypter service and should be set 117 | | to a random, 32 character string, otherwise these encrypted strings 118 | | will not be safe. Please do this before deploying an application! 119 | | 120 | */ 121 | 122 | 'key' => env('APP_KEY'), 123 | 124 | 'cipher' => 'AES-256-CBC', 125 | 126 | /* 127 | |-------------------------------------------------------------------------- 128 | | Autoloaded Service Providers 129 | |-------------------------------------------------------------------------- 130 | | 131 | | The service providers listed here will be automatically loaded on the 132 | | request to your application. Feel free to add your own services to 133 | | this array to grant expanded functionality to your applications. 134 | | 135 | */ 136 | 137 | 'providers' => [ 138 | 139 | /* 140 | * Laravel Framework Service Providers... 141 | */ 142 | Illuminate\Auth\AuthServiceProvider::class, 143 | Illuminate\Broadcasting\BroadcastServiceProvider::class, 144 | Illuminate\Bus\BusServiceProvider::class, 145 | Illuminate\Cache\CacheServiceProvider::class, 146 | Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class, 147 | Illuminate\Cookie\CookieServiceProvider::class, 148 | Illuminate\Database\DatabaseServiceProvider::class, 149 | Illuminate\Encryption\EncryptionServiceProvider::class, 150 | Illuminate\Filesystem\FilesystemServiceProvider::class, 151 | Illuminate\Foundation\Providers\FoundationServiceProvider::class, 152 | Illuminate\Hashing\HashServiceProvider::class, 153 | Illuminate\Mail\MailServiceProvider::class, 154 | Illuminate\Notifications\NotificationServiceProvider::class, 155 | Illuminate\Pagination\PaginationServiceProvider::class, 156 | Illuminate\Pipeline\PipelineServiceProvider::class, 157 | Illuminate\Queue\QueueServiceProvider::class, 158 | Illuminate\Redis\RedisServiceProvider::class, 159 | Illuminate\Auth\Passwords\PasswordResetServiceProvider::class, 160 | Illuminate\Session\SessionServiceProvider::class, 161 | Illuminate\Translation\TranslationServiceProvider::class, 162 | Illuminate\Validation\ValidationServiceProvider::class, 163 | Illuminate\View\ViewServiceProvider::class, 164 | 165 | /* 166 | * Package Service Providers... 167 | */ 168 | 169 | /* 170 | * Application Service Providers... 171 | */ 172 | App\Providers\AppServiceProvider::class, 173 | App\Providers\AuthServiceProvider::class, 174 | // App\Providers\BroadcastServiceProvider::class, 175 | App\Providers\EventServiceProvider::class, 176 | App\Providers\HorizonServiceProvider::class, 177 | App\Providers\RouteServiceProvider::class, 178 | 179 | ], 180 | 181 | /* 182 | |-------------------------------------------------------------------------- 183 | | Class Aliases 184 | |-------------------------------------------------------------------------- 185 | | 186 | | This array of class aliases will be registered when this application 187 | | is started. However, feel free to register as many as you wish as 188 | | the aliases are "lazy" loaded so they don't hinder performance. 189 | | 190 | */ 191 | 192 | 'aliases' => [ 193 | 194 | 'App' => Illuminate\Support\Facades\App::class, 195 | 'Arr' => Illuminate\Support\Arr::class, 196 | 'Artisan' => Illuminate\Support\Facades\Artisan::class, 197 | 'Auth' => Illuminate\Support\Facades\Auth::class, 198 | 'Blade' => Illuminate\Support\Facades\Blade::class, 199 | 'Broadcast' => Illuminate\Support\Facades\Broadcast::class, 200 | 'Bus' => Illuminate\Support\Facades\Bus::class, 201 | 'Cache' => Illuminate\Support\Facades\Cache::class, 202 | 'Config' => Illuminate\Support\Facades\Config::class, 203 | 'Cookie' => Illuminate\Support\Facades\Cookie::class, 204 | 'Crypt' => Illuminate\Support\Facades\Crypt::class, 205 | 'Date' => Illuminate\Support\Facades\Date::class, 206 | 'DB' => Illuminate\Support\Facades\DB::class, 207 | 'Eloquent' => Illuminate\Database\Eloquent\Model::class, 208 | 'Event' => Illuminate\Support\Facades\Event::class, 209 | 'File' => Illuminate\Support\Facades\File::class, 210 | 'Gate' => Illuminate\Support\Facades\Gate::class, 211 | 'Hash' => Illuminate\Support\Facades\Hash::class, 212 | 'Http' => Illuminate\Support\Facades\Http::class, 213 | 'Lang' => Illuminate\Support\Facades\Lang::class, 214 | 'Log' => Illuminate\Support\Facades\Log::class, 215 | 'Mail' => Illuminate\Support\Facades\Mail::class, 216 | 'Notification' => Illuminate\Support\Facades\Notification::class, 217 | 'Password' => Illuminate\Support\Facades\Password::class, 218 | 'Queue' => Illuminate\Support\Facades\Queue::class, 219 | 'Redirect' => Illuminate\Support\Facades\Redirect::class, 220 | // 'Redis' => Illuminate\Support\Facades\Redis::class, 221 | 'Request' => Illuminate\Support\Facades\Request::class, 222 | 'Response' => Illuminate\Support\Facades\Response::class, 223 | 'Route' => Illuminate\Support\Facades\Route::class, 224 | 'Schema' => Illuminate\Support\Facades\Schema::class, 225 | 'Session' => Illuminate\Support\Facades\Session::class, 226 | 'Storage' => Illuminate\Support\Facades\Storage::class, 227 | 'Str' => Illuminate\Support\Str::class, 228 | 'URL' => Illuminate\Support\Facades\URL::class, 229 | 'Validator' => Illuminate\Support\Facades\Validator::class, 230 | 'View' => Illuminate\Support\Facades\View::class, 231 | 232 | ], 233 | 234 | ]; 235 | -------------------------------------------------------------------------------- /src/config/auth.php: -------------------------------------------------------------------------------- 1 | [ 17 | 'guard' => 'web', 18 | 'passwords' => 'users', 19 | ], 20 | 21 | /* 22 | |-------------------------------------------------------------------------- 23 | | Authentication Guards 24 | |-------------------------------------------------------------------------- 25 | | 26 | | Next, you may define every authentication guard for your application. 27 | | Of course, a great default configuration has been defined for you 28 | | here which uses session storage and the Eloquent user provider. 29 | | 30 | | All authentication drivers have a user provider. This defines how the 31 | | users are actually retrieved out of your database or other storage 32 | | mechanisms used by this application to persist your user's data. 33 | | 34 | | Supported: "session", "token" 35 | | 36 | */ 37 | 38 | 'guards' => [ 39 | 'web' => [ 40 | 'driver' => 'session', 41 | 'provider' => 'users', 42 | ], 43 | 44 | 'api' => [ 45 | 'driver' => 'token', 46 | 'provider' => 'users', 47 | 'hash' => false, 48 | ], 49 | ], 50 | 51 | /* 52 | |-------------------------------------------------------------------------- 53 | | User Providers 54 | |-------------------------------------------------------------------------- 55 | | 56 | | All authentication drivers have a user provider. This defines how the 57 | | users are actually retrieved out of your database or other storage 58 | | mechanisms used by this application to persist your user's data. 59 | | 60 | | If you have multiple user tables or models you may configure multiple 61 | | sources which represent each model / table. These sources may then 62 | | be assigned to any extra authentication guards you have defined. 63 | | 64 | | Supported: "database", "eloquent" 65 | | 66 | */ 67 | 68 | 'providers' => [ 69 | 'users' => [ 70 | 'driver' => 'eloquent', 71 | 'model' => App\Models\User::class, 72 | ], 73 | 74 | // 'users' => [ 75 | // 'driver' => 'database', 76 | // 'table' => 'users', 77 | // ], 78 | ], 79 | 80 | /* 81 | |-------------------------------------------------------------------------- 82 | | Resetting Passwords 83 | |-------------------------------------------------------------------------- 84 | | 85 | | You may specify multiple password reset configurations if you have more 86 | | than one user table or model in the application and you want to have 87 | | separate password reset settings based on the specific user types. 88 | | 89 | | The expire time is the number of minutes that the reset token should be 90 | | considered valid. This security feature keeps tokens short-lived so 91 | | they have less time to be guessed. You may change this as needed. 92 | | 93 | */ 94 | 95 | 'passwords' => [ 96 | 'users' => [ 97 | 'provider' => 'users', 98 | 'table' => 'password_resets', 99 | 'expire' => 60, 100 | 'throttle' => 60, 101 | ], 102 | ], 103 | 104 | /* 105 | |-------------------------------------------------------------------------- 106 | | Password Confirmation Timeout 107 | |-------------------------------------------------------------------------- 108 | | 109 | | Here you may define the amount of seconds before a password confirmation 110 | | times out and the user is prompted to re-enter their password via the 111 | | confirmation screen. By default, the timeout lasts for three hours. 112 | | 113 | */ 114 | 115 | 'password_timeout' => 10800, 116 | 117 | ]; 118 | -------------------------------------------------------------------------------- /src/config/broadcasting.php: -------------------------------------------------------------------------------- 1 | env('BROADCAST_DRIVER', 'null'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Broadcast Connections 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the broadcast connections that will be used 26 | | to broadcast events to other systems or over websockets. Samples of 27 | | each available type of connection are provided inside this array. 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'pusher' => [ 34 | 'driver' => 'pusher', 35 | 'key' => env('PUSHER_APP_KEY'), 36 | 'secret' => env('PUSHER_APP_SECRET'), 37 | 'app_id' => env('PUSHER_APP_ID'), 38 | 'options' => [ 39 | 'cluster' => env('PUSHER_APP_CLUSTER'), 40 | 'useTLS' => true, 41 | ], 42 | ], 43 | 44 | 'ably' => [ 45 | 'driver' => 'ably', 46 | 'key' => env('ABLY_KEY'), 47 | ], 48 | 49 | 'redis' => [ 50 | 'driver' => 'redis', 51 | 'connection' => 'default', 52 | ], 53 | 54 | 'log' => [ 55 | 'driver' => 'log', 56 | ], 57 | 58 | 'null' => [ 59 | 'driver' => 'null', 60 | ], 61 | 62 | ], 63 | 64 | ]; 65 | -------------------------------------------------------------------------------- /src/config/cache.php: -------------------------------------------------------------------------------- 1 | env('CACHE_DRIVER', 'file'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Cache Stores 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may define all of the cache "stores" for your application as 26 | | well as their drivers. You may even define multiple stores for the 27 | | same cache driver to group types of items stored in your caches. 28 | | 29 | | Supported drivers: "apc", "array", "database", "file", 30 | | "memcached", "redis", "dynamodb", "octane", "null" 31 | | 32 | */ 33 | 34 | 'stores' => [ 35 | 36 | 'apc' => [ 37 | 'driver' => 'apc', 38 | ], 39 | 40 | 'array' => [ 41 | 'driver' => 'array', 42 | 'serialize' => false, 43 | ], 44 | 45 | 'database' => [ 46 | 'driver' => 'database', 47 | 'table' => 'cache', 48 | 'connection' => null, 49 | 'lock_connection' => null, 50 | ], 51 | 52 | 'file' => [ 53 | 'driver' => 'file', 54 | 'path' => storage_path('framework/cache/data'), 55 | ], 56 | 57 | 'memcached' => [ 58 | 'driver' => 'memcached', 59 | 'persistent_id' => env('MEMCACHED_PERSISTENT_ID'), 60 | 'sasl' => [ 61 | env('MEMCACHED_USERNAME'), 62 | env('MEMCACHED_PASSWORD'), 63 | ], 64 | 'options' => [ 65 | // Memcached::OPT_CONNECT_TIMEOUT => 2000, 66 | ], 67 | 'servers' => [ 68 | [ 69 | 'host' => env('MEMCACHED_HOST', '127.0.0.1'), 70 | 'port' => env('MEMCACHED_PORT', 11211), 71 | 'weight' => 100, 72 | ], 73 | ], 74 | ], 75 | 76 | 'redis' => [ 77 | 'driver' => 'redis', 78 | 'connection' => 'cache', 79 | 'lock_connection' => 'default', 80 | ], 81 | 82 | 'dynamodb' => [ 83 | 'driver' => 'dynamodb', 84 | 'key' => env('AWS_ACCESS_KEY_ID'), 85 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 86 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 87 | 'table' => env('DYNAMODB_CACHE_TABLE', 'cache'), 88 | 'endpoint' => env('DYNAMODB_ENDPOINT'), 89 | ], 90 | 91 | 'octane' => [ 92 | 'driver' => 'octane', 93 | ], 94 | 95 | ], 96 | 97 | /* 98 | |-------------------------------------------------------------------------- 99 | | Cache Key Prefix 100 | |-------------------------------------------------------------------------- 101 | | 102 | | When utilizing a RAM based store such as APC or Memcached, there might 103 | | be other applications utilizing the same cache. So, we'll specify a 104 | | value to get prefixed to all our keys so we can avoid collisions. 105 | | 106 | */ 107 | 108 | 'prefix' => env('CACHE_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_cache'), 109 | 110 | ]; 111 | -------------------------------------------------------------------------------- /src/config/cors.php: -------------------------------------------------------------------------------- 1 | ['api/*', 'sanctum/csrf-cookie'], 19 | 20 | 'allowed_methods' => ['*'], 21 | 22 | 'allowed_origins' => ['*'], 23 | 24 | 'allowed_origins_patterns' => [], 25 | 26 | 'allowed_headers' => ['*'], 27 | 28 | 'exposed_headers' => [], 29 | 30 | 'max_age' => 0, 31 | 32 | 'supports_credentials' => false, 33 | 34 | ]; 35 | -------------------------------------------------------------------------------- /src/config/database.php: -------------------------------------------------------------------------------- 1 | env('DB_CONNECTION', 'mysql'), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Database Connections 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here are each of the database connections setup for your application. 26 | | Of course, examples of configuring each database platform that is 27 | | supported by Laravel is shown below to make development simple. 28 | | 29 | | 30 | | All database work in Laravel is done through the PHP PDO facilities 31 | | so make sure you have the driver for your particular database of 32 | | choice installed on your machine before you begin development. 33 | | 34 | */ 35 | 36 | 'connections' => [ 37 | 38 | 'sqlite' => [ 39 | 'driver' => 'sqlite', 40 | 'url' => env('DATABASE_URL'), 41 | 'database' => env('DB_DATABASE', database_path('database.sqlite')), 42 | 'prefix' => '', 43 | 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), 44 | ], 45 | 46 | 'mysql' => [ 47 | 'driver' => 'mysql', 48 | 'url' => env('DATABASE_URL'), 49 | 'host' => env('DB_HOST', '127.0.0.1'), 50 | 'port' => env('DB_PORT', '3306'), 51 | 'database' => env('DB_DATABASE', 'forge'), 52 | 'username' => env('DB_USERNAME', 'forge'), 53 | 'password' => env('DB_PASSWORD', ''), 54 | 'unix_socket' => env('DB_SOCKET', ''), 55 | 'charset' => 'utf8mb4', 56 | 'collation' => 'utf8mb4_unicode_ci', 57 | 'prefix' => '', 58 | 'prefix_indexes' => true, 59 | 'strict' => true, 60 | 'engine' => null, 61 | 'options' => extension_loaded('pdo_mysql') ? array_filter([ 62 | PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'), 63 | ]) : [], 64 | ], 65 | 66 | 'pgsql' => [ 67 | 'driver' => 'pgsql', 68 | 'url' => env('DATABASE_URL'), 69 | 'host' => env('DB_HOST', '127.0.0.1'), 70 | 'port' => env('DB_PORT', '5432'), 71 | 'database' => env('DB_DATABASE', 'forge'), 72 | 'username' => env('DB_USERNAME', 'forge'), 73 | 'password' => env('DB_PASSWORD', ''), 74 | 'charset' => 'utf8', 75 | 'prefix' => '', 76 | 'prefix_indexes' => true, 77 | 'schema' => 'public', 78 | 'sslmode' => 'prefer', 79 | ], 80 | 81 | 'sqlsrv' => [ 82 | 'driver' => 'sqlsrv', 83 | 'url' => env('DATABASE_URL'), 84 | 'host' => env('DB_HOST', 'localhost'), 85 | 'port' => env('DB_PORT', '1433'), 86 | 'database' => env('DB_DATABASE', 'forge'), 87 | 'username' => env('DB_USERNAME', 'forge'), 88 | 'password' => env('DB_PASSWORD', ''), 89 | 'charset' => 'utf8', 90 | 'prefix' => '', 91 | 'prefix_indexes' => true, 92 | ], 93 | 94 | ], 95 | 96 | /* 97 | |-------------------------------------------------------------------------- 98 | | Migration Repository Table 99 | |-------------------------------------------------------------------------- 100 | | 101 | | This table keeps track of all the migrations that have already run for 102 | | your application. Using this information, we can determine which of 103 | | the migrations on disk haven't actually been run in the database. 104 | | 105 | */ 106 | 107 | 'migrations' => 'migrations', 108 | 109 | /* 110 | |-------------------------------------------------------------------------- 111 | | Redis Databases 112 | |-------------------------------------------------------------------------- 113 | | 114 | | Redis is an open source, fast, and advanced key-value store that also 115 | | provides a richer body of commands than a typical key-value system 116 | | such as APC or Memcached. Laravel makes it easy to dig right in. 117 | | 118 | */ 119 | 120 | 'redis' => [ 121 | 122 | 'client' => env('REDIS_CLIENT', 'phpredis'), 123 | 124 | 'options' => [ 125 | 'cluster' => env('REDIS_CLUSTER', 'redis'), 126 | 'prefix' => env('REDIS_PREFIX', Str::slug(env('APP_NAME', 'laravel'), '_').'_database_'), 127 | ], 128 | 129 | 'default' => [ 130 | 'url' => env('REDIS_URL'), 131 | 'host' => env('REDIS_HOST', '127.0.0.1'), 132 | 'password' => env('REDIS_PASSWORD', null), 133 | 'port' => env('REDIS_PORT', '6379'), 134 | 'database' => env('REDIS_DB', '0'), 135 | ], 136 | 137 | 'cache' => [ 138 | 'url' => env('REDIS_URL'), 139 | 'host' => env('REDIS_HOST', '127.0.0.1'), 140 | 'password' => env('REDIS_PASSWORD', null), 141 | 'port' => env('REDIS_PORT', '6379'), 142 | 'database' => env('REDIS_CACHE_DB', '1'), 143 | ], 144 | 145 | ], 146 | 147 | ]; 148 | -------------------------------------------------------------------------------- /src/config/filesystems.php: -------------------------------------------------------------------------------- 1 | env('FILESYSTEM_DRIVER', 'local'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Filesystem Disks 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure as many filesystem "disks" as you wish, and you 24 | | may even configure multiple disks of the same driver. Defaults have 25 | | been setup for each driver as an example of the required options. 26 | | 27 | | Supported Drivers: "local", "ftp", "sftp", "s3" 28 | | 29 | */ 30 | 31 | 'disks' => [ 32 | 33 | 'local' => [ 34 | 'driver' => 'local', 35 | 'root' => storage_path('app'), 36 | ], 37 | 38 | 'public' => [ 39 | 'driver' => 'local', 40 | 'root' => storage_path('app/public'), 41 | 'url' => env('APP_URL').'/storage', 42 | 'visibility' => 'public', 43 | ], 44 | 45 | 's3' => [ 46 | 'driver' => 's3', 47 | 'key' => env('AWS_ACCESS_KEY_ID'), 48 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 49 | 'region' => env('AWS_DEFAULT_REGION'), 50 | 'bucket' => env('AWS_BUCKET'), 51 | 'url' => env('AWS_URL'), 52 | 'endpoint' => env('AWS_ENDPOINT'), 53 | 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), 54 | ], 55 | 56 | ], 57 | 58 | /* 59 | |-------------------------------------------------------------------------- 60 | | Symbolic Links 61 | |-------------------------------------------------------------------------- 62 | | 63 | | Here you may configure the symbolic links that will be created when the 64 | | `storage:link` Artisan command is executed. The array keys should be 65 | | the locations of the links and the values should be their targets. 66 | | 67 | */ 68 | 69 | 'links' => [ 70 | public_path('storage') => storage_path('app/public'), 71 | ], 72 | 73 | ]; 74 | -------------------------------------------------------------------------------- /src/config/hashing.php: -------------------------------------------------------------------------------- 1 | 'bcrypt', 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Bcrypt Options 23 | |-------------------------------------------------------------------------- 24 | | 25 | | Here you may specify the configuration options that should be used when 26 | | passwords are hashed using the Bcrypt algorithm. This will allow you 27 | | to control the amount of time it takes to hash the given password. 28 | | 29 | */ 30 | 31 | 'bcrypt' => [ 32 | 'rounds' => env('BCRYPT_ROUNDS', 10), 33 | ], 34 | 35 | /* 36 | |-------------------------------------------------------------------------- 37 | | Argon Options 38 | |-------------------------------------------------------------------------- 39 | | 40 | | Here you may specify the configuration options that should be used when 41 | | passwords are hashed using the Argon algorithm. These will allow you 42 | | to control the amount of time it takes to hash the given password. 43 | | 44 | */ 45 | 46 | 'argon' => [ 47 | 'memory' => 1024, 48 | 'threads' => 2, 49 | 'time' => 2, 50 | ], 51 | 52 | ]; 53 | -------------------------------------------------------------------------------- /src/config/horizon.php: -------------------------------------------------------------------------------- 1 | env('HORIZON_DOMAIN', null), 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Horizon Path 23 | |-------------------------------------------------------------------------- 24 | | 25 | | This is the URI path where Horizon will be accessible from. Feel free 26 | | to change this path to anything you like. Note that the URI will not 27 | | affect the paths of its internal API that aren't exposed to users. 28 | | 29 | */ 30 | 31 | 'path' => env('HORIZON_PATH', 'horizon'), 32 | 33 | /* 34 | |-------------------------------------------------------------------------- 35 | | Horizon Redis Connection 36 | |-------------------------------------------------------------------------- 37 | | 38 | | This is the name of the Redis connection where Horizon will store the 39 | | meta information required for it to function. It includes the list 40 | | of supervisors, failed jobs, job metrics, and other information. 41 | | 42 | */ 43 | 44 | 'use' => 'default', 45 | 46 | /* 47 | |-------------------------------------------------------------------------- 48 | | Horizon Redis Prefix 49 | |-------------------------------------------------------------------------- 50 | | 51 | | This prefix will be used when storing all Horizon data in Redis. You 52 | | may modify the prefix when you are running multiple installations 53 | | of Horizon on the same server so that they don't have problems. 54 | | 55 | */ 56 | 57 | 'prefix' => env( 58 | 'HORIZON_PREFIX', 59 | Str::slug(env('APP_NAME', 'laravel'), '_').'_horizon:' 60 | ), 61 | 62 | /* 63 | |-------------------------------------------------------------------------- 64 | | Horizon Route Middleware 65 | |-------------------------------------------------------------------------- 66 | | 67 | | These middleware will get attached onto each Horizon route, giving you 68 | | the chance to add your own middleware to this list or change any of 69 | | the existing middleware. Or, you can simply stick with this list. 70 | | 71 | */ 72 | 73 | 'middleware' => ['web'], 74 | 75 | /* 76 | |-------------------------------------------------------------------------- 77 | | Queue Wait Time Thresholds 78 | |-------------------------------------------------------------------------- 79 | | 80 | | This option allows you to configure when the LongWaitDetected event 81 | | will be fired. Every connection / queue combination may have its 82 | | own, unique threshold (in seconds) before this event is fired. 83 | | 84 | */ 85 | 86 | 'waits' => [ 87 | 'redis:default' => 60, 88 | ], 89 | 90 | /* 91 | |-------------------------------------------------------------------------- 92 | | Job Trimming Times 93 | |-------------------------------------------------------------------------- 94 | | 95 | | Here you can configure for how long (in minutes) you desire Horizon to 96 | | persist the recent and failed jobs. Typically, recent jobs are kept 97 | | for one hour while all failed jobs are stored for an entire week. 98 | | 99 | */ 100 | 101 | 'trim' => [ 102 | 'recent' => 60, 103 | 'pending' => 60, 104 | 'completed' => 60, 105 | 'recent_failed' => 10080, 106 | 'failed' => 10080, 107 | 'monitored' => 10080, 108 | ], 109 | 110 | /* 111 | |-------------------------------------------------------------------------- 112 | | Metrics 113 | |-------------------------------------------------------------------------- 114 | | 115 | | Here you can configure how many snapshots should be kept to display in 116 | | the metrics graph. This will get used in combination with Horizon's 117 | | `horizon:snapshot` schedule to define how long to retain metrics. 118 | | 119 | */ 120 | 121 | 'metrics' => [ 122 | 'trim_snapshots' => [ 123 | 'job' => 24, 124 | 'queue' => 24, 125 | ], 126 | ], 127 | 128 | /* 129 | |-------------------------------------------------------------------------- 130 | | Fast Termination 131 | |-------------------------------------------------------------------------- 132 | | 133 | | When this option is enabled, Horizon's "terminate" command will not 134 | | wait on all of the workers to terminate unless the --wait option 135 | | is provided. Fast termination can shorten deployment delay by 136 | | allowing a new instance of Horizon to start while the last 137 | | instance will continue to terminate each of its workers. 138 | | 139 | */ 140 | 141 | 'fast_termination' => false, 142 | 143 | /* 144 | |-------------------------------------------------------------------------- 145 | | Memory Limit (MB) 146 | |-------------------------------------------------------------------------- 147 | | 148 | | This value describes the maximum amount of memory the Horizon master 149 | | supervisor may consume before it is terminated and restarted. For 150 | | configuring these limits on your workers, see the next section. 151 | | 152 | */ 153 | 154 | 'memory_limit' => 64, 155 | 156 | /* 157 | |-------------------------------------------------------------------------- 158 | | Queue Worker Configuration 159 | |-------------------------------------------------------------------------- 160 | | 161 | | Here you may define the queue worker settings used by your application 162 | | in all environments. These supervisors and settings handle all your 163 | | queued jobs and will be provisioned by Horizon during deployment. 164 | | 165 | */ 166 | 167 | 'defaults' => [ 168 | 'supervisor-1' => [ 169 | 'connection' => 'redis', 170 | 'queue' => ['default'], 171 | 'balance' => 'auto', 172 | 'maxProcesses' => 1, 173 | 'memory' => 128, 174 | 'tries' => 1, 175 | 'nice' => 0, 176 | ], 177 | ], 178 | 179 | 'environments' => [ 180 | 'production' => [ 181 | 'supervisor-1' => [ 182 | 'maxProcesses' => 10, 183 | 'balanceMaxShift' => 1, 184 | 'balanceCooldown' => 3, 185 | ], 186 | ], 187 | 188 | 'local' => [ 189 | 'supervisor-1' => [ 190 | 'maxProcesses' => 3, 191 | ], 192 | ], 193 | ], 194 | ]; 195 | -------------------------------------------------------------------------------- /src/config/logging.php: -------------------------------------------------------------------------------- 1 | env('LOG_CHANNEL', 'stack'), 21 | 22 | /* 23 | |-------------------------------------------------------------------------- 24 | | Log Channels 25 | |-------------------------------------------------------------------------- 26 | | 27 | | Here you may configure the log channels for your application. Out of 28 | | the box, Laravel uses the Monolog PHP logging library. This gives 29 | | you a variety of powerful log handlers / formatters to utilize. 30 | | 31 | | Available Drivers: "single", "daily", "slack", "syslog", 32 | | "errorlog", "monolog", 33 | | "custom", "stack" 34 | | 35 | */ 36 | 37 | 'channels' => [ 38 | 'stack' => [ 39 | 'driver' => 'stack', 40 | 'channels' => ['single'], 41 | 'ignore_exceptions' => false, 42 | ], 43 | 44 | 'single' => [ 45 | 'driver' => 'single', 46 | 'path' => storage_path('logs/laravel.log'), 47 | 'level' => env('LOG_LEVEL', 'debug'), 48 | ], 49 | 50 | 'daily' => [ 51 | 'driver' => 'daily', 52 | 'path' => storage_path('logs/laravel.log'), 53 | 'level' => env('LOG_LEVEL', 'debug'), 54 | 'days' => 14, 55 | ], 56 | 57 | 'slack' => [ 58 | 'driver' => 'slack', 59 | 'url' => env('LOG_SLACK_WEBHOOK_URL'), 60 | 'username' => 'Laravel Log', 61 | 'emoji' => ':boom:', 62 | 'level' => env('LOG_LEVEL', 'critical'), 63 | ], 64 | 65 | 'papertrail' => [ 66 | 'driver' => 'monolog', 67 | 'level' => env('LOG_LEVEL', 'debug'), 68 | 'handler' => SyslogUdpHandler::class, 69 | 'handler_with' => [ 70 | 'host' => env('PAPERTRAIL_URL'), 71 | 'port' => env('PAPERTRAIL_PORT'), 72 | ], 73 | ], 74 | 75 | 'stderr' => [ 76 | 'driver' => 'monolog', 77 | 'level' => env('LOG_LEVEL', 'debug'), 78 | 'handler' => StreamHandler::class, 79 | 'formatter' => env('LOG_STDERR_FORMATTER'), 80 | 'with' => [ 81 | 'stream' => 'php://stderr', 82 | ], 83 | ], 84 | 85 | 'syslog' => [ 86 | 'driver' => 'syslog', 87 | 'level' => env('LOG_LEVEL', 'debug'), 88 | ], 89 | 90 | 'errorlog' => [ 91 | 'driver' => 'errorlog', 92 | 'level' => env('LOG_LEVEL', 'debug'), 93 | ], 94 | 95 | 'null' => [ 96 | 'driver' => 'monolog', 97 | 'handler' => NullHandler::class, 98 | ], 99 | 100 | 'emergency' => [ 101 | 'path' => storage_path('logs/laravel.log'), 102 | ], 103 | ], 104 | 105 | ]; 106 | -------------------------------------------------------------------------------- /src/config/mail.php: -------------------------------------------------------------------------------- 1 | env('MAIL_MAILER', 'smtp'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Mailer Configurations 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure all of the mailers used by your application plus 24 | | their respective settings. Several examples have been configured for 25 | | you and you are free to add your own as your application requires. 26 | | 27 | | Laravel supports a variety of mail "transport" drivers to be used while 28 | | sending an e-mail. You will specify which one you are using for your 29 | | mailers below. You are free to add additional mailers as required. 30 | | 31 | | Supported: "smtp", "sendmail", "mailgun", "ses", 32 | | "postmark", "log", "array" 33 | | 34 | */ 35 | 36 | 'mailers' => [ 37 | 'smtp' => [ 38 | 'transport' => 'smtp', 39 | 'host' => env('MAIL_HOST', 'smtp.mailgun.org'), 40 | 'port' => env('MAIL_PORT', 587), 41 | 'encryption' => env('MAIL_ENCRYPTION', 'tls'), 42 | 'username' => env('MAIL_USERNAME'), 43 | 'password' => env('MAIL_PASSWORD'), 44 | 'timeout' => null, 45 | 'auth_mode' => null, 46 | ], 47 | 48 | 'ses' => [ 49 | 'transport' => 'ses', 50 | ], 51 | 52 | 'mailgun' => [ 53 | 'transport' => 'mailgun', 54 | ], 55 | 56 | 'postmark' => [ 57 | 'transport' => 'postmark', 58 | ], 59 | 60 | 'sendmail' => [ 61 | 'transport' => 'sendmail', 62 | 'path' => '/usr/sbin/sendmail -bs', 63 | ], 64 | 65 | 'log' => [ 66 | 'transport' => 'log', 67 | 'channel' => env('MAIL_LOG_CHANNEL'), 68 | ], 69 | 70 | 'array' => [ 71 | 'transport' => 'array', 72 | ], 73 | ], 74 | 75 | /* 76 | |-------------------------------------------------------------------------- 77 | | Global "From" Address 78 | |-------------------------------------------------------------------------- 79 | | 80 | | You may wish for all e-mails sent by your application to be sent from 81 | | the same address. Here, you may specify a name and address that is 82 | | used globally for all e-mails that are sent by your application. 83 | | 84 | */ 85 | 86 | 'from' => [ 87 | 'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'), 88 | 'name' => env('MAIL_FROM_NAME', 'Example'), 89 | ], 90 | 91 | /* 92 | |-------------------------------------------------------------------------- 93 | | Markdown Mail Settings 94 | |-------------------------------------------------------------------------- 95 | | 96 | | If you are using Markdown based email rendering, you may configure your 97 | | theme and component paths here, allowing you to customize the design 98 | | of the emails. Or, you may simply stick with the Laravel defaults! 99 | | 100 | */ 101 | 102 | 'markdown' => [ 103 | 'theme' => 'default', 104 | 105 | 'paths' => [ 106 | resource_path('views/vendor/mail'), 107 | ], 108 | ], 109 | 110 | ]; 111 | -------------------------------------------------------------------------------- /src/config/queue.php: -------------------------------------------------------------------------------- 1 | env('QUEUE_CONNECTION', 'sync'), 17 | 18 | /* 19 | |-------------------------------------------------------------------------- 20 | | Queue Connections 21 | |-------------------------------------------------------------------------- 22 | | 23 | | Here you may configure the connection information for each server that 24 | | is used by your application. A default configuration has been added 25 | | for each back-end shipped with Laravel. You are free to add more. 26 | | 27 | | Drivers: "sync", "database", "beanstalkd", "sqs", "redis", "null" 28 | | 29 | */ 30 | 31 | 'connections' => [ 32 | 33 | 'sync' => [ 34 | 'driver' => 'sync', 35 | ], 36 | 37 | 'database' => [ 38 | 'driver' => 'database', 39 | 'table' => 'jobs', 40 | 'queue' => 'default', 41 | 'retry_after' => 90, 42 | 'after_commit' => false, 43 | ], 44 | 45 | 'beanstalkd' => [ 46 | 'driver' => 'beanstalkd', 47 | 'host' => 'localhost', 48 | 'queue' => 'default', 49 | 'retry_after' => 90, 50 | 'block_for' => 0, 51 | 'after_commit' => false, 52 | ], 53 | 54 | 'sqs' => [ 55 | 'driver' => 'sqs', 56 | 'key' => env('AWS_ACCESS_KEY_ID'), 57 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 58 | 'prefix' => env('SQS_PREFIX', 'https://sqs.us-east-1.amazonaws.com/your-account-id'), 59 | 'queue' => env('SQS_QUEUE', 'default'), 60 | 'suffix' => env('SQS_SUFFIX'), 61 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 62 | 'after_commit' => false, 63 | ], 64 | 65 | 'redis' => [ 66 | 'driver' => 'redis', 67 | 'connection' => 'default', 68 | 'queue' => env('REDIS_QUEUE', 'default'), 69 | 'retry_after' => 90, 70 | 'block_for' => null, 71 | 'after_commit' => false, 72 | ], 73 | 74 | ], 75 | 76 | /* 77 | |-------------------------------------------------------------------------- 78 | | Failed Queue Jobs 79 | |-------------------------------------------------------------------------- 80 | | 81 | | These options configure the behavior of failed queue job logging so you 82 | | can control which database and table are used to store the jobs that 83 | | have failed. You may change them to any database / table you wish. 84 | | 85 | */ 86 | 87 | 'failed' => [ 88 | 'driver' => env('QUEUE_FAILED_DRIVER', 'database-uuids'), 89 | 'database' => env('DB_CONNECTION', 'mysql'), 90 | 'table' => 'failed_jobs', 91 | ], 92 | 93 | ]; 94 | -------------------------------------------------------------------------------- /src/config/services.php: -------------------------------------------------------------------------------- 1 | [ 18 | 'domain' => env('MAILGUN_DOMAIN'), 19 | 'secret' => env('MAILGUN_SECRET'), 20 | 'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'), 21 | ], 22 | 23 | 'postmark' => [ 24 | 'token' => env('POSTMARK_TOKEN'), 25 | ], 26 | 27 | 'ses' => [ 28 | 'key' => env('AWS_ACCESS_KEY_ID'), 29 | 'secret' => env('AWS_SECRET_ACCESS_KEY'), 30 | 'region' => env('AWS_DEFAULT_REGION', 'us-east-1'), 31 | ], 32 | 33 | ]; 34 | -------------------------------------------------------------------------------- /src/config/session.php: -------------------------------------------------------------------------------- 1 | env('SESSION_DRIVER', 'file'), 22 | 23 | /* 24 | |-------------------------------------------------------------------------- 25 | | Session Lifetime 26 | |-------------------------------------------------------------------------- 27 | | 28 | | Here you may specify the number of minutes that you wish the session 29 | | to be allowed to remain idle before it expires. If you want them 30 | | to immediately expire on the browser closing, set that option. 31 | | 32 | */ 33 | 34 | 'lifetime' => env('SESSION_LIFETIME', 120), 35 | 36 | 'expire_on_close' => false, 37 | 38 | /* 39 | |-------------------------------------------------------------------------- 40 | | Session Encryption 41 | |-------------------------------------------------------------------------- 42 | | 43 | | This option allows you to easily specify that all of your session data 44 | | should be encrypted before it is stored. All encryption will be run 45 | | automatically by Laravel and you can use the Session like normal. 46 | | 47 | */ 48 | 49 | 'encrypt' => false, 50 | 51 | /* 52 | |-------------------------------------------------------------------------- 53 | | Session File Location 54 | |-------------------------------------------------------------------------- 55 | | 56 | | When using the native session driver, we need a location where session 57 | | files may be stored. A default has been set for you but a different 58 | | location may be specified. This is only needed for file sessions. 59 | | 60 | */ 61 | 62 | 'files' => storage_path('framework/sessions'), 63 | 64 | /* 65 | |-------------------------------------------------------------------------- 66 | | Session Database Connection 67 | |-------------------------------------------------------------------------- 68 | | 69 | | When using the "database" or "redis" session drivers, you may specify a 70 | | connection that should be used to manage these sessions. This should 71 | | correspond to a connection in your database configuration options. 72 | | 73 | */ 74 | 75 | 'connection' => env('SESSION_CONNECTION', null), 76 | 77 | /* 78 | |-------------------------------------------------------------------------- 79 | | Session Database Table 80 | |-------------------------------------------------------------------------- 81 | | 82 | | When using the "database" session driver, you may specify the table we 83 | | should use to manage the sessions. Of course, a sensible default is 84 | | provided for you; however, you are free to change this as needed. 85 | | 86 | */ 87 | 88 | 'table' => 'sessions', 89 | 90 | /* 91 | |-------------------------------------------------------------------------- 92 | | Session Cache Store 93 | |-------------------------------------------------------------------------- 94 | | 95 | | While using one of the framework's cache driven session backends you may 96 | | list a cache store that should be used for these sessions. This value 97 | | must match with one of the application's configured cache "stores". 98 | | 99 | | Affects: "apc", "dynamodb", "memcached", "redis" 100 | | 101 | */ 102 | 103 | 'store' => env('SESSION_STORE', null), 104 | 105 | /* 106 | |-------------------------------------------------------------------------- 107 | | Session Sweeping Lottery 108 | |-------------------------------------------------------------------------- 109 | | 110 | | Some session drivers must manually sweep their storage location to get 111 | | rid of old sessions from storage. Here are the chances that it will 112 | | happen on a given request. By default, the odds are 2 out of 100. 113 | | 114 | */ 115 | 116 | 'lottery' => [2, 100], 117 | 118 | /* 119 | |-------------------------------------------------------------------------- 120 | | Session Cookie Name 121 | |-------------------------------------------------------------------------- 122 | | 123 | | Here you may change the name of the cookie used to identify a session 124 | | instance by ID. The name specified here will get used every time a 125 | | new session cookie is created by the framework for every driver. 126 | | 127 | */ 128 | 129 | 'cookie' => env( 130 | 'SESSION_COOKIE', 131 | Str::slug(env('APP_NAME', 'laravel'), '_').'_session' 132 | ), 133 | 134 | /* 135 | |-------------------------------------------------------------------------- 136 | | Session Cookie Path 137 | |-------------------------------------------------------------------------- 138 | | 139 | | The session cookie path determines the path for which the cookie will 140 | | be regarded as available. Typically, this will be the root path of 141 | | your application but you are free to change this when necessary. 142 | | 143 | */ 144 | 145 | 'path' => '/', 146 | 147 | /* 148 | |-------------------------------------------------------------------------- 149 | | Session Cookie Domain 150 | |-------------------------------------------------------------------------- 151 | | 152 | | Here you may change the domain of the cookie used to identify a session 153 | | in your application. This will determine which domains the cookie is 154 | | available to in your application. A sensible default has been set. 155 | | 156 | */ 157 | 158 | 'domain' => env('SESSION_DOMAIN', null), 159 | 160 | /* 161 | |-------------------------------------------------------------------------- 162 | | HTTPS Only Cookies 163 | |-------------------------------------------------------------------------- 164 | | 165 | | By setting this option to true, session cookies will only be sent back 166 | | to the server if the browser has a HTTPS connection. This will keep 167 | | the cookie from being sent to you when it can't be done securely. 168 | | 169 | */ 170 | 171 | 'secure' => env('SESSION_SECURE_COOKIE'), 172 | 173 | /* 174 | |-------------------------------------------------------------------------- 175 | | HTTP Access Only 176 | |-------------------------------------------------------------------------- 177 | | 178 | | Setting this value to true will prevent JavaScript from accessing the 179 | | value of the cookie and the cookie will only be accessible through 180 | | the HTTP protocol. You are free to modify this option if needed. 181 | | 182 | */ 183 | 184 | 'http_only' => true, 185 | 186 | /* 187 | |-------------------------------------------------------------------------- 188 | | Same-Site Cookies 189 | |-------------------------------------------------------------------------- 190 | | 191 | | This option determines how your cookies behave when cross-site requests 192 | | take place, and can be used to mitigate CSRF attacks. By default, we 193 | | will set this value to "lax" since this is a secure default value. 194 | | 195 | | Supported: "lax", "strict", "none", null 196 | | 197 | */ 198 | 199 | 'same_site' => 'lax', 200 | 201 | ]; 202 | -------------------------------------------------------------------------------- /src/config/view.php: -------------------------------------------------------------------------------- 1 | [ 17 | resource_path('views'), 18 | ], 19 | 20 | /* 21 | |-------------------------------------------------------------------------- 22 | | Compiled View Path 23 | |-------------------------------------------------------------------------- 24 | | 25 | | This option determines where all the compiled Blade templates will be 26 | | stored for your application. Typically, this is within the storage 27 | | directory. However, as usual, you are free to change this value. 28 | | 29 | */ 30 | 31 | 'compiled' => env( 32 | 'VIEW_COMPILED_PATH', 33 | realpath(storage_path('framework/views')) 34 | ), 35 | 36 | ]; 37 | -------------------------------------------------------------------------------- /src/database/.gitignore: -------------------------------------------------------------------------------- 1 | *.sqlite* 2 | -------------------------------------------------------------------------------- /src/database/factories/UserFactory.php: -------------------------------------------------------------------------------- 1 | $this->faker->name(), 27 | 'email' => $this->faker->unique()->safeEmail(), 28 | 'email_verified_at' => now(), 29 | 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 30 | 'remember_token' => Str::random(10), 31 | ]; 32 | } 33 | 34 | /** 35 | * Indicate that the model's email address should be unverified. 36 | * 37 | * @return \Illuminate\Database\Eloquent\Factories\Factory 38 | */ 39 | public function unverified() 40 | { 41 | return $this->state(function (array $attributes) { 42 | return [ 43 | 'email_verified_at' => null, 44 | ]; 45 | }); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/database/migrations/2014_10_12_000000_create_users_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('name'); 19 | $table->string('email')->unique(); 20 | $table->timestamp('email_verified_at')->nullable(); 21 | $table->string('password'); 22 | $table->rememberToken(); 23 | $table->timestamps(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('users'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/database/migrations/2014_10_12_100000_create_password_resets_table.php: -------------------------------------------------------------------------------- 1 | string('email')->index(); 18 | $table->string('token'); 19 | $table->timestamp('created_at')->nullable(); 20 | }); 21 | } 22 | 23 | /** 24 | * Reverse the migrations. 25 | * 26 | * @return void 27 | */ 28 | public function down() 29 | { 30 | Schema::dropIfExists('password_resets'); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/database/migrations/2019_08_19_000000_create_failed_jobs_table.php: -------------------------------------------------------------------------------- 1 | id(); 18 | $table->string('uuid')->unique(); 19 | $table->text('connection'); 20 | $table->text('queue'); 21 | $table->longText('payload'); 22 | $table->longText('exception'); 23 | $table->timestamp('failed_at')->useCurrent(); 24 | }); 25 | } 26 | 27 | /** 28 | * Reverse the migrations. 29 | * 30 | * @return void 31 | */ 32 | public function down() 33 | { 34 | Schema::dropIfExists('failed_jobs'); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/database/seeders/DatabaseSeeder.php: -------------------------------------------------------------------------------- 1 | create(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "dev": "npm run development", 5 | "development": "mix", 6 | "watch": "mix watch", 7 | "watch-poll": "mix watch -- --watch-options-poll=1000", 8 | "hot": "mix watch --hot", 9 | "prod": "npm run production", 10 | "production": "mix --production" 11 | }, 12 | "devDependencies": { 13 | "axios": "^0.21", 14 | "laravel-mix": "^6.0.6", 15 | "lodash": "^4.17.19", 16 | "postcss": "^8.1.14" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | ./tests/Unit 10 | 11 | 12 | ./tests/Feature 13 | 14 | 15 | 16 | 17 | ./app 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | 3 | Options -MultiViews -Indexes 4 | 5 | 6 | RewriteEngine On 7 | 8 | # Handle Authorization Header 9 | RewriteCond %{HTTP:Authorization} . 10 | RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}] 11 | 12 | # Redirect Trailing Slashes If Not A Folder... 13 | RewriteCond %{REQUEST_FILENAME} !-d 14 | RewriteCond %{REQUEST_URI} (.+)/$ 15 | RewriteRule ^ %1 [L,R=301] 16 | 17 | # Send Requests To Front Controller... 18 | RewriteCond %{REQUEST_FILENAME} !-d 19 | RewriteCond %{REQUEST_FILENAME} !-f 20 | RewriteRule ^ index.php [L] 21 | 22 | -------------------------------------------------------------------------------- /src/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jarnovanleeuwen/laravel-dock/c34525190c073f75b737d6f7265913dad00fcc69/src/public/favicon.ico -------------------------------------------------------------------------------- /src/public/index.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class); 50 | 51 | $response = tap($kernel->handle( 52 | $request = Request::capture() 53 | ))->send(); 54 | 55 | $kernel->terminate($request, $response); 56 | -------------------------------------------------------------------------------- /src/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: 3 | -------------------------------------------------------------------------------- /src/public/vendor/horizon/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jarnovanleeuwen/laravel-dock/c34525190c073f75b737d6f7265913dad00fcc69/src/public/vendor/horizon/img/favicon.png -------------------------------------------------------------------------------- /src/public/vendor/horizon/img/horizon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/public/vendor/horizon/mix-manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "/app.js": "/app.js?id=d33e0bb4038cbbc2466e", 3 | "/app-dark.css": "/app-dark.css?id=ade35296e4fa0c99a758", 4 | "/app.css": "/app.css?id=c14814cc1a7a4f298934", 5 | "/img/favicon.png": "/img/favicon.png?id=1542bfe8a0010dcbee71" 6 | } 7 | -------------------------------------------------------------------------------- /src/public/web.config: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/resources/css/app.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jarnovanleeuwen/laravel-dock/c34525190c073f75b737d6f7265913dad00fcc69/src/resources/css/app.css -------------------------------------------------------------------------------- /src/resources/js/app.js: -------------------------------------------------------------------------------- 1 | require('./bootstrap'); 2 | -------------------------------------------------------------------------------- /src/resources/js/bootstrap.js: -------------------------------------------------------------------------------- 1 | window._ = require('lodash'); 2 | 3 | /** 4 | * We'll load the axios HTTP library which allows us to easily issue requests 5 | * to our Laravel back-end. This library automatically handles sending the 6 | * CSRF token as a header based on the value of the "XSRF" token cookie. 7 | */ 8 | 9 | window.axios = require('axios'); 10 | 11 | window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; 12 | 13 | /** 14 | * Echo exposes an expressive API for subscribing to channels and listening 15 | * for events that are broadcast by Laravel. Echo and event broadcasting 16 | * allows your team to easily build robust real-time web applications. 17 | */ 18 | 19 | // import Echo from 'laravel-echo'; 20 | 21 | // window.Pusher = require('pusher-js'); 22 | 23 | // window.Echo = new Echo({ 24 | // broadcaster: 'pusher', 25 | // key: process.env.MIX_PUSHER_APP_KEY, 26 | // cluster: process.env.MIX_PUSHER_APP_CLUSTER, 27 | // forceTLS: true 28 | // }); 29 | -------------------------------------------------------------------------------- /src/resources/lang/en/auth.php: -------------------------------------------------------------------------------- 1 | 'These credentials do not match our records.', 17 | 'password' => 'The provided password is incorrect.', 18 | 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 19 | 20 | ]; 21 | -------------------------------------------------------------------------------- /src/resources/lang/en/pagination.php: -------------------------------------------------------------------------------- 1 | '« Previous', 17 | 'next' => 'Next »', 18 | 19 | ]; 20 | -------------------------------------------------------------------------------- /src/resources/lang/en/passwords.php: -------------------------------------------------------------------------------- 1 | 'Your password has been reset!', 17 | 'sent' => 'We have emailed your password reset link!', 18 | 'throttled' => 'Please wait before retrying.', 19 | 'token' => 'This password reset token is invalid.', 20 | 'user' => "We can't find a user with that email address.", 21 | 22 | ]; 23 | -------------------------------------------------------------------------------- /src/resources/lang/en/validation.php: -------------------------------------------------------------------------------- 1 | 'The :attribute must be accepted.', 17 | 'active_url' => 'The :attribute is not a valid URL.', 18 | 'after' => 'The :attribute must be a date after :date.', 19 | 'after_or_equal' => 'The :attribute must be a date after or equal to :date.', 20 | 'alpha' => 'The :attribute must only contain letters.', 21 | 'alpha_dash' => 'The :attribute must only contain letters, numbers, dashes and underscores.', 22 | 'alpha_num' => 'The :attribute must only contain letters and numbers.', 23 | 'array' => 'The :attribute must be an array.', 24 | 'before' => 'The :attribute must be a date before :date.', 25 | 'before_or_equal' => 'The :attribute must be a date before or equal to :date.', 26 | 'between' => [ 27 | 'numeric' => 'The :attribute must be between :min and :max.', 28 | 'file' => 'The :attribute must be between :min and :max kilobytes.', 29 | 'string' => 'The :attribute must be between :min and :max characters.', 30 | 'array' => 'The :attribute must have between :min and :max items.', 31 | ], 32 | 'boolean' => 'The :attribute field must be true or false.', 33 | 'confirmed' => 'The :attribute confirmation does not match.', 34 | 'current_password' => 'The password is incorrect.', 35 | 'date' => 'The :attribute is not a valid date.', 36 | 'date_equals' => 'The :attribute must be a date equal to :date.', 37 | 'date_format' => 'The :attribute does not match the format :format.', 38 | 'different' => 'The :attribute and :other must be different.', 39 | 'digits' => 'The :attribute must be :digits digits.', 40 | 'digits_between' => 'The :attribute must be between :min and :max digits.', 41 | 'dimensions' => 'The :attribute has invalid image dimensions.', 42 | 'distinct' => 'The :attribute field has a duplicate value.', 43 | 'email' => 'The :attribute must be a valid email address.', 44 | 'ends_with' => 'The :attribute must end with one of the following: :values.', 45 | 'exists' => 'The selected :attribute is invalid.', 46 | 'file' => 'The :attribute must be a file.', 47 | 'filled' => 'The :attribute field must have a value.', 48 | 'gt' => [ 49 | 'numeric' => 'The :attribute must be greater than :value.', 50 | 'file' => 'The :attribute must be greater than :value kilobytes.', 51 | 'string' => 'The :attribute must be greater than :value characters.', 52 | 'array' => 'The :attribute must have more than :value items.', 53 | ], 54 | 'gte' => [ 55 | 'numeric' => 'The :attribute must be greater than or equal :value.', 56 | 'file' => 'The :attribute must be greater than or equal :value kilobytes.', 57 | 'string' => 'The :attribute must be greater than or equal :value characters.', 58 | 'array' => 'The :attribute must have :value items or more.', 59 | ], 60 | 'image' => 'The :attribute must be an image.', 61 | 'in' => 'The selected :attribute is invalid.', 62 | 'in_array' => 'The :attribute field does not exist in :other.', 63 | 'integer' => 'The :attribute must be an integer.', 64 | 'ip' => 'The :attribute must be a valid IP address.', 65 | 'ipv4' => 'The :attribute must be a valid IPv4 address.', 66 | 'ipv6' => 'The :attribute must be a valid IPv6 address.', 67 | 'json' => 'The :attribute must be a valid JSON string.', 68 | 'lt' => [ 69 | 'numeric' => 'The :attribute must be less than :value.', 70 | 'file' => 'The :attribute must be less than :value kilobytes.', 71 | 'string' => 'The :attribute must be less than :value characters.', 72 | 'array' => 'The :attribute must have less than :value items.', 73 | ], 74 | 'lte' => [ 75 | 'numeric' => 'The :attribute must be less than or equal :value.', 76 | 'file' => 'The :attribute must be less than or equal :value kilobytes.', 77 | 'string' => 'The :attribute must be less than or equal :value characters.', 78 | 'array' => 'The :attribute must not have more than :value items.', 79 | ], 80 | 'max' => [ 81 | 'numeric' => 'The :attribute must not be greater than :max.', 82 | 'file' => 'The :attribute must not be greater than :max kilobytes.', 83 | 'string' => 'The :attribute must not be greater than :max characters.', 84 | 'array' => 'The :attribute must not have more than :max items.', 85 | ], 86 | 'mimes' => 'The :attribute must be a file of type: :values.', 87 | 'mimetypes' => 'The :attribute must be a file of type: :values.', 88 | 'min' => [ 89 | 'numeric' => 'The :attribute must be at least :min.', 90 | 'file' => 'The :attribute must be at least :min kilobytes.', 91 | 'string' => 'The :attribute must be at least :min characters.', 92 | 'array' => 'The :attribute must have at least :min items.', 93 | ], 94 | 'multiple_of' => 'The :attribute must be a multiple of :value.', 95 | 'not_in' => 'The selected :attribute is invalid.', 96 | 'not_regex' => 'The :attribute format is invalid.', 97 | 'numeric' => 'The :attribute must be a number.', 98 | 'password' => 'The password is incorrect.', 99 | 'present' => 'The :attribute field must be present.', 100 | 'regex' => 'The :attribute format is invalid.', 101 | 'required' => 'The :attribute field is required.', 102 | 'required_if' => 'The :attribute field is required when :other is :value.', 103 | 'required_unless' => 'The :attribute field is required unless :other is in :values.', 104 | 'required_with' => 'The :attribute field is required when :values is present.', 105 | 'required_with_all' => 'The :attribute field is required when :values are present.', 106 | 'required_without' => 'The :attribute field is required when :values is not present.', 107 | 'required_without_all' => 'The :attribute field is required when none of :values are present.', 108 | 'prohibited' => 'The :attribute field is prohibited.', 109 | 'prohibited_if' => 'The :attribute field is prohibited when :other is :value.', 110 | 'prohibited_unless' => 'The :attribute field is prohibited unless :other is in :values.', 111 | 'same' => 'The :attribute and :other must match.', 112 | 'size' => [ 113 | 'numeric' => 'The :attribute must be :size.', 114 | 'file' => 'The :attribute must be :size kilobytes.', 115 | 'string' => 'The :attribute must be :size characters.', 116 | 'array' => 'The :attribute must contain :size items.', 117 | ], 118 | 'starts_with' => 'The :attribute must start with one of the following: :values.', 119 | 'string' => 'The :attribute must be a string.', 120 | 'timezone' => 'The :attribute must be a valid zone.', 121 | 'unique' => 'The :attribute has already been taken.', 122 | 'uploaded' => 'The :attribute failed to upload.', 123 | 'url' => 'The :attribute format is invalid.', 124 | 'uuid' => 'The :attribute must be a valid UUID.', 125 | 126 | /* 127 | |-------------------------------------------------------------------------- 128 | | Custom Validation Language Lines 129 | |-------------------------------------------------------------------------- 130 | | 131 | | Here you may specify custom validation messages for attributes using the 132 | | convention "attribute.rule" to name the lines. This makes it quick to 133 | | specify a specific custom language line for a given attribute rule. 134 | | 135 | */ 136 | 137 | 'custom' => [ 138 | 'attribute-name' => [ 139 | 'rule-name' => 'custom-message', 140 | ], 141 | ], 142 | 143 | /* 144 | |-------------------------------------------------------------------------- 145 | | Custom Validation Attributes 146 | |-------------------------------------------------------------------------- 147 | | 148 | | The following language lines are used to swap our attribute placeholder 149 | | with something more reader friendly such as "E-Mail Address" instead 150 | | of "email". This simply helps us make our message more expressive. 151 | | 152 | */ 153 | 154 | 'attributes' => [], 155 | 156 | ]; 157 | -------------------------------------------------------------------------------- /src/resources/views/status.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | laravel-dock status 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 |
Time{{ Carbon\carbon::now()->format('c') }}
Client{{ request()->ip() }}
Server{{ request()->server('SERVER_ADDR') }}:{{ request()->server('SERVER_PORT') }} ({{ request()->server('SERVER_NAME') }})
Database Driver{{ config('database.connections.'.config('database.default').'.driver') }}
Database Server{{ config('database.connections.'.config('database.default').'.host') }}:{{ config('database.connections.'.config('database.default').'.port') }}
Database Migrations 36 |
    37 | @foreach($migrations as $migration) 38 |
  1. {{ $migration }}
  2. 39 | @endforeach 40 |
41 |
Cache Driver{{ config('cache.stores.'.config('cache.default').'.driver') }}
Queue Driver{{ config('queue.connections.'.config('queue.default').'.driver') }}
Cache Test{{ Cache::remember('cache-test', 1, function () { return Carbon\carbon::now()->format('H:i:s'); }) }} (TTL: 1 minute)
Scheduler Test{{ Cache::get('increment-requests', 0) }} jobs dispatched
Queue Test{{ Cache::get('counter', 0) }} jobs handled
65 |
66 | 67 | 68 | -------------------------------------------------------------------------------- /src/resources/views/welcome.blade.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Laravel 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 22 | 23 | 24 |
25 | @if (Route::has('login')) 26 | 37 | @endif 38 | 39 |
40 |
41 | 42 | 43 | 44 | 45 | 46 |
47 | 48 |
49 |
50 |
51 |
52 | 53 | 54 |
55 | 56 |
57 |
58 | Laravel has wonderful, thorough documentation covering every aspect of the framework. Whether you are new to the framework or have previous experience with Laravel, we recommend reading all of the documentation from beginning to end. 59 |
60 |
61 |
62 | 63 |
64 |
65 | 66 | 67 |
68 | 69 |
70 |
71 | Laracasts offers thousands of video tutorials on Laravel, PHP, and JavaScript development. Check them out, see for yourself, and massively level up your development skills in the process. 72 |
73 |
74 |
75 | 76 |
77 |
78 | 79 | 80 |
81 | 82 |
83 |
84 | Laravel News is a community driven portal and newsletter aggregating all of the latest and most important news in the Laravel ecosystem, including new package releases and tutorials. 85 |
86 |
87 |
88 | 89 |
90 |
91 | 92 |
Vibrant Ecosystem
93 |
94 | 95 |
96 |
97 | Laravel's robust library of first-party tools and libraries, such as Forge, Vapor, Nova, and Envoyer help you take your projects to the next level. Pair them with powerful open source libraries like Cashier, Dusk, Echo, Horizon, Sanctum, Telescope, and more. 98 |
99 |
100 |
101 |
102 |
103 | 104 |
105 |
106 |
107 | 108 | 109 | 110 | 111 | 112 | Shop 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | Sponsor 121 | 122 |
123 |
124 | 125 |
126 | Laravel v{{ Illuminate\Foundation\Application::VERSION }} (PHP v{{ PHP_VERSION }}) 127 |
128 |
129 |
130 |
131 | 132 | 133 | -------------------------------------------------------------------------------- /src/routes/api.php: -------------------------------------------------------------------------------- 1 | get('/user', function (Request $request) { 18 | return $request->user(); 19 | }); 20 | -------------------------------------------------------------------------------- /src/routes/channels.php: -------------------------------------------------------------------------------- 1 | id === (int) $id; 18 | }); 19 | -------------------------------------------------------------------------------- /src/routes/console.php: -------------------------------------------------------------------------------- 1 | comment(Inspiring::quote()); 19 | })->purpose('Display an inspiring quote'); 20 | -------------------------------------------------------------------------------- /src/routes/web.php: -------------------------------------------------------------------------------- 1 | DB::table('migrations')->orderBy('id')->pluck('migration') 19 | ]); 20 | }); 21 | -------------------------------------------------------------------------------- /src/server.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | $uri = urldecode( 11 | parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) 12 | ); 13 | 14 | // This file allows us to emulate Apache's "mod_rewrite" functionality from the 15 | // built-in PHP web server. This provides a convenient way to test a Laravel 16 | // application without having installed a "real" web server software here. 17 | if ($uri !== '/' && file_exists(__DIR__.'/public'.$uri)) { 18 | return false; 19 | } 20 | 21 | require_once __DIR__.'/public/index.php'; 22 | -------------------------------------------------------------------------------- /src/storage/app/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !public/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /src/storage/app/public/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /src/storage/framework/.gitignore: -------------------------------------------------------------------------------- 1 | compiled.php 2 | config.php 3 | down 4 | events.scanned.php 5 | maintenance.php 6 | routes.php 7 | routes.scanned.php 8 | schedule-* 9 | services.json 10 | -------------------------------------------------------------------------------- /src/storage/framework/cache/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !data/ 3 | !.gitignore 4 | -------------------------------------------------------------------------------- /src/storage/framework/cache/data/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /src/storage/framework/sessions/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /src/storage/framework/testing/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /src/storage/framework/views/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /src/storage/logs/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | !.gitignore 3 | -------------------------------------------------------------------------------- /src/tests/CreatesApplication.php: -------------------------------------------------------------------------------- 1 | make(Kernel::class)->bootstrap(); 19 | 20 | return $app; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/tests/Feature/ExampleTest.php: -------------------------------------------------------------------------------- 1 | get('/'); 18 | 19 | $response->assertStatus(200); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/tests/TestCase.php: -------------------------------------------------------------------------------- 1 | assertTrue(true); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/webpack.mix.js: -------------------------------------------------------------------------------- 1 | const mix = require('laravel-mix'); 2 | 3 | /* 4 | |-------------------------------------------------------------------------- 5 | | Mix Asset Management 6 | |-------------------------------------------------------------------------- 7 | | 8 | | Mix provides a clean, fluent API for defining some Webpack build steps 9 | | for your Laravel applications. By default, we are compiling the CSS 10 | | file for the application as well as bundling up all the JS files. 11 | | 12 | */ 13 | 14 | mix.js('resources/js/app.js', 'public/js') 15 | .postCss('resources/css/app.css', 'public/css', [ 16 | // 17 | ]); 18 | --------------------------------------------------------------------------------