Skip to content

Commit ba552c8

Browse files
authored
Merge pull request #56 from devilbox/release-1.0-beta2
Release 1.0 beta2
2 parents 36c416a + d59fe77 commit ba552c8

File tree

11 files changed

+395
-34
lines changed

11 files changed

+395
-34
lines changed

Dockerfiles/Dockerfile.alpine

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ LABEL \
1212
###
1313
### Build arguments
1414
###
15-
ARG VHOST_GEN_GIT_REF=1.0.8
15+
ARG VHOST_GEN_GIT_REF=1.0.9
1616
ARG WATCHERD_GIT_REF=v1.0.7
1717
ARG CERT_GEN_GIT_REF=0.10
1818

@@ -38,7 +38,7 @@ RUN set -eux \
3838
${RUN_DEPS} \
3939
\
4040
# Install vhost-gen
41-
&& wget --no-check-certificate -O vhost-gen.tar.gz "https://github.com/devilbox/vhost-gen/archive/refs/tags/${VHOST_GEN_GIT_REF}.tar.gz" \
41+
&& wget --no-check-certificate -O vhost-gen.tar.gz "https://github.com/devilbox/vhost-gen/archive/${VHOST_GEN_GIT_REF}.tar.gz" \
4242
&& tar xvfz vhost-gen.tar.gz \
4343
&& cd "vhost-gen-${VHOST_GEN_GIT_REF}" \
4444
&& make install \
@@ -66,7 +66,7 @@ RUN set -eux \
6666
ENV MY_USER=nginx
6767
ENV MY_GROUP=nginx
6868
ENV HTTPD_START="/usr/sbin/nginx"
69-
ENV HTTPD_RELOAD="nginx -s stop"
69+
ENV HTTPD_RELOAD="nginx -s reload"
7070
ENV HTTPD_VERSION="nginx -V 2>&1 | head -1 | awk '{print \$3}'"
7171
ENV VHOSTGEN_HTTPD_SERVER="nginx"
7272

Dockerfiles/Dockerfile.debian

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ LABEL \
1212
###
1313
### Build arguments
1414
###
15-
ARG VHOST_GEN_GIT_REF=1.0.8
15+
ARG VHOST_GEN_GIT_REF=1.0.9
1616
ARG WATCHERD_GIT_REF=v1.0.7
1717
ARG CERT_GEN_GIT_REF=0.10
1818

@@ -36,7 +36,7 @@ RUN set -eux \
3636
${RUN_DEPS} \
3737
\
3838
# Install vhost-gen
39-
&& wget --no-check-certificate -O vhost-gen.tar.gz "https://github.com/devilbox/vhost-gen/archive/refs/tags/${VHOST_GEN_GIT_REF}.tar.gz" \
39+
&& wget --no-check-certificate -O vhost-gen.tar.gz "https://github.com/devilbox/vhost-gen/archive/${VHOST_GEN_GIT_REF}.tar.gz" \
4040
&& tar xvfz vhost-gen.tar.gz \
4141
&& cd "vhost-gen-${VHOST_GEN_GIT_REF}" \
4242
&& make install \
@@ -65,7 +65,7 @@ RUN set -eux \
6565
ENV MY_USER=nginx
6666
ENV MY_GROUP=nginx
6767
ENV HTTPD_START="/usr/sbin/nginx"
68-
ENV HTTPD_RELOAD="nginx -s stop"
68+
ENV HTTPD_RELOAD="nginx -s reload"
6969
ENV HTTPD_VERSION="nginx -V 2>&1 | head -1 | awk '{print \$3}'"
7070
ENV VHOSTGEN_HTTPD_SERVER="nginx"
7171

Dockerfiles/data/docker-entrypoint.d/.httpd/func-backend.sh

