Skip to content

Commit 07fcb20

Browse files
tobiasgecimnine
andauthored
Switch server to Granian (#1561)
* Switch server to Granian Because the development of Nginx Unit has been stopped, switch the server to Granian which still allows to serve the Python application and the static files from one server. * Addressed review comments * Update docker/launch-netbox.sh Co-authored-by: Christian Mäder <[email protected]> * Update docker/launch-netbox.sh Co-authored-by: Christian Mäder <[email protected]> --------- Co-authored-by: Christian Mäder <[email protected]>
1 parent c89fd33 commit 07fcb20

File tree

11 files changed

+47
-158
lines changed

11 files changed

+47
-158
lines changed

.github/workflows/push.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ jobs:
4242
VALIDATE_GITHUB_ACTIONS_ZIZMOR: false
4343
VALIDATE_GITLEAKS: false
4444
VALIDATE_JSCPD: false
45+
VALIDATE_PYTHON_PYLINT: false
4546
VALIDATE_TRIVY: false
4647
FILTER_REGEX_EXCLUDE: (.*/)?(LICENSE|configuration/.*)
4748
EDITORCONFIG_FILE_NAME: .editorconfig-checker.json

Dockerfile

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ ARG NETBOX_PATH
2727
COPY ${NETBOX_PATH}/requirements.txt requirements-container.txt /
2828
ENV VIRTUAL_ENV=/opt/netbox/venv
2929
RUN \
30-
# Gunicorn is not needed because we use Nginx Unit
30+
# Gunicorn is not needed because we use Granian
3131
sed -i -e '/gunicorn/d' /requirements.txt && \
3232
# We need 'social-auth-core[all]' in the Docker image. But if we put it in our own requirements-container.txt
3333
# we have potential version conflicts and the build will fail.
@@ -46,8 +46,6 @@ RUN \
4646
ARG FROM
4747
FROM ${FROM} AS main
4848

49-
COPY docker/unit.list /etc/apt/sources.list.d/unit.list
50-
ADD --chmod=444 --chown=0:0 https://unit.nginx.org/keys/nginx-keyring.gpg /usr/share/keyrings/nginx-keyring.gpg
5149
RUN export DEBIAN_FRONTEND=noninteractive \
5250
&& apt-get update -qq \
5351
&& apt-get upgrade \
@@ -64,8 +62,6 @@ RUN export DEBIAN_FRONTEND=noninteractive \
6462
openssl \
6563
python3 \
6664
tini \
67-
unit-python3.12=1.34.2-1~noble \
68-
unit=1.34.2-1~noble \
6965
&& rm -rf /var/lib/apt/lists/*
7066

7167
# Copy the modified 'requirements*.txt' files, to have the files actually used during installation
@@ -81,21 +77,21 @@ COPY docker/ldap_config.docker.py /opt/netbox/netbox/netbox/ldap_config.py
8177
COPY docker/docker-entrypoint.sh /opt/netbox/docker-entrypoint.sh
8278
COPY docker/launch-netbox.sh /opt/netbox/launch-netbox.sh
8379
COPY configuration/ /etc/netbox/config/
84-
COPY docker/nginx-unit.json /etc/unit/
80+
COPY docker/granian.py /opt/netbox/netbox/netbox/granian.py
8581
COPY VERSION /opt/netbox/VERSION
8682

8783
WORKDIR /opt/netbox/netbox
8884

8985
# Must set permissions for '/opt/netbox/netbox/media' directory
9086
# to g+w so that pictures can be uploaded to netbox.
91-
RUN mkdir -p static media /opt/unit/state/ /opt/unit/tmp/ \
92-
&& chown -R unit:root /opt/unit/ media reports scripts \
93-
&& chmod -R g+w /opt/unit/ media reports scripts \
94-
&& cd /opt/netbox/ && SECRET_KEY="dummyKeyWithMinimumLength-------------------------" /opt/netbox/venv/bin/python -m mkdocs build \
95-
--config-file /opt/netbox/mkdocs.yml --site-dir /opt/netbox/netbox/project-static/docs/ \
96-
&& DEBUG="true" SECRET_KEY="dummyKeyWithMinimumLength-------------------------" /opt/netbox/venv/bin/python /opt/netbox/netbox/manage.py collectstatic --no-input \
97-
&& mkdir /opt/netbox/netbox/local \
98-
&& echo "build: Docker-$(cat /opt/netbox/VERSION)" > /opt/netbox/netbox/local/release.yaml
87+
RUN useradd --home-dir /opt/netbox/ --no-create-home --no-user-group --system --shell /bin/false --uid 999 --gid 0 netbox \
88+
&& mkdir -p static media local \
89+
&& chown -R netbox:root media reports scripts \
90+
&& chmod -R g+w media reports scripts \
91+
&& cd /opt/netbox/ && SECRET_KEY="dummyKeyWithMinimumLength-------------------------" /opt/netbox/venv/bin/python -m mkdocs build \
92+
--config-file /opt/netbox/mkdocs.yml --site-dir /opt/netbox/netbox/project-static/docs/ \
93+
&& DEBUG="true" SECRET_KEY="dummyKeyWithMinimumLength-------------------------" /opt/netbox/venv/bin/python /opt/netbox/netbox/manage.py collectstatic --no-input \
94+
&& echo "build: Docker-$(cat /opt/netbox/VERSION)" > /opt/netbox/netbox/local/release.yaml
9995

10096
ENV LANG=C.utf8 PATH=/opt/netbox/venv/bin:$PATH VIRTUAL_ENV=/opt/netbox/venv UV_NO_CACHE=1
10197
ENTRYPOINT [ "/usr/bin/tini", "--" ]

docker-compose.override.yml.example

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@ services:
22
netbox:
33
ports:
44
- "8000:8080"
5-
# If you want the Nginx unit status page visible from the
6-
# outside of the container add the following port mapping:
7-
# - "8001:8081"
85
# healthcheck:
96
# Time for which the health check can fail after the container is started.
107
# This depends mostly on the performance of your database. On the first start,
@@ -19,4 +16,3 @@ services:
1916
# SUPERUSER_EMAIL: ""
2017
# SUPERUSER_NAME: ""
2118
# SUPERUSER_PASSWORD: ""
22-

docker-compose.test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ services:
99
redis-cache:
1010
condition: service_healthy
1111
env_file: env/netbox.env
12-
user: "unit:root"
12+
user: "netbox:root"
1313
volumes:
1414
- ./test-configuration/test_config.py:/etc/netbox/config/test_config.py:z,ro
1515
healthcheck:

docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ services:
66
- redis
77
- redis-cache
88
env_file: env/netbox.env
9-
user: "unit:root"
9+
user: "netbox:root"
1010
healthcheck:
1111
test: curl -f http://localhost:8080/login/ || exit 1
1212
start_period: 90s

docker/granian.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from granian.utils.proxies import wrap_wsgi_with_proxy_headers
2+
from netbox.wsgi import application
3+
4+
application = wrap_wsgi_with_proxy_headers(
5+
application,
6+
trusted_hosts=[
7+
"10.0.0.0/8",
8+
"172.16.0.0/12",
9+
"192.168.0.0/16",
10+
"fc00::/7",
11+
"fe80::/10",
12+
],
13+
)

docker/launch-netbox.sh

Lines changed: 18 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,20 @@
11
#!/bin/bash
22

3-
UNIT_CONFIG="${UNIT_CONFIG-/etc/unit/nginx-unit.json}"
4-
# Also used in "nginx-unit.json"
5-
UNIT_SOCKET="/opt/unit/unit.sock"
6-
7-
load_configuration() {
8-
MAX_WAIT=10
9-
WAIT_COUNT=0
10-
while [ ! -S $UNIT_SOCKET ]; do
11-
if [ $WAIT_COUNT -ge $MAX_WAIT ]; then
12-
echo "⚠️ No control socket found; configuration will not be loaded."
13-
return 1
14-
fi
15-
16-
WAIT_COUNT=$((WAIT_COUNT + 1))
17-
echo "⏳ Waiting for control socket to be created... (${WAIT_COUNT}/${MAX_WAIT})"
18-
19-
sleep 1
20-
done
21-
22-
# even when the control socket exists, it does not mean unit has finished initialisation
23-
# this curl call will get a reply once unit is fully launched
24-
curl --silent --output /dev/null --request GET --unix-socket $UNIT_SOCKET http://localhost/
25-
26-
echo "⚙️ Applying configuration from $UNIT_CONFIG"
27-
28-
RESP_CODE=$(
29-
curl \
30-
--silent \
31-
--output /dev/null \
32-
--write-out '%{http_code}' \
33-
--request PUT \
34-
--data-binary "@${UNIT_CONFIG}" \
35-
--unix-socket $UNIT_SOCKET \
36-
http://localhost/config
37-
)
38-
if [ "$RESP_CODE" != "200" ]; then
39-
echo "⚠️ Could not load Unit configuration"
40-
kill "$(cat /opt/unit/unit.pid)"
41-
return 1
42-
fi
43-
44-
echo "✅ Unit configuration loaded successfully"
45-
}
46-
47-
load_configuration &
48-
49-
exec unitd \
50-
--no-daemon \
51-
--control unix:$UNIT_SOCKET \
52-
--pid /opt/unit/unit.pid \
53-
--log /dev/stdout \
54-
--statedir /opt/unit/state/ \
55-
--tmpdir /opt/unit/tmp/ \
56-
--user unit \
57-
--group root
3+
exec granian \
4+
--host "::" \
5+
--port "8080" \
6+
--interface "wsgi" \
7+
--no-ws \
8+
--workers "${GRANIAN_WORKERS:-4}" \
9+
--respawn-failed-workers \
10+
--backpressure "${GRANIAN_BACKPRESSURE:-${GRANIAN_WORKERS:-4}}" \
11+
--loop "uvloop" \
12+
--log \
13+
--log-level "info" \
14+
--access-log \
15+
--working-dir "/opt/netbox/netbox/" \
16+
--static-path-route "/static" \
17+
--static-path-mount "/opt/netbox/netbox/static/" \
18+
--pid-file "/tmp/granian.pid" \
19+
"${GRANIAN_EXTRA_ARGS[@]}" \
20+
"netbox.granian:application"

docker/nginx-unit.json

Lines changed: 0 additions & 82 deletions
This file was deleted.

docker/unit.list

Lines changed: 0 additions & 1 deletion
This file was deleted.

env/netbox.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ EMAIL_USERNAME=netbox
1515
# EMAIL_USE_SSL and EMAIL_USE_TLS are mutually exclusive, i.e. they can't both be `true`!
1616
EMAIL_USE_SSL=false
1717
EMAIL_USE_TLS=false
18+
GRANIAN_BACKPRESSURE=4
19+
GRANIAN_WORKERS=4
1820
GRAPHQL_ENABLED=true
1921
MEDIA_ROOT=/opt/netbox/netbox/media
2022
METRICS_ENABLED=false

0 commit comments

Comments
 (0)