Replace pdns-admin-static and pdns-admin-uwsgi images with single pdns-admin

This commit is contained in:
Peter Schiffer 2024-01-01 20:39:33 +01:00
parent c18b7dcdce
commit 2b264c149e
No known key found for this signature in database
GPG key ID: F2A18AC34A008397
24 changed files with 435 additions and 240 deletions

View file

@ -9,6 +9,6 @@ updates:
schedule:
interval: "monthly"
- package-ecosystem: "docker"
directory: "/pdns-admin-base-ngoduykhanh"
directory: "/pdns-admin"
schedule:
interval: "monthly"

View file

@ -86,7 +86,7 @@ jobs:
- name: Image digest
run: echo ${{ steps.docker_build_pdns_alpine.outputs.digest }}
test-admin-base:
test-pdns-admin:
runs-on: ubuntu-latest
steps:
- name: Check Out Repo
@ -94,62 +94,15 @@ jobs:
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
- name: Build admin base
id: docker_build_admin_base
- name: Build pdns admin
id: docker_build_pdns_admin
uses: docker/build-push-action@v5
with:
context: ./pdns-admin-base-ngoduykhanh
file: ./pdns-admin-base-ngoduykhanh/Dockerfile
context: ./pdns-admin
file: ./pdns-admin/Dockerfile
builder: ${{ steps.buildx.outputs.name }}
push: false
tags: |
pdns-admin-base:latest
pdns-admin-base:ngoduykhanh
pdns-admin:latest
- name: Image digest
run: echo ${{ steps.docker_build_admin_base.outputs.digest }}
test-admin-uwsgi:
runs-on: ubuntu-latest
needs: test-admin-base
steps:
- name: Check Out Repo
uses: actions/checkout@v4
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
- name: Build admin uwsgi
id: docker_build_admin_uwsgi
uses: docker/build-push-action@v5
with:
context: ./pdns-admin-uwsgi-ngoduykhanh
file: ./pdns-admin-uwsgi-ngoduykhanh/Dockerfile
builder: ${{ steps.buildx.outputs.name }}
push: false
tags: |
pdns-admin-uwsgi:latest
pdns-admin-uwsgi:ngoduykhanh
- name: Image digest
run: echo ${{ steps.docker_build_admin_uwsgi.outputs.digest }}
test-admin-static:
runs-on: ubuntu-latest
needs: test-admin-base
steps:
- name: Check Out Repo
uses: actions/checkout@v4
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
- name: Build admin static
id: docker_build_admin_static
uses: docker/build-push-action@v5
with:
context: ./pdns-admin-static-ngoduykhanh
file: ./pdns-admin-static-ngoduykhanh/Dockerfile
builder: ${{ steps.buildx.outputs.name }}
push: false
tags: |
pdns-admin-static:latest
pdns-admin-static:ngoduykhanh
- name: Image digest
run: echo ${{ steps.docker_build_admin_static.outputs.digest }}
run: echo ${{ steps.docker_build_pdns_admin.outputs.digest }}

View file

@ -118,7 +118,7 @@ jobs:
- name: Image digest
run: echo ${{ steps.docker_build_pdns_alpine.outputs.digest }}
build-admin-base:
build-pdns-admin:
runs-on: ubuntu-latest
steps:
- name: Check Out Repo
@ -133,79 +133,16 @@ jobs:
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Build and push admin base
id: docker_build_admin_base
- name: Build and push pdns admin
id: docker_build_pdns_admin
uses: docker/build-push-action@v5
with:
context: ./pdns-admin-base-ngoduykhanh
file: ./pdns-admin-base-ngoduykhanh/Dockerfile
context: ./pdns-admin
file: ./pdns-admin/Dockerfile
platforms: linux/amd64,linux/arm64
builder: ${{ steps.buildx.outputs.name }}
push: true
tags: |
${{ secrets.DOCKER_HUB_USERNAME }}/pdns-admin-base:latest
${{ secrets.DOCKER_HUB_USERNAME }}/pdns-admin-base:ngoduykhanh
${{ secrets.DOCKER_HUB_USERNAME }}/pdns-admin:latest
- name: Image digest
run: echo ${{ steps.docker_build_admin_base.outputs.digest }}
build-admin-uwsgi:
runs-on: ubuntu-latest
needs: build-admin-base
steps:
- name: Check Out Repo
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Build and push admin uwsgi
id: docker_build_admin_uwsgi
uses: docker/build-push-action@v5
with:
context: ./pdns-admin-uwsgi-ngoduykhanh
file: ./pdns-admin-uwsgi-ngoduykhanh/Dockerfile
platforms: linux/amd64,linux/arm64
builder: ${{ steps.buildx.outputs.name }}
push: true
tags: |
${{ secrets.DOCKER_HUB_USERNAME }}/pdns-admin-uwsgi:latest
${{ secrets.DOCKER_HUB_USERNAME }}/pdns-admin-uwsgi:ngoduykhanh
- name: Image digest
run: echo ${{ steps.docker_build_admin_uwsgi.outputs.digest }}
build-admin-static:
runs-on: ubuntu-latest
needs: build-admin-base
steps:
- name: Check Out Repo
uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
- name: Build and push admin static
id: docker_build_admin_static
uses: docker/build-push-action@v5
with:
context: ./pdns-admin-static-ngoduykhanh
file: ./pdns-admin-static-ngoduykhanh/Dockerfile
platforms: linux/amd64,linux/arm64
builder: ${{ steps.buildx.outputs.name }}
push: true
tags: |
${{ secrets.DOCKER_HUB_USERNAME }}/pdns-admin-static:latest
${{ secrets.DOCKER_HUB_USERNAME }}/pdns-admin-static:ngoduykhanh
- name: Image digest
run: echo ${{ steps.docker_build_admin_static.outputs.digest }}
run: echo ${{ steps.docker_build_pdns_admin.outputs.digest }}

