├── .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 | 
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 | 
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 |
--------------------------------------------------------------------------------