├── .env ├── .github ├── FUNDING.yml └── workflows │ └── build.yml ├── .helpers ├── .blueprintrc ├── listen.sh ├── permissions.sh └── seeder.sh ├── CODE_OF_CONDUCT.md ├── Dockerfile ├── LICENSE ├── README.md ├── SECURITY.md ├── classic-docker-compose.yml └── docker-compose.yml /.env: -------------------------------------------------------------------------------- 1 | BASE_DIR=/srv/pterodactyl 2 | # By default, you'd want to place your Wings config.yml file at /srv/pterodactyl/wings/config.yml 3 | # In general, such as with this and with certs, you'd want to look at your mounts in the docker-compose.yml file 4 | # in order to know where to put things on the host system. 5 | APP_NAME= 6 | APP_ENV=production # "production" or "testing" 7 | PANEL_PORT=443 8 | # If you want to allow port 80 as well, i.e. if you don't use Cloudflare to manage your DNS and 9 | # automatically direct requests to https, you can add another port in the docker-compose.yml file 10 | WINGS_PORT=8080 11 | WINGS_SFTP_PORT=2022 12 | # Domain for mail sections (if you're configuring email) 13 | DOMAIN=example.com 14 | # Recommended strength is a random 20 digit password with letters, numbers, and symbols 15 | # You can go to https://1password.com/password-generator and check "Symbols", then refresh for each password below 16 | MARIADB_ROOT_PASS= 17 | MARIADB_USER_PASS= 18 | VALKEY_PASS= 19 | HASH_SALT= 20 | # Remember https:// or http:// 21 | FQDN= 22 | # Part of what you'd set if behind a proxy in order for activity logs to see the correct IP addresses 23 | # The other part would be passing the headers through by modifying your panel.conf file 24 | TRUSTED_PROXIES= 25 | # A list of valid timezones can be found here: http://php.net/manual/en/timezones.php 26 | TIMEZONE=America/Los_Angeles 27 | EGG_AUTHOR_EMAIL=example@gmail.com 28 | RECAPTCHA_ENABLED=true 29 | # Go to https://www.google.com/recaptcha/admin to generate these 30 | RECAPTCHA_SITE_KEY= 31 | RECAPTCHA_SECRET_KEY= 32 | # 2 = required for all, 1 = required for panel admins, 0 = disabled 33 | APP_2FA_REQUIRED=2 34 | AUTO_ALLOCATION=false 35 | AUTO_ALLOCATION_START_PORT= 36 | AUTO_ALLOCATION_END_PORT= 37 | # To effectively disable the mail feature, set to "array" instead of "smtp" 38 | MAIL_DRIVER=smtp 39 | SMTP_SERVER=smtp-relay.brevo.com 40 | SMTP_PORT=587 41 | SMTP_ENCRYPTION=tls 42 | SMTP_USERNAME= 43 | SMTP_APIKEY= 44 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: https://hcb.hackclub.com/donations/start/blueprint 2 | github: [BlueprintFramework, Loki-101] 3 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and Push Docker Images 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: 7 | - 'Master' 8 | paths: 9 | - Dockerfile 10 | schedule: 11 | - cron: '0 8 * * TUE' 12 | 13 | jobs: 14 | build_and_push: 15 | name: Build and Push Docker Image 16 | runs-on: ubuntu-latest 17 | env: 18 | LATEST_VERSION: v1.11.10 # Determines :latest tag 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | version: 23 | - v1.11.5 24 | - v1.11.6 25 | - v1.11.7 26 | - v1.11.9 27 | - v1.11.10 28 | steps: 29 | - name: Checkout code 30 | uses: actions/checkout@v4 31 | 32 | - name: Set up Docker Buildx 33 | uses: docker/setup-buildx-action@v3 34 | 35 | - name: Set up QEMU 36 | uses: docker/setup-qemu-action@v3 37 | 38 | - name: Login to GitHub Container Registry 39 | uses: docker/login-action@v3 40 | with: 41 | registry: ghcr.io 42 | username: ${{ github.repository_owner }} 43 | password: ${{ secrets.REGISTRY_TOKEN }} 44 | 45 | - name: Prepare tags 46 | id: prep_tags 47 | shell: bash 48 | run: | 49 | if [[ "${{ matrix.version }}" == "${{ env.LATEST_VERSION }}" ]]; then 50 | TAGS="ghcr.io/blueprintframework/blueprint:latest,ghcr.io/blueprintframework/blueprint:${{ matrix.version }}" 51 | else 52 | TAGS="ghcr.io/blueprintframework/blueprint:${{ matrix.version }}" 53 | fi 54 | echo "VERSION_TAG=${{ matrix.version }}" >> $GITHUB_ENV 55 | echo "TAGS=$TAGS" >> $GITHUB_ENV 56 | 57 | - name: Build and Push Docker Image 58 | uses: docker/build-push-action@v5 59 | with: 60 | context: . 61 | file: ./Dockerfile 62 | platforms: linux/amd64,linux/arm64 63 | push: true 64 | tags: ${{ env.TAGS }} 65 | build-args: VERSION_TAG=${{ env.VERSION_TAG }} 66 | -------------------------------------------------------------------------------- /.helpers/.blueprintrc: -------------------------------------------------------------------------------- 1 | OWNERSHIP="nginx:nginx" 2 | WEBUSER="nginx" -------------------------------------------------------------------------------- /.helpers/listen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euo pipefail 3 | 4 | trap 'echo "Interrupted"; exit 1' INT TERM 5 | 6 | # Initial sync 7 | rsync -av --exclude=".blueprint" --include="*.blueprint" --exclude="*" --delete "/blueprint_extensions/" "/app/" 8 | 9 | # Continuous monitor task 10 | inotifywait -m -q \ 11 | -e close_write,delete,moved_to,moved_from \ 12 | --format '%e %w%f' \ 13 | "/blueprint_extensions/" | 14 | while read -r event filepath; do 15 | case "$filepath" in 16 | *.blueprint) 17 | case "$event" in 18 | CLOSE_WRITE,CLOSE|MOVED_TO) 19 | if ! cp "$filepath" "/app/$(basename "$filepath")"; then 20 | echo "Error copying: $filepath" >&2 21 | else 22 | echo "Updated: $filepath" 23 | fi 24 | ;; 25 | DELETE|MOVED_FROM) 26 | if ! rm -f "/app/$(basename "$filepath")"; then 27 | echo "Error removing: $filepath" >&2 28 | else 29 | echo "Removed: $filepath" 30 | fi 31 | ;; 32 | esac 33 | ;; 34 | esac 35 | done 36 | -------------------------------------------------------------------------------- /.helpers/permissions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Array of paths that should be nginx owned 4 | paths=( 5 | "/app/var" 6 | "/etc/nginx/http.d" 7 | "/app/storage/logs" 8 | "/var/log/nginx" 9 | "/blueprint_extensions" 10 | ) 11 | 12 | for path in "${paths[@]}"; do 13 | OWNER=$(stat -c "%U" "$path") 14 | if [ "$OWNER" != "nginx" ]; then 15 | chown -R nginx: "$path" 16 | fi 17 | done -------------------------------------------------------------------------------- /.helpers/seeder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | while ! [[ $(/usr/local/bin/php /app/artisan db:monitor) =~ OK ]]; do 3 | /bin/sleep 5 4 | done 5 | /usr/local/bin/php /app/artisan db:seed --class=BlueprintSeeder --force -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | Blueprint's code of conduct is available on [this page](https://github.com/BlueprintFramework/framework/blob/main/CODE_OF_CONDUCT.md). 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | ARG VERSION_TAG 2 | FROM --platform=$TARGETOS/$TARGETARCH ghcr.io/pterodactyl/panel:${VERSION_TAG} 3 | 4 | # Set the Working Directory 5 | WORKDIR /app 6 | 7 | # Install necessary packages 8 | RUN apk update && apk add --no-cache \ 9 | unzip \ 10 | zip \ 11 | curl \ 12 | git \ 13 | bash \ 14 | wget \ 15 | nodejs \ 16 | npm \ 17 | coreutils \ 18 | build-base \ 19 | musl-dev \ 20 | libgcc \ 21 | openssl \ 22 | openssl-dev \ 23 | linux-headers \ 24 | ncurses \ 25 | rsync \ 26 | inotify-tools \ 27 | sed 28 | 29 | # Install yarn and Pterodactyl dependencies, as well as update browserlist 30 | RUN for i in {1..3}; do \ 31 | npm install -g yarn && \ 32 | yarn --network-timeout 120000 && \ 33 | npx update-browserslist-db@latest && \ 34 | break || \ 35 | echo "Attempt $i failed! Retrying..." && \ 36 | sleep 10; \ 37 | done 38 | 39 | # Download and unzip the latest Blueprint release 40 | RUN wget $(curl -s https://api.github.com/repos/BlueprintFramework/framework/releases/latest | grep 'browser_download_url' | cut -d '"' -f 4) -O blueprint.zip \ 41 | && unzip -o blueprint.zip -d /app \ 42 | && touch /.dockerenv \ 43 | && rm blueprint.zip 44 | 45 | # Required for tput (used in blueprint.sh) 46 | ENV TERM=xterm 47 | 48 | # Copy helpers directory - has to be done before running blueprint.sh for .blueprintrc to set correct permisisons 49 | COPY .helpers /helpers 50 | RUN mv /helpers/.blueprintrc /app/.blueprintrc 51 | RUN chmod +x /helpers/*.sh 52 | 53 | # Make the script executable and run it 54 | RUN chmod +x blueprint.sh \ 55 | && bash blueprint.sh 56 | 57 | # Create directory for blueprint extensions 58 | RUN mkdir -p /blueprint_extensions 59 | 60 | # Append our additions to supervisord 61 | RUN echo "" >> /etc/supervisord.conf && \ 62 | cat >> /etc/supervisord.conf <<'EOF' 63 | 64 | [program:database-seeder] 65 | command=/helpers/seeder.sh 66 | user=nginx 67 | autostart=true 68 | autorestart=false 69 | startsecs=0 70 | 71 | [program:listener] 72 | command=/helpers/listen.sh 73 | user=root 74 | autostart=true 75 | autorestart=true 76 | 77 | [program:fix-bind-mount-perms] 78 | command=/helpers/permissions.sh 79 | user=root 80 | autostart=true 81 | autorestart=false 82 | startsecs=0 83 | priority=1 84 | EOF 85 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024-2025 Emma (prpl.wtf) and Loki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![Blueprint Docker](https://github.com/BlueprintFramework/docker/assets/103201875/f1c39e6e-afb0-4e24-abd3-508ec883d66b) 3 |