View file

@ -1,8 +1,8 @@
# PowerDNS Docker Images
This repository contains four Docker images - pdns-mysql, pdns-recursor, pdns-admin-static and pdns-admin-uwsgi. Image **pdns-mysql** contains completely configurable [PowerDNS 4.x server](https://www.powerdns.com/) with mysql backend (without mysql server). Image **pdns-recursor** contains completely configurable [PowerDNS 4.x recursor](https://www.powerdns.com/). Images **pdns-admin-static** and **pdns-admin-uwsgi** contains fronted (nginx) and backend (uWSGI) for [PowerDNS Admin](https://github.com/PowerDNS-Admin/PowerDNS-Admin) web app, written in Flask, for managing PowerDNS servers.
This repository contains the following Docker images - pdns-mysql, pdns-recursor and pdns-admin. Image **pdns-mysql** contains completely configurable [PowerDNS 4.x server](https://www.powerdns.com/) with mysql backend (without mysql server). Image **pdns-recursor** contains completely configurable [PowerDNS 4.x recursor](https://www.powerdns.com/). Image **pdns-admin** contains fronted (Caddy) and backend (uWSGI) for the [PowerDNS Admin](https://github.com/PowerDNS-Admin/PowerDNS-Admin) web app, which is written in Flask and used for managing PowerDNS servers.
The pdns-mysql and pdns-recursor images have also the `alpine` tag thanks to the @PoppyPop .
The pdns-mysql and pdns-recursor images also have the `alpine` tag, thanks to @PoppyPop.
All images are available on Docker Hub:
@ -10,9 +10,7 @@ https://hub.docker.com/r/pschiffe/pdns-mysql/
https://hub.docker.com/r/pschiffe/pdns-recursor/
https://hub.docker.com/r/pschiffe/pdns-admin-uwsgi/
https://hub.docker.com/r/pschiffe/pdns-admin-static/
https://hub.docker.com/r/pschiffe/pdns-admin/
## pdns-mysql
@ -20,7 +18,7 @@ https://hub.docker.com/r/pschiffe/pdns-admin-static/
https://hub.docker.com/r/pschiffe/pdns-mysql/
Docker image with [PowerDNS 4.x server](https://www.powerdns.com/) and mysql backend (without mysql server). For running, it needs external mysql server. Env vars for mysql configuration:
Docker image with [PowerDNS 4.x server](https://www.powerdns.com/) and mysql backend (without mysql server). Requires external mysql server. Env vars for mysql configuration:
```
(name=default value)
@ -30,17 +28,18 @@ PDNS_gmysql_user=root
PDNS_gmysql_password=powerdns
PDNS_gmysql_dbname=powerdns
```
If linked with official [mariadb](https://hub.docker.com/_/mariadb/) image with alias `mysql`, the connection can be automatically configured, so you don't need to specify any of the above. Also, DB is automatically initialized if tables are missing.
PowerDNS server is configurable via env vars. Every variable starting with `PDNS_` will be inserted into `/etc/pdns/pdns.conf` conf file in the following way: prefix `PDNS_` will be stripped and every `_` will be replaced with `-`. For example, from above mysql config, `PDNS_gmysql_host=mysql` will became `gmysql-host=mysql` in `/etc/pdns/pdns.conf` file. This way, you can configure PowerDNS server any way you need within a `docker run` command.
If linked with the official [mariadb](https://hub.docker.com/_/mariadb/) image using the alias `mysql`, the connection can be automatically configured, eliminating the need to specify any of the above. The DB is automatically initialized if tables are missing.
There is also a `SUPERMASTER_IPS` env var supported, which can be used to configure supermasters for slave dns server. [Docs](https://doc.powerdns.com/md/authoritative/modes-of-operation/#supermaster-automatic-provisioning-of-slaves). Multiple ip addresses separated by space should work.
The PowerDNS server is configurable via env vars. Every variable starting with `PDNS_` will be inserted into `/etc/pdns/pdns.conf` conf file in the following way: prefix `PDNS_` will be stripped away and every `_` will be replaced with `-`. For example, from the above mysql config, `PDNS_gmysql_host=mysql` will became `gmysql-host=mysql` in `/etc/pdns/pdns.conf` file. This way, you can configure PowerDNS server in any way you need within a `docker run` command.
You can find [here](https://doc.powerdns.com/md/authoritative/) all available settings.
The `SUPERMASTER_IPS` env var is also supported, which can be used to configure supermasters for a slave DNS server. [Docs](https://doc.powerdns.com/md/authoritative/modes-of-operation/#supermaster-automatic-provisioning-of-slaves). Multiple IP addresses separated by spaces should work.
You can find all the available settings [here](https://doc.powerdns.com/md/authoritative/).
### Examples
Master server with API enabled and with one slave server configured:
Example of a master server with the API enabled and one slave server configured:
```
docker run -d -p 53:53 -p 53:53/udp --name pdns-master \
--hostname ns1.example.com --link mariadb:mysql \
@ -57,7 +56,7 @@ docker run -d -p 53:53 -p 53:53/udp --name pdns-master \
pschiffe/pdns-mysql
```
Slave server with supermaster:
Example of a slave server with a supermaster:
```
docker run -d -p 53:53 -p 53:53/udp --name pdns-slave \
--hostname ns2.example.com --link mariadb:mysql \
@ -78,11 +77,11 @@ https://hub.docker.com/r/pschiffe/pdns-recursor/
Docker image with [PowerDNS 4.x recursor](https://www.powerdns.com/).
PowerDNS recursor is configurable via env vars. Every variable starting with `PDNS_` will be inserted into `/etc/pdns/recursor.conf` conf file in the following way: prefix `PDNS_` will be stripped and every `_` will be replaced with `-`. For example, from above mysql config, `PDNS_gmysql_host=mysql` will became `gmysql-host=mysql` in `/etc/pdns/recursor.conf` file. This way, you can configure PowerDNS recursor any way you need within a `docker run` command.
PowerDNS recursor is configurable via env vars. Every variable starting with `PDNS_` will be inserted into `/etc/pdns/recursor.conf` conf file in the following way: prefix `PDNS_` will be stripped away and every `_` will be replaced with `-`. For example, from the above mysql config, `PDNS_gmysql_host=mysql` will became `gmysql-host=mysql` in `/etc/pdns/recursor.conf` file. This way, you can configure PowerDNS recursor any way you need within a `docker run` command.
You can find [here](https://doc.powerdns.com/md/recursor/settings/) all available settings.
You can find all available settings [here](https://doc.powerdns.com/md/recursor/settings/).
### Examples
### Example
Recursor server with API enabled:
```
@ -94,13 +93,17 @@ docker run -d -p 53:53 -p 53:53/udp --name pdns-recursor \
pschiffe/pdns-recursor
```
## pdns-admin-uwsgi
## pdns-admin
![Docker Image Size (tag)](https://img.shields.io/docker/image-size/pschiffe/pdns-admin-uwsgi/latest?label=latest) ![Docker Pulls](https://img.shields.io/docker/pulls/pschiffe/pdns-admin-uwsgi)
![Docker Image Size (tag)](https://img.shields.io/docker/image-size/pschiffe/pdns-admin/latest?label=latest) ![Docker Pulls](https://img.shields.io/docker/pulls/pschiffe/pdns-admin)
https://hub.docker.com/r/pschiffe/pdns-admin-uwsgi/
https://hub.docker.com/r/pschiffe/pdns-admin/
Docker image with backend of [PowerDNS Admin](https://github.com/PowerDNS-Admin/PowerDNS-Admin) web app, written in Flask, for managing PowerDNS servers. This image contains the python part of the app running under uWSGI. It needs external mysql server. Env vars for mysql configuration:
Docker image with [PowerDNS Admin](https://github.com/PowerDNS-Admin/PowerDNS-Admin) web app, written in Flask, for managing PowerDNS servers. It needs external mysql server.
There is also an official image for the pdns-admin on [Docker Hub](https://hub.docker.com/r/powerdnsadmin/pda-legacy). That image contains only gunicorn process that handles both - static files and the python app. Image in this repo contains uWSGI server handling requests for python app and Caddy web server handling static files and optionally HTTPS with Let's Encrypt.
Env vars for mysql configuration:
```
(name=default value)
@ -110,9 +113,9 @@ PDNS_ADMIN_SQLA_DB_USER="root"
PDNS_ADMIN_SQLA_DB_PASSWORD="powerdnsadmin"
PDNS_ADMIN_SQLA_DB_NAME="powerdnsadmin"
```
If linked with official [mariadb](https://hub.docker.com/_/mariadb/) image with alias `mysql`, the connection can be automatically configured, so you don't need to specify any of the above. Also, DB is automatically initialized if tables are missing.
If linked with official [mariadb](https://hub.docker.com/_/mariadb/) image with alias `mysql`, the connection can be automatically configured, so you don't need to specify any of the above. The DB is automatically initialized if tables are missing.
Similar to the pdns-mysql, pdns-admin is also completely configurable via env vars. Prefix in this case is `PDNS_ADMIN_`, configuration will be written to the `/opt/powerdns-admin/config.py` file.
Similar to the pdns-mysql, pdns-admin is also completely configurable via env vars. Prefix in this case is `PDNS_ADMIN_`, configuration will be written to the `/opt/powerdns-admin/powerdnsadmin/default_config.py` file.
### Connecting to the PowerDNS server
@ -144,34 +147,35 @@ python3 -c 'import bcrypt; print(bcrypt.gensalt().decode("utf-8"));'
```
Example value looks like `$2b$12$xxxxxxxxxxxxxxxxxxxxxx` - remember that when using docker-compose, literal `$` must be specified as `$$`.
### SSL with Let's Encrypt
Included Caddy server can optionally handle HTTPS with certificates from Let's Encrypt. To make this work, add `SSL_MAIN_DOMAIN` env var with your primary domain for HTTPS. The `SSL_EXTRA_DOMAINS` env var can contain list of comma-separated domains that will be redirected to the `SSL_MAIN_DOMAIN`. Public DNS must be properly configured and pdns-admin ports `8080`, `8443` and `8443/udp` must be exposed as `80`, `443` and `443/udp` (`443/udp` is for HTTP/3 traffic).
Finally, make the `/var/lib/caddy` dir inside of the pdns-admin container persistent - that's where the generated certificates will be stored.
### Persistent data
There is a directory with user uploads which should be persistent: `/opt/powerdns-admin/upload`
There is also a directory with user uploads which should be persistent: `/opt/powerdns-admin/upload`
### Example
### Examples
When linked with pdns-mysql from this repo and with LDAP auth:
When linked with pdns-mysql from this repo:
```
docker run -d --name pdns-admin-uwsgi \
docker run -d -p 8080:8080 --name pdns-admin \
--link mariadb:mysql --link pdns-master:pdns \
-v pdns-admin-upload:/opt/powerdns-admin/upload \
pschiffe/pdns-admin-uwsgi
pschiffe/pdns-admin
```
## pdns-admin-static
![Docker Image Size (tag)](https://img.shields.io/docker/image-size/pschiffe/pdns-admin-static/latest?label=latest) ![Docker Pulls](https://img.shields.io/docker/pulls/pschiffe/pdns-admin-static)
https://hub.docker.com/r/pschiffe/pdns-admin-static/
Fronted image with nginx and static files for [PowerDNS Admin](https://github.com/PowerDNS-Admin/PowerDNS-Admin). Exposes port 80 for connections, expects uWSGI backend image under `pdns-admin-uwsgi` alias.
### Example
The same with HTTPS:
```
docker run -d -p 8080:80 --name pdns-admin-static \
--link pdns-admin-uwsgi:pdns-admin-uwsgi \
pschiffe/pdns-admin-static
docker run -d -p 80:8080 -p 443:8443 -p 443:8443/udp --name pdns-admin \
--link mariadb:mysql --link pdns-master:pdns \
-v pdns-admin-caddy:/var/lib/caddy \
-v pdns-admin-upload:/opt/powerdns-admin/upload \
-e SSL_MAIN_DOMAIN=www.pdns-admin.com \
-e SSL_EXTRA_DOMAINS=pdns-admin.com,pdns-admin.eu \
pschiffe/pdns-admin
```
## ansible-playbook.yml
@ -180,3 +184,10 @@ Included ansible playbook can be used to build and run the containers from this
```
ansible-playbook ansible-playbook.yml
```
## docker-compose.yml
Included docker compose file contains example configuration of how to use these containers:
```
docker-compose up -d
```

View file

@ -183,54 +183,30 @@
tags:
- pdns
- name: Build pdns-admin base
- name: Build pdns-admin
community.docker.docker_image:
name: pschiffe/pdns-admin-base
name: pschiffe/pdns-admin
tag: latest
state: '{{ i_state }}'
source: build
force_source: true
build:
pull: true
path: ./pdns-admin-base-ngoduykhanh
path: ./pdns-admin
tags:
- pdns-admin
- name: Build pdns-admin backend
community.docker.docker_image:
name: pschiffe/pdns-admin-uwsgi
tag: latest
state: '{{ i_state }}'
source: build
force_source: true
build:
pull: false
path: ./pdns-admin-uwsgi-ngoduykhanh
tags:
- pdns-admin
- name: Build pdns-admin frontent
community.docker.docker_image:
name: pschiffe/pdns-admin-static
tag: latest
state: '{{ i_state }}'
source: build
force_source: true
build:
pull: false
path: ./pdns-admin-static-ngoduykhanh
tags:
- pdns-admin
- name: PDNS-admin backend
- name: PDNS-admin
community.docker.docker_container:
name: pdns-admin-uwsgi
image: pschiffe/pdns-admin-uwsgi
name: pdns-admin
image: pschiffe/pdns-admin
state: '{{ c_state }}'
networks:
- name: pdns-net
aliases:
- pdns-admin-uwsgi
- pdns-admin
published_ports:
- '8889:8080'
volumes:
- /etc/localtime:/etc/localtime:ro
env:
@ -240,20 +216,6 @@
tags:
- pdns-admin
- name: PDNS-admin frontend
community.docker.docker_container:
name: pdns-admin-static
image: pschiffe/pdns-admin-static
state: '{{ c_state }}'
networks:
- name: pdns-net
published_ports:
- '8889:80'
volumes:
- /etc/localtime:/etc/localtime:ro
tags:
- pdns-admin
- name: Remove docker volume
community.docker.docker_volume:
name: pdns-mariadb-volume

87
deprecated/README.md Normal file
View file

@ -0,0 +1,87 @@
# Deprecated PowerDNS-Admin Docker Images
The **pdns-admin** docker image for the [PowerDNS Admin](https://github.com/PowerDNS-Admin/PowerDNS-Admin) web app was previously created as two images: **pdns-admin-static** and **pdns-admin-uwsgi** for fronted (nginx) and backend (uWSGI). These two images won't by updated anymore.
https://hub.docker.com/r/pschiffe/pdns-admin-uwsgi/
https://hub.docker.com/r/pschiffe/pdns-admin-static/
## pdns-admin-uwsgi
![Docker Image Size (tag)](https://img.shields.io/docker/image-size/pschiffe/pdns-admin-uwsgi/latest?label=latest) ![Docker Pulls](https://img.shields.io/docker/pulls/pschiffe/pdns-admin-uwsgi)
https://hub.docker.com/r/pschiffe/pdns-admin-uwsgi/
Docker image with backend of [PowerDNS Admin](https://github.com/PowerDNS-Admin/PowerDNS-Admin) web app, written in Flask, for managing PowerDNS servers. This image contains the python part of the app running under uWSGI. It needs external mysql server. Env vars for mysql configuration:
```
(name=default value)
PDNS_ADMIN_SQLA_DB_HOST="mysql"
PDNS_ADMIN_SQLA_DB_PORT="3306"
PDNS_ADMIN_SQLA_DB_USER="root"
PDNS_ADMIN_SQLA_DB_PASSWORD="powerdnsadmin"
PDNS_ADMIN_SQLA_DB_NAME="powerdnsadmin"
```
If linked with official [mariadb](https://hub.docker.com/_/mariadb/) image with alias `mysql`, the connection can be automatically configured, so you don't need to specify any of the above. Also, DB is automatically initialized if tables are missing.
Similar to the pdns-mysql, pdns-admin is also completely configurable via env vars. Prefix in this case is `PDNS_ADMIN_`, configuration will be written to the `/opt/powerdns-admin/config.py` file.
### Connecting to the PowerDNS server
For the pdns-admin to make sense, it needs a PowerDNS server to manage. The PowerDNS server needs to have exposed API (example configuration for PowerDNS 4.x):
```
api=yes
api-key=secret
webserver=yes
webserver-address=0.0.0.0
webserver-allow-from=172.5.0.0/16
```
And again, PowerDNS connection is configured via env vars (it needs url of the PowerDNS server, api key and a version of PowerDNS server, for example 4.0):
```
(name=default value)
PDNS_API_URL="http://pdns:8081/"
PDNS_API_KEY=""
PDNS_VERSION=""
```
If this container is linked with pdns-mysql from this repo with alias `pdns`, it will be configured automatically and none of the env vars from above are needed to be specified.
### PowerDNS Admin API keys and SALT
In order to be able to generate an API Key, you will need to specify the SALT via `PDNS_ADMIN_SALT` env var. This is a secret value, which can be generated via command:
```
python3 -c 'import bcrypt; print(bcrypt.gensalt().decode("utf-8"));'
```
Example value looks like `$2b$12$xxxxxxxxxxxxxxxxxxxxxx` - remember that when using docker-compose, literal `$` must be specified as `$$`.
### Persistent data
There is a directory with user uploads which should be persistent: `/opt/powerdns-admin/upload`
### Example
When linked with pdns-mysql from this repo and with LDAP auth:
```
docker run -d --name pdns-admin-uwsgi \
--link mariadb:mysql --link pdns-master:pdns \
-v pdns-admin-upload:/opt/powerdns-admin/upload \
pschiffe/pdns-admin-uwsgi
```
## pdns-admin-static
![Docker Image Size (tag)](https://img.shields.io/docker/image-size/pschiffe/pdns-admin-static/latest?label=latest) ![Docker Pulls](https://img.shields.io/docker/pulls/pschiffe/pdns-admin-static)
https://hub.docker.com/r/pschiffe/pdns-admin-static/
Fronted image with nginx and static files for [PowerDNS Admin](https://github.com/PowerDNS-Admin/PowerDNS-Admin). Exposes port 80 for connections, expects uWSGI backend image under `pdns-admin-uwsgi` alias.
### Example
```
docker run -d -p 8080:80 --name pdns-admin-static \
--link pdns-admin-uwsgi:pdns-admin-uwsgi \
pschiffe/pdns-admin-static
```

View file

@ -94,12 +94,14 @@ services:
- mariadb
- pdns-master
pdns-admin-uwsgi:
image: pschiffe/pdns-admin-uwsgi
pdns-admin:
image: pschiffe/pdns-admin
networks:
pdns:
aliases:
- pdns-admin-uwsgi
- pdns-admin
ports:
- '8989:8080'
volumes:
- /etc/localtime:/etc/localtime:ro
environment:
@ -110,17 +112,6 @@ services:
- mariadb
- pdns-master
pdns-admin-static:
image: pschiffe/pdns-admin-static
networks:
- pdns
ports:
- '8989:80'
volumes:
- /etc/localtime:/etc/localtime:ro
depends_on:
- pdns-admin-uwsgi
networks:
pdns:
ipam:

View file

@ -23,24 +23,14 @@ spec:
hostAliases:
- ip: "127.0.0.1"
hostnames:
- "pdns-admin-uwsgi"
- "pdns-admin"
containers:
- name: pdns-admin-static
image: pschiffe/pdns-admin-static
- name: pdns-admin
image: pschiffe/pdns-admin
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
- containerPort: 8080
protocol: TCP
resources:
limits:
cpu: 300m
memory: 128Mi
requests:
cpu: 50m
memory: 64Mi
- name: pdns-admin-uwsgi
image: pschiffe/pdns-admin-uwsgi
imagePullPolicy: IfNotPresent
env:
- name: PDNS_ADMIN_SQLA_DB_HOST
value: "mariadb-pdns"
@ -106,7 +96,7 @@ spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
targetPort: 8080
selector:
app.kubernetes.io/name: pdns-admin
---

43
pdns-admin/Caddyfile.tpl Normal file
View file

@ -0,0 +1,43 @@
{
http_port 8080
https_port 8443
}
{{ if all .SSL_MAIN_DOMAIN .SSL_EXTRA_DOMAINS -}}
{{ .SSL_EXTRA_DOMAINS }} {
redir https://{{ .SSL_MAIN_DOMAIN }}
}
{{ end -}}
{{ .SSL_MAIN_DOMAIN | default ":8080" }} {
@staticfiles {
path *.jpeg *.jpg *.png *.gif *.bmp *.ico *.svg *.tif *.tiff *.css *.js *.htm *.html *.ttf *.otf *.webp *.woff *.woff2 *.txt *.csv *.rtf *.doc *.docx *.xls *.xlsx *.ppt *.pptx *.odf *.odp *.ods *.odt *.pdf *.psd *.ai *.eot *.eps *.ps *.zip *.tar *.tgz *.gz *.rar *.bz2 *.7z *.aac *.m4a *.mp3 *.mp4 *.ogg *.wav *.wma *.3gp *.avi *.flv *.m4v *.mkv *.mov *.mp4 *.mpeg *.mpg *.wmv *.exe *.iso *.dmg *.swf
}
log {
output stdout
format json
}
@blocked {
path */.*
}
respond @blocked 404
encode zstd gzip
header X-Content-Type-Options "nosniff"
header X-Frame-Options "SAMEORIGIN"
header @staticfiles Cache-Control "public, max-age=604800, must-revalidate"
header -Server
header -X-Powered-By
root * /opt/powerdns-admin/powerdnsadmin
route {
file_server @staticfiles {
pass_thru
}
reverse_proxy 127.0.0.1:9494
}
}

71
pdns-admin/Dockerfile Normal file
View file

@ -0,0 +1,71 @@
FROM rockylinux/rockylinux:9-ubi
RUN arch=$([ "$(arch)" = 'aarch64' ] && echo -n 'arm64' || echo -n 'amd64') \
&& echo 'install_weak_deps=False' >> /etc/dnf/dnf.conf \
&& echo 'tsflags=nodocs' >> /etc/dnf/dnf.conf \
&& echo 'assumeyes=True' >> /etc/dnf/dnf.conf \
&& curl -fsSL -o /etc/yum.repos.d/yarn.repo https://dl.yarnpkg.com/rpm/yarn.repo \
&& dnf module enable nodejs:20 \
&& dnf install dnf-plugins-core epel-release \
&& dnf config-manager --set-disabled epel-cisco-openh264 \
&& dnf config-manager --set-enabled crb \
&& dnf --refresh upgrade \
&& dnf install \
caddy \
mariadb \
npm \
python3-cffi \
python3-ldap \
python3-lxml \
python3-mysqlclient \
python3-pip \
python3-pyyaml \
python3-saml \
python3-xmlsec \
supervisor \
uwsgi \
uwsgi-plugin-python3 \
yarn \
https://github.com/kha7iq/subvars/releases/download/v0.1.5/subvars_${arch}.rpm \
&& dnf clean all
RUN mkdir -p /opt/powerdns-admin \
&& curl -fsSL https://github.com/PowerDNS-Admin/PowerDNS-Admin/archive/refs/tags/v0.4.1.tar.gz \
| tar -xzf - -C /opt/powerdns-admin --strip 1 \
&& sed -i \
-e '/cffi/d' \
-e '/lxml/d' \
-e '/mysqlclient/d' \
-e '/psycopg2/d' \
-e '/python-ldap/d' \
-e '/python3-saml/d' \
-e '/PyYAML/d' \
/opt/powerdns-admin/requirements.txt \
&& chown -R root: /opt/powerdns-admin
WORKDIR /opt/powerdns-admin
RUN pip3 install -r requirements.txt --no-cache-dir
ENV FLASK_APP=/opt/powerdns-admin/powerdnsadmin/__init__.py
ENV SSL_MAIN_DOMAIN=""
ENV SSL_EXTRA_DOMAINS=""
COPY config.py.tpl Caddyfile.tpl docker-entrypoint.sh /
COPY run.py .
COPY --chown=uwsgi:uwsgi pdns-admin.ini /etc/uwsgi.ini
COPY supervisor.ini /etc/supervisord.d/supervisor.ini
RUN subvars --prefix 'PDNS_ADMIN_' < /config.py.tpl > /opt/powerdns-admin/config.py \
&& sed -i '/SQLALCHEMY_DATABASE_URI/d' /opt/powerdns-admin/config.py
RUN yarn install --pure-lockfile --production \
&& yarn cache clean \
&& flask assets build \
&& chown -R uwsgi: /opt/powerdns-admin/powerdnsadmin/static/.webassets-cache
EXPOSE 8080
ENTRYPOINT [ "/docker-entrypoint.sh" ]
CMD [ "/usr/bin/supervisord", "-c", "/etc/supervisord.conf" ]

32
pdns-admin/config.py.tpl Normal file
View file

@ -0,0 +1,32 @@
import os
basedir = os.path.abspath(os.path.dirname(__file__))
### BASIC APP CONFIG
BIND_ADDRESS = '0.0.0.0'
PORT = 9191
HSTS_ENABLED = False
# CAPTCHA Config
CAPTCHA_ENABLE = True
CAPTCHA_LENGTH = 6
CAPTCHA_WIDTH = 160
CAPTCHA_HEIGHT = 60
CAPTCHA_SESSION_KEY = 'captcha_image'
SESSION_TYPE = 'sqlalchemy'
# SAML Authnetication
SAML_ENABLED = False
# Configuration from env vars
{{ range $key, $value := match "PDNS_ADMIN_" -}}
{{ $v := $value | trimAll "\"'\\" -}}
{{ if or (eq $v "True" "False" "None" "0") (ne ($v | int) 0) -}}
{{- $key | trimPrefix "PDNS_ADMIN_" }} = {{ $v }}
{{ else -}}
{{- $key | trimPrefix "PDNS_ADMIN_" }} = '{{ $v }}'
{{ end -}}
{{ end }}
### DATABASE CONFIG
SQLALCHEMY_DATABASE_URI = 'mysql://' + SQLA_DB_USER + ':' + SQLA_DB_PASSWORD + '@' + SQLA_DB_HOST + ':' + str(SQLA_DB_PORT) + '/' + SQLA_DB_NAME
SQLALCHEMY_TRACK_MODIFICATIONS = True

63
pdns-admin/docker-entrypoint.sh Executable file
View file

@ -0,0 +1,63 @@
#!/bin/bash
set -euo pipefail
# Configure mysql env vars
: "${PDNS_ADMIN_SQLA_DB_HOST:=${MYSQL_ENV_MYSQL_HOST:-mysql}}"
: "${PDNS_ADMIN_SQLA_DB_PORT:=${MYSQL_ENV_MYSQL_PORT:-3306}}"
: "${PDNS_ADMIN_SQLA_DB_USER:=${MYSQL_ENV_MYSQL_USER:-root}}"
if [ "${PDNS_ADMIN_SQLA_DB_USER}" = "root" ]; then
: "${PDNS_ADMIN_SQLA_DB_PASSWORD:=$MYSQL_ENV_MYSQL_ROOT_PASSWORD}"
fi
: "${PDNS_ADMIN_SQLA_DB_PASSWORD:=${MYSQL_ENV_MYSQL_PASSWORD:-powerdnsadmin}}"
: "${PDNS_ADMIN_SQLA_DB_NAME:=${MYSQL_ENV_MYSQL_DATABASE:-powerdnsadmin}}"
# Cleanup quotes from mysql env vars
PDNS_ADMIN_SQLA_DB_HOST="${PDNS_ADMIN_SQLA_DB_HOST//[\'\"]}"
PDNS_ADMIN_SQLA_DB_PORT="${PDNS_ADMIN_SQLA_DB_PORT//[\'\"]}"
PDNS_ADMIN_SQLA_DB_USER="${PDNS_ADMIN_SQLA_DB_USER//[\'\"]}"
PDNS_ADMIN_SQLA_DB_PASSWORD="${PDNS_ADMIN_SQLA_DB_PASSWORD//[\'\"]}"
PDNS_ADMIN_SQLA_DB_NAME="${PDNS_ADMIN_SQLA_DB_NAME//[\'\"]}"
export PDNS_ADMIN_SQLA_DB_HOST PDNS_ADMIN_SQLA_DB_PORT PDNS_ADMIN_SQLA_DB_USER PDNS_ADMIN_SQLA_DB_PASSWORD PDNS_ADMIN_SQLA_DB_NAME
# Configure pdns server env vars
: "${PDNS_API_URL:=http://${PDNS_ENV_PDNS_webserver_host:-pdns}:${PDNS_ENV_PDNS_webserver_port:-8081}/}"
: "${PDNS_API_KEY:=${PDNS_ENV_PDNS_api_key:-}}"
: "${PDNS_VERSION:=${PDNS_ENV_VERSION:-}}"
# Generate secret key
[ -f /root/secret-key ] || tr -dc _A-Z-a-z-0-9 < /dev/urandom | head -c 32 > /root/secret-key || true
PDNS_ADMIN_SECRET_KEY="$(cat /root/secret-key)"
export PDNS_ADMIN_SECRET_KEY
subvars --prefix 'SSL_' < '/Caddyfile.tpl' > '/etc/caddy/Caddyfile'
subvars --prefix 'PDNS_ADMIN_' < '/config.py.tpl' > '/opt/powerdns-admin/powerdnsadmin/default_config.py'
# Initialize DB if needed
MYSQL_COMMAND="mysql -h ${PDNS_ADMIN_SQLA_DB_HOST} -P ${PDNS_ADMIN_SQLA_DB_PORT} -u ${PDNS_ADMIN_SQLA_DB_USER} -p${PDNS_ADMIN_SQLA_DB_PASSWORD}"
until $MYSQL_COMMAND -e ';' ; do
>&2 echo 'MySQL is unavailable - sleeping'
sleep 1
done
$MYSQL_COMMAND -e "CREATE DATABASE IF NOT EXISTS ${PDNS_ADMIN_SQLA_DB_NAME}"
flask db upgrade
# initial settings if not available in the DB
$MYSQL_COMMAND "${PDNS_ADMIN_SQLA_DB_NAME}" -e "INSERT INTO setting (name, value) SELECT * FROM (SELECT 'pdns_api_url', '${PDNS_API_URL//[\'\"]}') AS tmp WHERE NOT EXISTS (SELECT name FROM setting WHERE name = 'pdns_api_url') LIMIT 1;"
$MYSQL_COMMAND "${PDNS_ADMIN_SQLA_DB_NAME}" -e "INSERT INTO setting (name, value) SELECT * FROM (SELECT 'pdns_api_key', '${PDNS_API_KEY//[\'\"]}') AS tmp WHERE NOT EXISTS (SELECT name FROM setting WHERE name = 'pdns_api_key') LIMIT 1;"
$MYSQL_COMMAND "${PDNS_ADMIN_SQLA_DB_NAME}" -e "INSERT INTO setting (name, value) SELECT * FROM (SELECT 'pdns_version', '${PDNS_VERSION//[\'\"]}') AS tmp WHERE NOT EXISTS (SELECT name FROM setting WHERE name = 'pdns_version') LIMIT 1;"
# update pdns api settings if env changed
$MYSQL_COMMAND "${PDNS_ADMIN_SQLA_DB_NAME}" -e "UPDATE setting SET value='${PDNS_API_URL//[\'\"]}' WHERE name='pdns_api_url';"
$MYSQL_COMMAND "${PDNS_ADMIN_SQLA_DB_NAME}" -e "UPDATE setting SET value='${PDNS_API_KEY//[\'\"]}' WHERE name='pdns_api_key';"
$MYSQL_COMMAND "${PDNS_ADMIN_SQLA_DB_NAME}" -e "UPDATE setting SET value='${PDNS_VERSION//[\'\"]}' WHERE name='pdns_version';"
mkdir -p /run/uwsgi
chown uwsgi: /run/uwsgi
exec "$@"

26
pdns-admin/pdns-admin.ini Normal file
View file

@ -0,0 +1,26 @@
[uwsgi]
strict = true
master = true
die-on-term = true
need-app = true
plugins = python3
uid = uwsgi
gid = uwsgi
chdir = /opt/powerdns-admin
pythonpath = /opt/powerdns-admin
mount = /=run.py
manage-script-name = true
callable = app
vacuum = true
harakiri = 20
buffer-size = 32768
post-buffering = 8192
http-socket = 127.0.0.1:9494
pidfile = /run/uwsgi/%n.pid
enable-threads = true

5
pdns-admin/run.py Normal file
View file

@ -0,0 +1,5 @@
#!/usr/bin/env python3
from powerdnsadmin import create_app
app = create_app()

24
pdns-admin/supervisor.ini Normal file
View file

@ -0,0 +1,24 @@
[supervisord]
nodaemon = true
user = root
logfile = /dev/stderr
logfile_maxbytes = 0
loglevel = info
[program:uwsgi]
command = /usr/sbin/uwsgi --ini /etc/uwsgi.ini
autorestart = true
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0
[program:caddy]
command = /usr/bin/caddy run --config /etc/caddy/Caddyfile
user = caddy
environment = HOME="/var/lib/caddy"
autorestart = true
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0