+35-6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ set -o pipefail
2222
### conf:phpfpm:tcp:<host>:<port> # Remote PHP-FPM server at <host>:<port>
2323
### conf:rproxy:http:<host>:<port> # Reverse Proxy server at http://<host>:<port>
2424
### conf:rproxy:https:<host>:<port> # Reverse Proxy server at https://<host>:<port>
25+
### conf:rproxy:ws:<host>:<port> # Reverse Proxy (websocket) at ws://<host>:<port>
26+
### conf:rproxy:wss:<host>:<port> # Reverse Proxy (websocket) at wss://<host>:<port>
2527
###
2628
###
2729
### Format-2: file:<file>
@@ -40,6 +42,8 @@ set -o pipefail
4042
### Examples:
4143
### conf:rproxy:http:10.0.0.1:3000
4244
### conf:rproxy:https:mydomain.com:8080
45+
### conf:rproxy:ws:10.0.0.1:3000
46+
### conf:rproxy:wss:10.0.0.1:3000
4347
###
4448
### Note: If no file is found, a warning will be logged and no Reverse proxy will be created.
4549
###
@@ -90,7 +94,13 @@ backend_conf_is_valid() {
9094
fi
9195
# 3. Protocol: 'tcp', 'http' or 'https'
9296
if ! backend_is_valid_conf_prot "${1}"; then
93-
echo "Invalid backend conf:<prot> in: '${1}'. It must be 'tcp', 'http' or 'https'"
97+
# Apache 2.2 does not have websocket support
98+
if [ "${VHOSTGEN_HTTPD_SERVER}" = "apache22" ]; then
99+
echo "Invalid backend conf:<prot> in: '${1}'. It must be 'tcp', 'http' or 'https'."
100+
# All other webserver have websocket support
101+
else
102+
echo "Invalid backend conf:<prot> in: '${1}'. It must be 'tcp', 'http', 'https', 'ws' or 'wss'."
103+
fi
94104
return 1
95105
fi
96106
# 4. Host
@@ -116,9 +126,22 @@ backend_conf_is_valid() {
116126
fi
117127
# 7. Validate conf <protocol> rproxy == http(s)?
118128
if [ "${backend_conf_type}" = "rproxy" ]; then
119-
if [ "${backend_conf_prot}" != "http" ] && [ "${backend_conf_prot}" != "https" ]; then
120-
echo "Invalid backend conf:<prot> in: '${1}'. 'rproxy' only supports 'http' or 'https'"
121-
return 1
129+
# Apache 2.2 does not have websocket support
130+
if [ "${VHOSTGEN_HTTPD_SERVER}" = "apache22" ]; then
131+
if [ "${backend_conf_prot}" != "http" ] \
132+
&& [ "${backend_conf_prot}" != "https" ]; then
133+
echo "Invalid backend conf:<prot> in: '${1}'. 'rproxy' only supports 'http' and 'https'"
134+
return 1
135+
fi
136+
# All other webserver have websocket support
137+
else
138+
if [ "${backend_conf_prot}" != "http" ] \
139+
&& [ "${backend_conf_prot}" != "https" ] \
140+
&& [ "${backend_conf_prot}" != "ws" ] \
141+
&& [ "${backend_conf_prot}" != "wss" ]; then
142+
echo "Invalid backend conf:<prot> in: '${1}'. 'rproxy' only supports 'http', 'https', 'ws' and 'wss'"
143+
return 1
144+
fi
122145
fi
123146
fi
124147
}
@@ -181,8 +204,14 @@ backend_is_valid_conf_prot() {
181204
local value
182205
value="$( get_backend_conf_prot "${1}" )"
183206

184-
if [ "${value}" != "tcp" ] && [ "${value}" != "http" ] && [ "${value}" != "https" ]; then
185-
return 1
207+
if [ "${VHOSTGEN_HTTPD_SERVER}" = "apache22" ];then
208+
if [ "${value}" != "tcp" ] && [ "${value}" != "http" ] && [ "${value}" != "https" ]; then
209+
return 1
210+
fi
211+
else
212+
if [ "${value}" != "tcp" ] && [ "${value}" != "http" ] && [ "${value}" != "https" ] && [ "${value}" != "ws" ] && [ "${value}" != "wss" ]; then
213+
return 1
214+
fi
186215
fi
187216
return 0
188217
}

Dockerfiles/data/docker-entrypoint.d/02-env-vars-validate.sh

+27-10
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,12 @@ _validate_vhost_backend() {
647647
# 5. Validate conf <protocol>
648648
if ! backend_is_valid_conf_prot "${value}"; then
649649
_log_env_valid "invalid" "${name}" "${value}" "Invalid format"
650-
_log_env_valid "invalid" "${name}" "${backend_conf_prot}" "<proto> is invalid. Must be: " "'tcp', 'http' or 'https'"
650+
# Apache 2.2 does not have websocket support
651+
if [ "${VHOSTGEN_HTTPD_SERVER}" = "apache22" ];then
652+
_log_env_valid "invalid" "${name}" "${backend_conf_prot}" "<proto> is invalid. Must be: " "'tcp', 'http' or 'https'"
653+
else
654+
_log_env_valid "invalid" "${name}" "${backend_conf_prot}" "<proto> is invalid. Must be: " "'tcp', 'http', 'https', 'ws' or 'wss'"
655+
fi
651656
_log_backend_examples "conf"
652657
exit 1
653658
fi
@@ -662,11 +667,21 @@ _validate_vhost_backend() {
662667
fi
663668
# 7. Validate conf <protocol> rproxy == http(s)?
664669
if [ "${backend_conf_type}" = "rproxy" ]; then
665-
if [ "${backend_conf_prot}" != "http" ] && [ "${backend_conf_prot}" != "https" ]; then
666-
_log_env_valid "invalid" "${name}" "${value}" "Invalid format"
667-
_log_env_valid "invalid" "${name}" "${backend_conf_prot}" "rproxy only supports protocol " "'http' or 'https'"
668-
_log_backend_examples "conf"
669-
exit 1
670+
# Apache 2.2 does not have websocket support
671+
if [ "${VHOSTGEN_HTTPD_SERVER}" = "apache22" ];then
672+
if [ "${backend_conf_prot}" != "http" ] && [ "${backend_conf_prot}" != "https" ]; then
673+
_log_env_valid "invalid" "${name}" "${value}" "Invalid format"
674+
_log_env_valid "invalid" "${name}" "${backend_conf_prot}" "rproxy only supports protocol " "'http' and 'https'"
675+
_log_backend_examples "conf"
676+
exit 1
677+
fi
678+
else
679+
if [ "${backend_conf_prot}" != "http" ] && [ "${backend_conf_prot}" != "https" ] && [ "${backend_conf_prot}" != "ws" ] && [ "${backend_conf_prot}" != "wss" ]; then
680+
_log_env_valid "invalid" "${name}" "${value}" "Invalid format"
681+
_log_env_valid "invalid" "${name}" "${backend_conf_prot}" "rproxy only supports protocol " "'http', 'https', 'ws' and 'wss'"
682+
_log_backend_examples "conf"
683+
exit 1
684+
fi
670685
fi
671686
fi
672687
# 8. Validate conf <host>
@@ -1062,11 +1077,13 @@ _log_backend_examples() {
10621077
log "err" "Example: conf:phpfpm:tcp:10.0.0.100:9000"
10631078
log "err" "Example: conf:phpfpm:tcp:domain.com:9000"
10641079
log "err" ""
1065-
log "err" "Example: conf:rproxy:http:10.0.0.100:3000"
1066-
log "err" "Example: conf:rproxy:http:domain.com:443"
1067-
log "err" ""
1068-
log "err" "Example: conf:rproxy:https:10.0.0.100:8080"
1080+
log "err" "Example: conf:rproxy:http:10.0.0.100:8080"
10691081
log "err" "Example: conf:rproxy:https:domain.com:8443"
1082+
if [ "${VHOSTGEN_HTTPD_SERVER}" != "apache22" ]; then
1083+
log "err" ""
1084+
log "err" "Example: conf:rproxy:ws:10.0.0.100:8080"
1085+
log "err" "Example: conf:rproxy:wss:domain.com:8443"
1086+
fi
10701087
fi
10711088
if [ "${show}" = "all" ] || [ "${show}" = "file" ]; then
10721089
log "err" ""

Dockerfiles/data/nginx/nginx.conf

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ http {
3636

3737
# [emerg] could not build server_names_hash, you should increase server_names_hash_bucket_size: 32
3838
# https://stackoverflow.com/questions/26357487/
39-
server_names_hash_bucket_size 64;
39+
server_names_hash_bucket_size 128;
4040

4141

4242
# -------------------------------------------------------------------------------

Dockerfiles/data/vhost-gen/templates-main/nginx.yml

+23-4
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,31 @@ vhost_type:
8484
root "__DOCUMENT_ROOT__";
8585
index __INDEX__;
8686
87-
# Reverse Proxy (-r)
87+
# Reverse Proxy (-r http(s)://ADDR:PORT)
8888
rproxy: |
89-
# Define the vhost to reverse proxy
89+
# Define Reverse Proxy
9090
location __LOCATION__ {
91-
proxy_set_header Host $host;
92-
proxy_set_header X-Real-IP $remote_addr;
91+
# https://stackoverflow.com/a/72586833
92+
proxy_set_header Host $host;
93+
proxy_set_header X-Real-IP $remote_addr;
94+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
95+
# Proxy connection
96+
proxy_pass __PROXY_PROTO__://__PROXY_ADDR__:__PROXY_PORT__;
97+
}
98+
99+
# Reverse Proxy with websocket support (-r ws(s)://ADDR:PORT)
100+
rproxy_ws: |
101+
# Define Reverse Proxy with Websock support
102+
location __LOCATION__ {
103+
# https://stackoverflow.com/a/72586833
104+
proxy_set_header Host $host;
105+
proxy_set_header X-Real-IP $remote_addr;
106+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
107+
# Websocket settings
108+
proxy_http_version 1.1;
109+
proxy_set_header Upgrade $http_upgrade;
110+
proxy_set_header Connection "Upgrade";
111+
# Proxy connection
93112
proxy_pass __PROXY_PROTO__://__PROXY_ADDR__:__PROXY_PORT__;
94113
}
95114

README.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
This image is based on the official **[Nginx](https://hub.docker.com/_/nginx)** Docker image and extends it with the ability to have **virtual hosts created automatically**, as well as **adding SSL certificates** when creating new directories. For that to work, it integrates two tools that will take care about the whole process: **[watcherd](https://github.com/devilbox/watcherd)** and **[vhost-gen](https://github.com/devilbox/vhost-gen)**.
1919

20-
From a users perspective, you mount your local project directory into the container under `/shared/httpd`. Any directory then created in your local project directory wil spawn a new virtual host by the same name. Each virtual host optionally supports a generic or custom backend configuration (**static files**, **PHP-FPM** or **reverse proxy**).
20+
From a users perspective, you mount your local project directory into the container under `/shared/httpd`. Any directory then created in your local project directory wil spawn a new virtual host by the same name. Each virtual host optionally supports a generic or custom backend configuration: **static files**, **PHP-FPM**, **reverse proxy** (with or without **websocket** support)..
2121

2222
**HTTP/2 is enabled by default for all SSL connections.**
2323

@@ -100,7 +100,7 @@ Below is a brief overview about most outstanding features, but I would still adv
100100
* PHP is not included in the provided images, but you can enable a remote backend and link it to a PHP-FPM image. This allows you to easily switch PHP versions and choose one which is currently required.
101101

102102
#### Automated Reverse Proxy setup
103-
* In reverse proxy mode, you can choose any http or https backend of your likings. This way you can proxy NodeJS, Python, etc. and use the webserver to add SSL in front.
103+
* In reverse proxy mode, you can choose any http or https backend of your likings. This way you can proxy NodeJS, Python, etc. and use the webserver to add SSL in front. It distinguishes between HTTP backends (`http://`, `https://`) and Websocket backends (`ws://`, `wss://`) automatically and configures accordingly.
104104

105105
#### Automated SSL certificate generation
106106
* SSL certificates are generated automatically for each virtual host if you choose to enable it
@@ -246,6 +246,7 @@ The given examples distinguish between two different kinds of setup: The default
246246
&nbsp;&nbsp;&nbsp;💡 <a href="doc/examples.md#-serve-php-files-with-php-fpm-and-sync-local-permissions" >Sync local filestem permission</a><br/>
247247
&nbsp;&nbsp;&nbsp;💡 <a href="doc/examples.md#-serve-php-files-with-php-fpm-over-https" >Serve PHP files over HTTPS</a><br/>
248248
&nbsp;&nbsp;&nbsp;💡 <a href="doc/examples.md#-act-as-a-reverse-proxy-for-nodejs" >Reverse Proxy NodeJS</a><br/>
249+
&nbsp;&nbsp;&nbsp;💡 <a href="doc/examples.md#-act-as-a-reverse-proxy-websockets" >Reverse Proxy Websocket</a><br/>
249250
</td>
250251
<td>
251252
<strong>Unlimited vhosts</strong><br/>

doc/environment-variables.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ The given value determines the backend (potentia remote/reveres hosts) for the m
349349
* **Var type:** `string`
350350
* **Requires:** `MAIN_VHOST_ENABLE=1`
351351
352-
You can configure a remote backend via this environment variable. Either a remote PHP-FPM server or any kind of service via `http` or `https` reverse proxy.
352+
You can configure a remote backend via this environment variable. Either a remote PHP-FPM server or any kind of service via `http`, `https`, `ws`, or `wss` reverse proxy (where `ws` and `wss` are for websocket backends).
353353
354354
### String format
355355
@@ -369,7 +369,7 @@ The backend environment variable supports two different formats.
369369
With the direct configuration you set everything explicitly via this environment variable and nothing else is required.
370370
371371
* **`<type>`**: `phpfpm` or `rproxy`
372-
* **`<protocol>`**: `tcp`, `http` or `https`
372+
* **`<protocol>`**: `tcp`, `http`, `https`, `ws` or `wss`
373373
* **`<host>`**: the address of upstream host to send requests to (`hostname`, `IPv4` or `IPv6`).
374374
* **`<port>`**: the port of the upstream host to send requests to
375375
@@ -378,6 +378,8 @@ With the direct configuration you set everything explicitly via this environment
378378
MAIN_VHOST_BACKEND=conf:phpfpm:tcp:10.0.0.1:9000
379379
MAIN_VHOST_BACKEND=conf:rproxy:http:10.0.0.1:3000
380380
MAIN_VHOST_BACKEND=conf:rproxy:https:10.0.0.1:3000
381+
MAIN_VHOST_BACKEND=conf:rproxy:ws:10.0.0.1:3000
382+
MAIN_VHOST_BACKEND=conf:rproxy:wss:10.0.0.1:3000
381383
```
382384
383385
When specifying `phpfpm`, the vhost will also automatically be configured for serving PHP files. (including `index.php` for its directory index).

doc/examples.md

+86-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@
1414
3. [Serve PHP files with PHP-FPM and sync local permissions](#-serve-php-files-with-php-fpm-and-sync-local-permissions)
1515
4. [Serve PHP files with PHP-FPM over HTTPS](#-serve-php-files-with-php-fpm-over-https)
1616
5. [Act as a Reverse Proxy for NodeJS](#-act-as-a-reverse-proxy-for-nodejs)
17-
6. [Fully functional LEMP stack with Mass vhosts](#-fully-functional-lemp-stack-with-mass-vhosts)
18-
7. [Docker Compose](#-docker-compose)
17+
6. [Act as a Reverse Proxy for Websocket](#-act-as-a-reverse-proxy-for-websocket)
18+
7. [Fully functional LEMP stack with Mass vhosts](#-fully-functional-lemp-stack-with-mass-vhosts)
19+
8. [Docker Compose](#-docker-compose)
1920

2021

2122

@@ -237,6 +238,89 @@ The following example proxies all HTTP requests to a NodeJS remote backend. You
237238
238239
239240
241+
## 💡 Act as a Reverse Proxy for Websocket
242+
243+
The following example proxies all HTTP requests to a Websocket remote backend. You could also enable SSL on the webserver in order to access the websocket backend via HTTPS.
244+
245+
* **Vhost:** main (default)
246+
* **Backend:** Reverse Proxy (with websocket support)
247+
248+
> 🛈 No files need to be mounted into the webserver, as content is coming from the websocket server.
249+
250+
1. Create a websocket server application
251+
```bash
252+
# Create source directory
253+
mkdir -p src
254+
255+
# websocket server application
256+
cat << EOF > src/index.js
257+
const WebSocket = require("ws");
258+
const wss = new WebSocket.Server({ port: 3000 });
259+
wss.on("connection", (ws) => {
260+
ws.send("hello client, you are connected to me");
261+
ws.on("message", (message) => {
262+
console.log("New message from client: %s", message);
263+
});
264+
});
265+
console.log("WebSocket server ready at localhost:3000");
266+
EOF
267+
268+
# package.json
269+
cat << EOF > src/package.json
270+
{
271+
"name": "node-websocket-example",
272+
"version": "1.0.0",
273+
"main": "index.js",
274+
"devDependencies": {},
275+
"scripts": {
276+
"test": "echo \"Error: no test specified\" && exit 1"
277+
},
278+
"keywords": [],
279+
"author": "",
280+
"license": "ISC",
281+
"description": "",
282+
"dependencies": {
283+
"ws": "^7.5.1"
284+
}
285+
}
286+
EOF
287+
288+
# Startup script
289+
cat << EOF > src/start.sh
290+
#!/bin/sh
291+
npm install
292+
node index.js
293+
EOF
294+
```
295+
2. Start the Websocket server container
296+
```bash
297+
docker run -d -it \
298+
--name websocket \
299+
-v $(pwd)/src:/app \
300+
-w /app \
301+
node:19-alpine sh start.sh
302+
```
303+
3. Start Reverse Proxy
304+
```bash
305+
docker run -d -it \
306+
-p 80:80 \
307+
-e MAIN_VHOST_BACKEND='conf:rproxy:ws:websocket:3000' \
308+
--link websocket \
309+
devilbox/nginx-stable
310+
```
311+
4. Verify
312+
```bash
313+
# On your host system
314+
npm install -g wscat
315+
wscat --connect localhost
316+
317+
Connected (press CTRL+C to quit)
318+
< hello client, you are connected to me
319+
>
320+
```
321+
322+
323+
240324
## 💡 Fully functional LEMP stack with Mass vhosts
241325
242326
The following example creates a dynamic setup. Each time you create a new project directory below `www/`, a new virtual host is being created.

doc/features.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,9 @@ Reverse Proxies are configured in a similar way to how PHP-FPM is setup as a rem
9494
```bash
9595
MAIN_VHOST_BACKEND:conf:rproxy:<protocol>:<server-addr>:<server-port>
9696
```
97-
Where `<procotol>` can by one of `http` or `https` (depending what your backend provides. `<server-addr>` and `<serer-port>` specify the hostname, IPv4 or IPv6 address of your upstream server, followed by its TCP port.
97+
Where `<procotol>` can by one of `http`, `https`, `ws` or `wss` (depending what your backend provides. `<server-addr>` and `<serer-port>` specify the hostname, IPv4 or IPv6 address of your upstream server, followed by its TCP port.
98+
99+
**Note:** When specifying `ws` or `wss`, the webserver will automatically be configured to be capable of communicating with web sockets.
98100

99101

100102

0 commit comments

Comments
 (0)