Blueprint's extension ecosystem you know and love, in 🐳 Docker.

4 | 5 | 6 |

🐳 Blueprint in Docker

7 | 8 | ### Supported Architectures 9 | | Architecture | Support Status | 10 | |--------------|---------------| 11 | | AMD64 | :white_check_mark: Supported | 12 | | ARM64 | :white_check_mark: Supported | 13 | 14 | - Note: While the panel and Wings images provided will run fine on Arm64, most game servers _will not_, so if you are running Wings on an Arm64 machine, that's something to be aware of. 15 | - If running Wings on a Rasberry Pi, see the following section posted by quintenqvd in the Pterodactyl Discord: 16 | > Running wings on a pi 4 or 5 17 | > Wings require docker cgroups. Those are not present in the ubuntu version only in the debian 11 or 12 one 18 | > install the debian lite 64 bit OS 19 | > Install docker then open the /boot/cmdline.txt file and add (don't remove anything and do not add a new line) cgroup_memory=1 cgroup_enable=memory systemd.unified_cgroup_hierarchy=0 to the end of what is already there, save + exit and then restart 20 | > Note on the debian 12 based os the path is /boot/firmware/cmdline.txt 21 | 22 | ### What is the difference between docker-compose.yml and classic-docker-compose.yml? 23 | - classic-docker-compose.yml stays as close to the stock Pterodactyl compose file as possible 24 | - This means it still has the obsolete "version" attribute, has no health checks, and does not use a .env file for configuration 25 | - This file is simpler to look at and understand, mostly because it doesn't give you the same level of control and information as the recommended docker-compose.yml file 26 | - docker-compose.yml (recommended) can and has been improved over time 27 | - If you are using this version, download and configure the .env file as well; most if not all configuration can be done through the .env file 28 | 29 | ### Is this your first time running Wings inside of Docker? 30 | - One thing to be prepared for is that Wings uses the host system's Docker Engine through the mounted socket; it does not use Docker in Docker. 31 | - What this means is the directory where you store your data, if you wish to customize it, must be set to the same value for both host and container in the mounts, and then you must make the values in your config.yml match; otherwise the Wings container would see one directory, then when a new container is created that isn't affected by this docker-compose.yml's mounts, it won't see the same directory. Here's an example: 32 | - Mount in docker-compose.yml: ``"${BASE_DIR}/:${BASE_DIR}/"`` 33 | - Let's say, for the purposes of this example, that you set ``BASE_DIR`` in your .env file to **/srv/pterodactyl**. If you want to mount Wings server data in another location, just add any other mount, making sure both sides of the mount match. 34 | - Now when you create your node, you would select somewhere inside the mount you made for **Daemon Server File Directory**, e.g. /srv/pterodacty/wings/servers 35 | - After Wings runs successfully the first time, more options will appear in your **config.yml** file. They will look like this: 36 | - ``` 37 | root_directory: /var/lib/pterodactyl 38 | log_directory: /var/log/pterodactyl 39 | data: /srv/pterodactyl/wings/servers 40 | archive_directory: /var/lib/pterodactyl/archives 41 | backup_directory: /var/lib/pterodactyl/backups 42 | tmp_directory: /tmp/pterodactyl 43 | ``` 44 | - As you can see, only **data** gets set to your configured location. You can make the others match by changing **/var/lib/pterodactyl** to match your base directory, again for the example **/srv/pterodactyl**. Optionally, you can change the log location too if you'd like to keep ***everything*** possible inside one directory, which is one of the benefits of using containers. Once you're done, it may look like: 45 | - ``` 46 | root_directory: /srv/pterodactyl 47 | log_directory: /srv/pterodactyl/wings/logs 48 | data: /srv/pterodactyl/wings/servers 49 | archive_directory: /srv/pterodactyl/archives 50 | backup_directory: /srv/pterodactyl/backups 51 | tmp_directory: /tmp/pterodactyl 52 | ``` 53 | ### Creating your first user 54 | - ``cd`` into the directory containing your compose file, e.g. ``cd /srv/pterodactyl`` 55 | - ```bash 56 | docker compose exec panel php artisan p:user:make 57 | ``` 58 | 59 | ### Uploading extensions 60 | Extensions must be placed/dragged into the `extensions` folder. 61 | 62 | ### Interacting with Blueprint 63 | By default, you can only interact with Blueprint by going through the Docker Engine command line, i.e. 64 | ```bash 65 | docker compose exec panel blueprint (arguments) 66 | ``` 67 | 68 | #### We recommend setting an alias so you can interact with Blueprint the same way you would in the non-Docker version (If you have your compose file in a different place, adjust accordingly: 69 | ```bash 70 | # Set alias for current session 71 | alias blueprint="docker compose -f /srv/pterodactyl/docker-compose.yml exec panel blueprint" 72 | # Append to the end of your .bashrc file to make it persistent 73 | echo 'alias blueprint="docker compose -f /srv/pterodactyl/docker-compose.yml exec panel blueprint"' >> ~/.bashrc 74 | ``` 75 | 76 | ### Example of installing an extension 77 | Here's a quick example showcasing how you would go about installing extensions on the Docker version of Blueprint. Note that your experience can differ for every extension. 78 | 1. [Find an extension](https://blueprint.zip/browse) you would like to install and look for a file with the `.blueprint` file extension. 79 | 2. Drag/upload the `example.blueprint` file over/onto to your extensions folder, i.e. by default `/srv/pterodactyl/extensions`. 80 | 3. Install the extension through the Blueprint command line tool: 81 | ```bash 82 | docker compose exec panel blueprint -i example 83 | ``` 84 | Alternatively, if you have applied the alias we suggested above: 85 | ```bash 86 | blueprint -i example 87 | ``` 88 | 89 | #### So, you installed your first extension. Congratulations! Blueprint is now keeping persistent data inside the `pterodactyl_app` volume, so you'll want to start backing that volume up regularly. 90 | 91 | ### First, we'll install Restic to handle backups 92 | Why Restic? Compression, de-duplication, and incremental backups. Save on space compared to simply archiving the directory each time. 93 | The package name is usually `restic`, e.g. 94 | | Operating System | Command | 95 | |----------------------------------|-----------------------------------------------------------------| 96 | | Ubuntu / Debian / Linux Mint | `sudo apt -y install restic` | 97 | | Fedora | `sudo dnf -y install restic` | 98 | | Rocky Linux / AlmaLinux / CentOS | `sudo dnf -y install epel-release && sudo dnf -y install restic`| 99 | | Arch Linux | `sudo pacman -S --noconfirm restic` | 100 | | openSUSE | `sudo zypper install -n restic` | 101 | | Gentoo | `sudo emerge --ask=n app-backup/restic` | 102 | 103 | #### Make a directory and script for backups 104 | ```bash 105 | mkdir -p /srv/backups/pterodactyl 106 | export RESTIC_PASSWORD="CHANGE_ME" 107 | restic init --repo /srv/backups/pterodactyl 108 | cat < /srv/backups/backup.sh 109 | #!/bin/bash 110 | docker compose -f /srv/pterodactyl/docker-compose.yml down panel 111 | cd /var/lib/docker/volumes/pterodactyl_app/_data 112 | RESTIC_PASSWORD="${RESTIC_PASSWORD}" restic backup . -r /srv/backups/pterodactyl 113 | docker compose -f /srv/pterodactyl/docker-compose.yml up -d panel 114 | EOF 115 | chmod +x /srv/backups/backup.sh 116 | ``` 117 | 118 | #### Set a crontab to back up your panel (choose a time when it will be least likely to be being used) 119 | ```bash 120 | (crontab -l 2>/dev/null; echo "59 23 * * * /srv/backups/backup.sh") | crontab - 121 | ``` 122 | 123 | #### Well, great. I have daily backups now, and they're set to keep at most 30 backups at a time. How can I restore from one of them? 124 | You can list snapshots with ``restic snapshots --repo /srv/backups/pterodactyl`` 125 | You're looking for a value for **ID** that looks something like ``46adb587``. **Time** will be right next to each ID, so you can see what day your backups are from. 126 | 127 | #### Once you've determined which snapshot you want to restore, stop your compose stack, restore your data, and start your stack again 128 | ```bash 129 | docker compose -f /srv/pterodactyl/docker-compose.yml down 130 | # Clear the directory so the restoration will be clean 131 | rm -rf /var/lib/docker/volumes/pterodactyl_app/_data/.[!.]* /var/lib/docker/volumes/pterodactyl_app/_data/* 132 | # Remember to replace "46adb587" with your actual ID of the snapshot you want to restore 133 | restic restore 46adb587 -r /srv/backups/pterodactyl -t /var/lib/docker/volumes/pterodactyl_app/_data 134 | docker compose -f /srv/pterodactyl/docker-compose.yml up -d 135 | ``` 136 | 137 | # Updating Blueprint in Docker 138 | - Remember, always [create a backup]() before updates 139 | ## Option 1: Only update Blueprint 140 | - If you have set the alias we suggested earlier 141 | ```bash 142 | blueprint -upgrade 143 | ``` 144 | - If you have not 145 | ```bash 146 | docker compose -f /srv/pterodactyl/docker-compose.yml exec panel blueprint -upgrade 147 | ``` 148 | 149 | ## Option 2: Update both Blueprint and Pterodactyl Panel 150 | - This guide operates under the assumption that individual extension/theme authors have chosen to store any persistent data such as settings in the database. If they have not done this... there isn't any specific place extension data is meant to be stored, so the data could be anywhere. You'll need to ask them if there is any persistent data stored anywhere that you have to back up before updating. 151 | - Go to the directory of your docker-compose.yml file 152 | - ```bash 153 | docker compose down -v 154 | ``` 155 | - The -v tells it to delete any named volumes, i.e. the app volume we use. It will not delete data from bind-mounts. This way the new image's app volume can take place. 156 | - Change the tag in your panel's image (i.e. to upgrade from **v1.11.5** to **v1.11.7**, you would change ``ghcr.io/blueprintframework/blueprint:v1.11.5`` to ``ghcr.io/blueprintframework/blueprint:v1.11.7``. 157 | - ```bash 158 | docker compose pull 159 | ``` 160 | - ```bash 161 | docker compose up -d 162 | ``` 163 | - Lastly, install your extensions again. You can reinstall all of the extensions in your extensions folder with ``blueprint -i *.blueprint``. 164 | - If any of your extensions' settings are gone after this step, restore from your backup and ask the author of those extensions where persistent data is stored so you can back it up and restore it after each update. 165 | 166 | 167 | 168 | 169 |

170 |

171 | © 2024-2025 Emma (prpl.wtf) and Loki 172 |

173 |

174 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | ![Security policy](https://github.com/user-attachments/assets/b31af317-c071-41ae-8060-ef12f6c741a6) 2 | 3 | ## Reporting a Vulnerability 4 | 5 | - To report a vulnerability in private, feel free to send an email to `loki@crazycoder.dev` 6 | - Note that this policy is strictly for this repository, the container image for Blueprint. To report a vulnerability in the Blueprint project itself, refer to the [Blueprint Security Policy]() 7 | -------------------------------------------------------------------------------- /classic-docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.8' 2 | x-common: 3 | database: 4 | &db-environment 5 | # Do not remove the "&db-password" from the end of the line below, it is important 6 | # for Panel functionality. 7 | MYSQL_PASSWORD: &db-password "CHANGE_ME" 8 | MYSQL_ROOT_PASSWORD: "CHANGE_ME_TOO" 9 | panel: 10 | &panel-environment 11 | APP_URL: "http://example.com" 12 | # A list of valid timezones can be found here: http://php.net/manual/en/timezones.php 13 | APP_TIMEZONE: "UTC" 14 | APP_SERVICE_AUTHOR: "noreply@example.com" 15 | # Uncomment the line below and set to a non-empty value if you want to use Let's Encrypt 16 | # to generate an SSL certificate for the Panel. 17 | # LE_EMAIL: "" 18 | mail: 19 | &mail-environment 20 | MAIL_FROM: "noreply@example.com" 21 | MAIL_DRIVER: "smtp" 22 | MAIL_HOST: "mail" 23 | MAIL_PORT: "1025" 24 | MAIL_USERNAME: "" 25 | MAIL_PASSWORD: "" 26 | MAIL_ENCRYPTION: "true" 27 | 28 | # 29 | # ------------------------------------------------------------------------------------------ 30 | # DANGER ZONE BELOW 31 | # 32 | # The remainder of this file likely does not need to be changed. Please only make modifications 33 | # below if you understand what you are doing. 34 | # 35 | services: 36 | database: 37 | image: mariadb:10.5 38 | restart: always 39 | command: --default-authentication-plugin=mysql_native_password 40 | volumes: 41 | - "/srv/pterodactyl/database:/var/lib/mysql" 42 | environment: 43 | <<: *db-environment 44 | MYSQL_DATABASE: "panel" 45 | MYSQL_USER: "pterodactyl" 46 | cache: 47 | image: redis:alpine 48 | restart: always 49 | panel: 50 | image: ghcr.io/blueprintframework/blueprint:v1.11.10 51 | restart: always 52 | ports: 53 | - "80:80" 54 | - "443:443" 55 | links: 56 | - database 57 | - cache 58 | volumes: 59 | - "/srv/pterodactyl/var/:/app/var/" 60 | - "/srv/pterodactyl/nginx/:/etc/nginx/http.d/" 61 | - "/srv/pterodactyl/certs/:/etc/letsencrypt/" 62 | - "/srv/pterodactyl/logs/:/app/storage/logs" 63 | - "/srv/pterodactyl/extensions/:/blueprint_extensions" 64 | - "app:/app" 65 | environment: 66 | <<: [*panel-environment, *mail-environment] 67 | DB_PASSWORD: *db-password 68 | APP_ENV: "production" 69 | APP_ENVIRONMENT_ONLY: "false" 70 | CACHE_DRIVER: "redis" 71 | SESSION_DRIVER: "redis" 72 | QUEUE_DRIVER: "redis" 73 | REDIS_HOST: "cache" 74 | DB_HOST: "database" 75 | DB_PORT: "3306" 76 | networks: 77 | default: 78 | ipam: 79 | config: 80 | - subnet: 172.20.0.0/16 81 | 82 | volumes: 83 | app: 84 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | x-common: 2 | database: 3 | &db-environment 4 | # Do not remove the "&db-password" from the end of the line below, it is important 5 | # for Panel functionality. 6 | MYSQL_PASSWORD: &db-password "${MARIADB_USER_PASS}" 7 | MYSQL_ROOT_PASSWORD: "${MARIADB_ROOT_PASS}" 8 | cache: 9 | &redis-environment 10 | REDIS_PASSWORD: &redis-password "${VALKEY_PASS}" 11 | panel: 12 | &panel-environment 13 | APP_URL: "${FQDN}" 14 | APP_NAME: "${APP_NAME}" 15 | # A list of valid timezones can be found here: http://php.net/manual/en/timezones.php 16 | APP_TIMEZONE: "${TIMEZONE}" 17 | APP_SERVICE_AUTHOR: "${EGG_AUTHOR_EMAIL}" 18 | # Uncomment the line below and set to a non-empty value if you want to use Let's Encrypt 19 | # to generate an SSL certificate for the Panel. 20 | # LE_EMAIL: "" 21 | # TRUSTED_PROXIES: "${TRUSTED_PROXIES}" 22 | RECAPTCHA_ENABLED: "${RECAPTCHA_ENABLED}" 23 | RECAPTCHA_WEBSITE_KEY: "${RECAPTCHA_SITE_KEY}" 24 | RECAPTCHA_SECRET_KEY: "${RECAPTCHA_SECRET_KEY}" 25 | APP_2FA_REQUIRED: "${APP_2FA_REQUIRED}" 26 | PTERODACTYL_CLIENT_ALLOCATIONS_ENABLED: "${AUTO_ALLOCATION}" 27 | PTERODACTYL_CLIENT_ALLOCATIONS_RANGE_START: "${AUTO_ALLOCATION_START_PORT}" 28 | PTERODACTYL_CLIENT_ALLOCATIONS_RANGE_END: "${AUTO_ALLOCATION_END_PORT}" 29 | mail: 30 | &mail-environment 31 | MAIL_FROM: "no-reply${DOMAIN}" 32 | MAIL_FROM_NAME: "no-reply${DOMAIN}" 33 | MAIL_DRIVER: "${MAIL_DRIVER}" 34 | MAIL_HOST: "${SMTP_SERVER}" 35 | MAIL_PORT: "${SMTP_PORT}" 36 | MAIL_USERNAME: "${SMTP_USERNAME}" 37 | MAIL_PASSWORD: "${SMTP_APIKEY}" 38 | MAIL_ENCRYPTION: "${SMTP_ENCRYPTION}" 39 | MAIL_EHLO_DOMAIN: "no-reply@${DOMAIN}" 40 | 41 | # 42 | # ------------------------------------------------------------------------------------------ 43 | # DANGER ZONE BELOW 44 | # 45 | # The remainder of this file likely does not need to be changed. Please only make modifications 46 | # below if you understand what you are doing. 47 | # 48 | services: 49 | database: 50 | image: mariadb:11 51 | restart: always 52 | command: --default-authentication-plugin=mysql_native_password --max-connections=2000 53 | volumes: 54 | - "${BASE_DIR}/database:/var/lib/mysql" 55 | environment: 56 | <<: *db-environment 57 | MYSQL_DATABASE: "panel" 58 | MYSQL_USER: "pterodactyl" 59 | healthcheck: 60 | test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] 61 | interval: 30s 62 | timeout: 10s 63 | retries: 5 64 | start_period: 30s 65 | networks: 66 | - pterodactyl_stack 67 | # - pterodactyl_nw 68 | # If you un-comment the above, also un-comment the bottom of the network section at the very 69 | # bottom of this file where it mentions pterodactyl_nw 70 | ports: 71 | - "3306:3306" 72 | # After connecting Wings to your panel successfully, change this to "172.18.0.1:3306:3306" 73 | # to allow database connections from servers at the 172.18.0.1 address 74 | # Un-commenting pterodactyl_nw will also allow game servers to connect to the database at the address "database" 75 | cache: 76 | image: valkey/valkey:alpine 77 | restart: always 78 | command: > 79 | --requirepass "${VALKEY_PASS}" 80 | environment: 81 | REDISCLI_AUTH: "${VALKEY_PASS}" 82 | healthcheck: 83 | test: ["CMD", "valkey-cli", "ping"] 84 | interval: 30s 85 | timeout: 10s 86 | retries: 5 87 | start_period: 30s 88 | networks: 89 | - pterodactyl_stack 90 | panel: 91 | image: ghcr.io/blueprintframework/blueprint:v1.11.10 92 | restart: always 93 | ports: 94 | - "${PANEL_PORT}:${PANEL_PORT}" 95 | links: 96 | - database 97 | - cache 98 | volumes: 99 | - "${BASE_DIR}/var/:/app/var/" 100 | - "${BASE_DIR}/nginx/:/etc/nginx/http.d/" 101 | - "${BASE_DIR}/certs/:/etc/letsencrypt/live:ro" 102 | - "${BASE_DIR}/logs/:/app/storage/logs" 103 | - "${BASE_DIR}/nginx/logs:/var/log/nginx" 104 | - "${BASE_DIR}/extensions/:/blueprint_extensions" 105 | - "app:/app" 106 | environment: 107 | <<: [*panel-environment, *mail-environment] 108 | DB_PASSWORD: *db-password 109 | APP_ENV: "production" # "production" or "testing" 110 | APP_ENVIRONMENT_ONLY: "false" 111 | CACHE_DRIVER: "redis" 112 | SESSION_DRIVER: "redis" 113 | QUEUE_DRIVER: "redis" 114 | REDIS_HOST: "cache" 115 | REDIS_PASSWORD: *redis-password 116 | DB_HOST: "database" 117 | DB_PORT: "3306" 118 | HASHIDS_SALT: "${HASH_SALT}" 119 | HASHIDS_LENGTH: 8 120 | healthcheck: 121 | test: ["CMD", "curl", "http://localhost:${PANEL_PORT}"] 122 | interval: 30s 123 | timeout: 10s 124 | retries: 5 125 | start_period: 30s 126 | networks: 127 | - pterodactyl_stack 128 | wings: 129 | # See https://github.com/Loki-101/cwings for info about cwings 130 | image: ghcr.io/loki-101/cwings:v1.11.13 131 | restart: always 132 | ports: 133 | - "${WINGS_PORT}:${WINGS_PORT}" 134 | - "2022:2022" 135 | tty: true 136 | environment: 137 | TZ: "${TIMEZONE}" 138 | WINGS_UID: 988 139 | WINGS_GID: 988 140 | WINGS_USERNAME: pterodactyl 141 | volumes: 142 | - "/var/run/docker.sock:/var/run/docker.sock" 143 | - "/var/lib/docker/containers/:/var/lib/docker/containers/" 144 | - "${BASE_DIR}/wings:/etc/pterodactyl" 145 | - "${BASE_DIR}/:${BASE_DIR}/" 146 | - "${BASE_DIR}/logs/:/var/log/pterodactyl/" 147 | - "/tmp/pterodactyl/:/tmp/pterodactyl/" 148 | - "${BASE_DIR}/certs:/etc/letsencrypt/live:ro" 149 | healthcheck: 150 | test: ["CMD", "curl", "http://localhost:${WINGS_PORT}"] 151 | interval: 30s 152 | timeout: 10s 153 | retries: 5 154 | start_period: 30s 155 | networks: 156 | - pterodactyl_stack 157 | 158 | networks: 159 | pterodactyl_stack: 160 | driver: bridge 161 | ipam: 162 | driver: default 163 | config: 164 | - subnet: "172.20.0.0/24" 165 | # pterodactyl_nw: 166 | # external: true 167 | 168 | volumes: 169 | app: 170 | --------------------------------------------------------------------------------